Repository navigation
Description
Summary
DonkeyConfig is the single frozen dataclass every other module reads. Two
behaviours matter more than the field list:
Resolution order (§2.1): explicit kwarg → env var → .donkey-kit.toml
(cwd or $XDG_CONFIG_HOME) → default. We never read .env implicitly;
document that the user calls load_dotenv() themselves.
validated() reports every missing field at once. A config error that
surfaces one missing variable per run is the most common source of
first-five-minutes abandonment, so this is a correctness requirement, not a
nicety.
The control-plane credential and the LLM-proxy credential are deliberately not
conflated (§2.2) — a developer may legitimately have proxy access and no
Exchange access — so validated(need=...) takes "control_plane" or "llm" and
only checks that capability's fields.
Current state — built
Implemented in python/src/donkey_kit/core/config.py. Field set reflects the
live-verified proxy contract: the proxy authenticates on a
client_id/client_secret request-header pair, not a bearer token, so the
config carries llm_proxy_client_id / llm_proxy_client_secret, and
llm_proxy_key exists only to fill the OpenAI SDK's mandatory api_key slot.
Python
from donkey_kit import Donkey, DonkeyConfig
from donkey_kit.core.errors import ConfigError
# 1. Env-driven, the normal path.
cfg = DonkeyConfig.from_env()
# 2. Explicit, overriding the environment.
cfg = DonkeyConfig(
llm_proxy_url="https://ingress-gw-abc.usa-e2.cloudhub.io/openai-sdk/", # no /v1
llm_proxy_client_id="…",
llm_proxy_client_secret="…",
application_name="checkout-agent",
business_group="payments",
timeout_s=30.0,
max_retries=5,
)
# 3. Derived copy, e.g. to point one call at another environment.
prod = cfg.with_overrides(environment="Production")
# 4. Validation names EVERY missing field, with its env var, in one raise.
try:
DonkeyConfig().validated(need="llm")
except ConfigError as e:
print(e)
# Configuration for 'llm' is incomplete. Missing:
# - llm_proxy_url (env MULESOFT_LLM_PROXY_URL)
# - llm_proxy_client_id (env MULESOFT_LLM_PROXY_CLIENT_ID)
# - llm_proxy_client_secret (env MULESOFT_LLM_PROXY_CLIENT_SECRET)
donkey = Donkey(cfg).donkey-kit.toml, committed to the repo — only keys that are real
DonkeyConfig fields are accepted, so a typo is dropped rather than silently
misapplied:
[donkey]
environment = "Sandbox"
region = "us"
application_name = "checkout-agent"
business_group = "payments"
registry_cache_ttl_s = 600TypeScript
import { Donkey, DonkeyConfig, ConfigError, loadConfig } from "@donkey-kit/core";
// 1. Env-driven.
const cfg = loadConfig();
// 2. Explicit. Same resolution order: arg > env > .donkey-kit.toml > default.
const explicit = new DonkeyConfig({
llmProxyUrl: "https://ingress-gw-abc.usa-e2.cloudhub.io/openai-sdk/",
llmProxyClientId: "…",
llmProxyClientSecret: "…",
applicationName: "checkout-agent",
businessGroup: "payments",
timeoutMs: 30_000,
maxRetries: 5,
});
// 3. Validation is one throw listing everything, matching Python.
try {
new DonkeyConfig({}).validated("llm");
} catch (e) {
if (e instanceof ConfigError) console.error(e.message);
// Configuration for 'llm' is incomplete. Missing:
// - llmProxyUrl (env MULESOFT_LLM_PROXY_URL)
// - llmProxyClientId (env MULESOFT_LLM_PROXY_CLIENT_ID)
// - llmProxyClientSecret (env MULESOFT_LLM_PROXY_CLIENT_SECRET)
}
const donkey = new Donkey(explicit);The TS port must keep the same env var names so a repo can run a Python agent
and a TS agent off one .env, and expose camelCase fields with the snake_case
env vars — do not invent LLM_PROXY_URL-style aliases.
Acceptance criteria
- Resolution order kwarg → env → toml → default
-
.envnever read implicitly -
validated()reports all missing fields for the requested capability at once - Unknown
regionraisesConfigErrornaming the valid set - Malformed
.donkey-kit.tomlraises; a missing one is fine - Unknown toml keys are ignored rather than applied
- TypeScript port with identical env var names and error text
- Docs page enumerating every field, its env var and its default
Blocked on
region only resolves us today. EU / CA / JP Hyperforce host variants are
UNVERIFIED — see Verify Anypoint control-plane region hosts for EU, CA and JP.
References
python/src/donkey_kit/core/config.py,python/tests/unit/test_config.py- Build plan §2.1
Activity
amirkhan-ak-sf commentedon Sep 4, 2026
Remapped by the phase-based backlog rebuild.
FabricConfig resolution order and all-at-once validation survive unchanged — build guide 1.1 explicitly keeps them.
[-]core/config: FabricConfig resolution order and all-at-once validation[/-][+]core/config: DonkeyConfig resolution order and all-at-once validation[/+]tommasobolis commentedon Sep 20, 2026
Closing: the Phase-1 Python deliverable is implemented and tested in core/config.py (from_env() resolution order, all-at-once validated(need=...), unknown-region/malformed-toml raises, unknown-key drop) with tests/unit/test_config.py green, and website/content/reference/configuration.mdx documents the fields. The only unchecked item is the TypeScript port, which is Phase 5 (0.1.0 does not ship TS) — not a Phase 1 blocker.