Skip to Content
ReferenceConfiguration

Configuration

Donkey.from_env() resolves configuration from, in precedence order: explicit kwargs → environment variables → .donkey-kit.toml → defaults.

Governed model access

The three required values for the LLM proxy:

Env varMeaning
DONKEY_LLM_PROXY_URLProxy base URL: https://<ingress-gw>/<instance>/ — no /v1.
DONKEY_LLM_PROXY_CLIENT_IDConsumer client ID (the per-agent identity).
DONKEY_LLM_PROXY_CLIENT_SECRETConsumer client secret.

Auth is a client_id / client_secret header pair (consumer auth), not a bearer token, and separate from any Anypoint control-plane credential. The OpenAI SDK still requires a non-empty api_key slot, which the proxy ignores.

The stock gateway also accepts a single colon-joined header — authorization: Bearer <client_id>:<client_secret> or apikey: <client_id>:<client_secret> — which its dataweave-headers-transformation policy splits back into the pair. DDK doesn’t use that form: it always sends the two-header pair, because client_id is the per-agent attribution unit. The colon-joined value is not an alternative once a client_id header is present — the policy ignores it.

Missing required fields are reported all at once with their env-var names, so you can fix configuration in a single pass.

Optional env varDonkeyConfig fieldMeaning
DONKEY_LLM_PROXY_KEYllm_proxy_keyFills the OpenAI SDK’s mandatory api_key slot. The proxy ignores it, so leave it unset unless a tool insists on a real-looking value.

JWT / model-wallet auth mode

A model-wallet proxy identifies the caller from an IdP-issued JWT plus a durable wallet-selector client ID, with Client ID Enforcement disabled and no client_secret. Select it with DONKEY_LLM_PROXY_AUTH=jwt:

Env varDonkeyConfig fieldMeaning
DONKEY_LLM_PROXY_AUTHllm_proxy_authData-plane auth mode: client-id (default) or jwt.
DONKEY_LLM_PROXY_WALLET_CLIENT_IDllm_proxy_wallet_client_idThe wallet’s system-generated client ID, sent as the X-Client-Id header. Required in jwt mode.

In jwt mode the required fields are llm_proxy_url and llm_proxy_wallet_client_id — not client_id / client_secret. The rotating JWT is not a config value: supply it through an AuthProvider passed as Donkey(llm_auth=…), so the SDK can re-fetch it as it rotates and refresh it once on a 401:

from donkey_kit import Donkey, DonkeyConfig from donkey_kit.core.auth import StaticToken # or your own rotating AuthProvider donkey = Donkey( DonkeyConfig( llm_proxy_url="https://<ingress-gw>/<instance>/", llm_proxy_auth="jwt", llm_proxy_wallet_client_id="<wallet-client-id>", ), llm_auth=StaticToken("<jwt>"), # rides as Authorization: Bearer <jwt> )

jwt mode is async-only — the rotating credential is fetched from an async AuthProvider, so the blocking client (sync=True) is refused with an actionable error. Use client-id auth for a synchronous caller. It also works only for adapters that use the SDK’s shared HTTP client (the raw client and LangGraph). Frameworks given a one-time default_headers snapshot (ADK, CrewAI, LlamaIndex, MS Agent Framework) pin the token at construction and can’t refresh it — see Testing.

Auth providers

An AuthProvider (in donkey_kit.core.auth) is any object with two async methods: token() returns the current credential and invalidate() drops a cached one. The transport calls invalidate() and retries exactly once when a downstream call returns 401.

ProviderUse it for
StaticToken(token)A token injected out-of-band, for example from CI. Never refreshes.
AnypointConnectedApp(client_id=…, client_secret=…, control_plane_url=…, http_client=…)OAuth2 client credentials against the Anypoint token endpoint. Caches the token in memory and refreshes it 60 seconds before expiry.
ChainedAuth(*providers)Tries providers in order; the first that yields a token wins.

For a rotating JWT from your IdP, implement the two methods yourself and pass the object as llm_auth.

Optional attribution

Env varMeaning
DONKEY_APP_NAMEHuman-readable app name, surfaced on telemetry.
DONKEY_BUSINESS_GROUPBusiness group for attribution.

Correlation headers

Per-call and per-run correlation IDs ride on request headers. The gateway’s inbound header names aren’t published, so the SDK uses placeholder names you can override to match your gateway. The IDs also appear on spans and exceptions regardless of the header names. See Telemetry & cost.

Env varDonkeyConfig fieldMeaning
DONKEY_CORRELATION_HEADERcorrelation_headerRequest header that carries the per-run correlation ID.
DONKEY_CALL_ID_HEADERcall_id_headerRequest header that carries the per-call ID.

Cost-attribution tags

A fixed set of dimensions set once and emitted on every call (both as request headers and as donkey.cost.* span attributes). Override them per run with donkey.run(team=…, project=…, env=…, enduser_id=…). The key set is fixed — an unknown dimension is a configuration error, not a silently dropped tag. See Telemetry & cost.

Env varDonkey.from_env kwargMeaning
DONKEY_COST_TEAMteamOwning team.
DONKEY_COST_PROJECTprojectProject / workload.
DONKEY_COST_ENVenvDeployment environment (e.g. prod).
DONKEY_COST_ENDUSER_IDenduser_idEnd-user ID (the enduser.id tag).

In .donkey-kit.toml these live under a [donkey.cost] table (the end-user dimension keeps its dotted key):

[donkey.cost] team = "support" project = "triage-v2" env = "prod" "enduser.id" = "user-42"

The request-header names the gateway reads for these tags aren’t published, so the SDK uses placeholder names you can override to match your gateway: DONKEY_COST_TEAM_HEADER, DONKEY_COST_PROJECT_HEADER, DONKEY_COST_ENV_HEADER, DONKEY_COST_ENDUSER_HEADER (or the matching cost_*_header config keys). The donkey.cost.* span attributes carry the full value regardless.

Telemetry

Env varDonkey.from_env kwargMeaning
DONKEY_TELEMETRYtelemetryEmit OTel spans at all (default true).
DONKEY_TELEMETRY_CAPTURE_CONTENTtelemetry_capture_contentPut prompt/completion text on spans (default false).

telemetry_capture_content defaults to false on purpose: spans are emitted inside your process, upstream of the gateway’s PII masking, so capturing content re-exports the very text the platform masks. Enable it only for a trusted collector. See Telemetry & cost.

Behaviour

Env varDonkeyConfig fieldDefaultMeaning
DONKEY_TIMEOUT_Stimeout_s60.0HTTP timeout for governed calls, in seconds.
DONKEY_MAX_RETRIESmax_retries3Retries for transient upstream failures (502 / 503 / 504) with backoff. Policy refusals are never retried, and a gateway fallback is never retried twice.
DONKEY_ON_MODEL_SUBSTITUTIONon_model_substitutionoffoff surfaces a model substitution on donkey.last_call; raise turns it into ModelSubstituted. See Telemetry & cost.
DONKEY_REGISTRY_CACHE_TTL_Sregistry_cache_ttl_s300How long registry lookups (used by tool access) are cached in memory, in seconds.
DONKEY_NO_CACHE—unsetSet to 1, true or yes to bypass that in-memory registry cache.

Anypoint control plane

A separate credential from the LLM proxy, used by features that call the Anypoint control plane (for example, the connected-app token and the CLI). You don’t need these for governed model access.

Env varMeaning
ANYPOINT_CLIENT_IDConnected-app client ID.
ANYPOINT_CLIENT_SECRETConnected-app client secret.
ANYPOINT_ORG_IDAnypoint organization ID.
ANYPOINT_ENVAnypoint environment (default Sandbox).
ANYPOINT_REGIONControl-plane region: us (default), eu, ca, or jp.
ANYPOINT_BASE_URLExplicit control-plane base URL; overrides the region.

Config file

Instead of env vars you can put non-secret values in a [donkey] table in .donkey-kit.toml, read from the working directory (or $XDG_CONFIG_HOME). Keys are the DonkeyConfig field names:

[donkey] llm_proxy_url = "https://<ingress-gw>/<instance>/" llm_proxy_client_id = "…"

donkey init generates this file from your current environment. Keep secrets (llm_proxy_client_secret, client_secret) out of the committed file and supply them as environment variables.

Programmatic

from donkey_kit import Donkey, DonkeyConfig # Explicit config (kwargs win over env): donkey = Donkey(DonkeyConfig( llm_proxy_url="https://<ingress-gw>/<instance>/", llm_proxy_client_id="…", llm_proxy_client_secret="…", )) # Or from the environment, with lifecycle: async with Donkey.from_env() as donkey: ...
Last updated on