Configuration
The SDK is configured with environment variables. Every setting has a default except your key and team id. Run hajer doctor to see each setting's value and whether it came from the environment or the default.
Settings
Identity
| Variable | Default | Meaning |
|---|---|---|
HAJER_API_KEY | unset | Your team API key. Without it the SDK is inert. |
HAJER_TEAM_ID | unset | The team traces belong to. Without it the SDK is inert. |
HAJER_BASE_URL | https://api.hajer.ai | The Hajer API. Change it only for a local or self-hosted platform, for example http://localhost:8000. |
HAJER_ENVIRONMENT | unset | The environment this process runs in, such as production, staging or dev. Exported on every span as deployment.environment.name (and the older deployment.environment). |
HAJER_DISABLED | 0 | Makes the SDK inert whatever key is set. Does not stop export to a collector named by HAJER_OTLP_ENDPOINT. |
HAJER_ENVIRONMENT is lowercased. A value that is still not 1 to 64 lowercase letters, digits and dashes, starting with a letter or digit, is dropped without an error; hajer doctor shows it as ignored: invalid.
Export
| Variable | Default | Meaning |
|---|---|---|
HAJER_TRACES_ENABLED | 1 | Export to Hajer when a key is set. 0 sends nothing to Hajer; spans still go to your own tracer provider, if any. |
HAJER_MODEL_SPANS | 1 | Emit a span for each recorded model call. 0 when another instrumentation already traces your model calls. Declared spans are unaffected. |
HAJER_OTLP_ENDPOINT | OTEL_EXPORTER_OTLP_ENDPOINT, else unset | Your own OTLP/HTTP collector. Spans go to its /v1/traces instead of to Hajer. |
HAJER_OTLP_HEADERS | unset | Extra exporter headers, as key=value,key2=value2 (values percent-decoded). |
HAJER_SERVICE_NAME | OTEL_SERVICE_NAME, else OpenTelemetry's default | service.name on the provider the SDK builds when your application has none. |
HAJER_TRACE_EXPORT_TIMEOUT_MS | 5000 | Deadline of one export request. Also the longest an exit flush waits on an unreachable receiver. |
HAJER_TRACE_FLUSH_TIMEOUT_MS | 2000 | Default wait for hajer.flush(). |
HAJER_TRACE_BATCH_DELAY_MS | 5000 | How long a partial batch waits before it is exported. |
HAJER_TRACE_QUEUE_MAX | 2048 | Spans held for export before new ones are dropped. |
HAJER_TRACE_BATCH_MAX | 128 | Spans per export request. |
See Exporting spans.
Capture
| Variable | Default | Meaning |
|---|---|---|
HAJER_CAPTURE_CONTENT | 1 | Capture message text, answers, tool arguments and tool results. 0 keeps metadata and usage only. |
HAJER_REDACT_CLIENT | 1 | Redact sensitive values in your process before export. |
HAJER_CAPTURE_CALL_SITE | 1 | Record where each call was made and the provider endpoint. |
HAJER_PROJECT_ROOT | the working directory | The directory call-site file paths are made relative to. |
HAJER_CAPTURE_HTTP | 0 | Also record other outbound httpx requests as HTTP spans. |
HAJER_WRAPPED_CALL_MAX_BYTES | 32768 | Content one call may carry; longer texts are clipped in the middle. |
HAJER_BODY_MAX_BYTES | 65536 | Bytes of a raw response body buffered to read the answer. |
HAJER_WRAPPED_CALLS_MAX | 32 | Calls one task, or one hajer.scope(), keeps in memory for hajer.wrapped_calls(). Further calls are counted in wrapped_calls_dropped(). Does not limit spans. |
See Content capture and redaction.
Attach mode
| Variable | Default | Meaning |
|---|---|---|
HAJER_ATTACH | 0 | Read by import hajer.autoattach and the sitecustomize shim. With it on, the process is attached at startup. hajer.attach() in code ignores it. |
HAJER_CACHE_DIR and the HAJER_EVAL_* variables configure hajer eval; see Evals CLI.
Value formats
Booleans accept 1/0, true/false, t/f, yes/no, y/n and on/off, in any case.
Numbers must be positive integers.
Empty values. Surrounding whitespace is stripped, and an empty variable is treated as unset.
Invalid values
A variable that should be a boolean or a number but is not raises hajer.HajerConfigError when settings are read from the environment. That happens in:
hajer.wrap(),hajer.instrument()andhajer.attach()(when called withoutsettings=),hajer.CaptureTransport(...)andhajer.AsyncCaptureTransport(...),import hajer.autoattach,hajer.HajerSettings.from_env()andhajer doctor.
It is never raised during a model call. The error names the variable and what was expected, and withholds the value you supplied, since it might be a secret:
HAJER_INVALID_CONFIGURATION: HAJER_TRACE_QUEUE_MAX is not an integer; supplied value withheld
The span exporter reads the environment lazily, so it does not raise. It logs a warning on the hajer logger and runs on default settings instead.
Default settings include no API key, so while a variable is invalid the exporter sends nothing to Hajer. Fix the value, or run hajer doctor to find it.
A missing HAJER_API_KEY or HAJER_TEAM_ID is not an error: it makes the SDK inert.
Settings in code
hajer.HajerSettings holds every setting as a frozen object. HajerSettings.from_env() reads the environment; it is the only place the SDK reads environment variables.
import hajer
settings = hajer.HajerSettings.from_env()
print(settings.inert, settings.base_url)
You can also build settings yourself and pass them in. Field names are the variable names in lower case without the HAJER_ prefix, for example capture_content for HAJER_CAPTURE_CONTENT:
import hajer
from openai import OpenAI
settings = hajer.HajerSettings.from_env().model_copy(update={"capture_content": False})
hajer.configure(settings=settings) # span export and emission
client = hajer.wrap(OpenAI(), settings=settings) # what this client records
HajerSettings is a Pydantic model. Constructing it directly with an invalid value, such as HajerSettings(trace_queue_max=0), raises Pydantic's ValidationError, and unknown fields are rejected.
configure(settings=...) governs the span emitter. wrap, instrument, attach and CaptureTransport each take their own settings= argument and otherwise read the environment. Environment variables apply to all of them, so prefer them unless you need different settings in one process.