Config Fields and Settings¶
The configuration is described by AgentConfig and stored on disk at $XUN_HOME/config.json.
Every agent receives a clone of the global configuration, so runtime changes affect only that agent and are never written back to the file.
Location and loading¶
flowchart LR
T["Built-in template<br/>with ${XUN_*} placeholders"] --> M["Deep merge<br/>config.json"]
F["$XUN_HOME/config.json"] --> M
M --> S["Environment variable substitution"]
S --> C["AgentConfig"]
C --> A1["agent.config clone"]
C --> A2["Sub-agent clone"]
- When
XUN_HOMEis unset it defaults to./.xun, so the config file is./.xun/config.json. - It is loaded once per process (
lru_cache); after changingXUN_HOMEyou needload_config(force_reload=True). load_dotenv()is called before the file is read; by default it does not overwrite existing environment variables.- The file only needs the fields you want to change. Dictionaries merge recursively, lists and scalars are replaced wholesale —
if you write only
{"model": {"name": "x"}},model.capabilitieskeeps the template value; to clear it you must write"capabilities": []. - Every model uses
extra="forbid": a misspelled field name fails at startup instead of being silently ignored. - When the file does not exist the template is used directly, and
XUN_OPENAI_BASE_URLandXUN_OPENAI_API_KEYmust then be present in the environment.
Environment variable placeholders¶
Strings in the template are string.Template patterns, so both ${XUN_OPENAI_API_KEY} and $XUN_OPENAI_API_KEY work ($$ escapes). Rules:
- A placeholder identifier must start with
XUN_, otherwise startup fails with an error. - When a variable is missing, a built-in fallback table is consulted first; if there is no fallback, it is an error:
| Variable | Fallback when missing |
|---|---|
XUN_OPENAI_MODEL |
"" (triggers model auto-detection) |
XUN_AUTO_CONFIRM |
"false" |
XUN_ENABLE_EXTENSIONS |
"true" |
XUN_OPENAI_BASE_URL / XUN_OPENAI_API_KEY |
No fallback; missing means an error |
- Substitution happens before
json.loads, so a placeholder may appear at any position inside a string (including insideextension_settings). Conversely, a value must not contain quotes, backslashes, or newlines, or it will break the JSON.
The built-in mappings:
| Environment variable | Affected field |
|---|---|
XUN_OPENAI_BASE_URL |
provider.openai_base_url |
XUN_OPENAI_API_KEY |
provider.openai_api_key |
XUN_OPENAI_MODEL |
model.name |
XUN_AUTO_CONFIRM |
auto_confirm |
XUN_ENABLE_EXTENSIONS |
enable_extensions |
XUN_HOME |
Root location of config, extensions, and data directories (not a config field) |
Extensions use the same mechanism
Placeholder substitution applies to the merged JSON as a whole, so ${XUN_*} also works inside an extension's config bucket —
secrets stay in the environment instead of in the config file.
Field reference¶
| Field | Type | Default | Description |
|---|---|---|---|
auto_confirm |
bool | ${XUN_AUTO_CONFIRM} → false |
Every confirmation picks the default option without asking the user. /yolo toggles it at runtime |
auto_compact.enabled |
bool | true |
Master switch for automatic compaction |
auto_compact.token_threshold |
int | 192000 |
Token threshold that triggers compaction; the value compared is the total reported by the most recent model call |
provider.openai_base_url |
str | ${XUN_OPENAI_BASE_URL} |
OpenAI-compatible endpoint |
provider.openai_api_key |
str | ${XUN_OPENAI_API_KEY} |
API key |
model.name |
str | ${XUN_OPENAI_MODEL} → "" |
Model name; when the resolved value is an empty string, initialize() takes the first entry of models.list() |
model.capabilities |
set | ["vision"] |
Capability gating; currently only "vision". Decides whether tools carrying required_capabilities are exposed |
model.temperature |
float | None | None |
When None, it does not appear in the request |
model.reasoning_field |
str | None | None |
Field name for reasoning text; None means auto-detect on first appearance (reasoning / reasoning_content) |
model.reasoning_effort |
str | None | None |
none / minimal / low / medium / high / xhigh / max; some models accept only part of this set |
enable_extensions |
bool | ${XUN_ENABLE_EXTENSIONS} → true |
Whether extensions run at each agent initialization; automatically disabled for internal helper agents |
load_project_instructions |
bool | true |
Whether to load AGENTS.md from the working directory as a separate section of the system prompt |
extension_settings |
dict[str, dict] | {} |
Configuration bucketed per extension name; extensions read it through ctx.settings |
Internal agents modify their own config
The conversation-summary agent turns off auto_compact and enable_extensions; the command risk-assessment agent likewise disables extensions.
These changes happen only on their cloned configs.
Reading and writing at runtime¶
print(agent.config.to_json_str()) # JSON indented with 4 spaces
agent.config.model.name = "my-model" # validate_assignment=True; a wrong type errors immediately
In a session, /config is the counterpart: with no arguments it prints the current configuration, and with key.sub=value it changes a single value (without writing to disk).
load_config() returns the resolved global template — to diagnose what one agent actually uses, read agent.config.
How the compaction threshold behaves¶
auto_compact.token_threshold only decides "when compaction starts"; the strategy itself lives on AutoCompactor:
old tool results are reclaimed first (no API call spent), and only if that is not enough does the summary agent write a summary that is placed into the system prompt.
The tunables (toolcall_keep_max=12, summary_keep_max=16, escalation_rounds=2, max_retries=2)
are fields of AutoCompactor, not entries in the config file; replace agent.compactor when you need to change them.
What is not in the config¶
The following are often mistaken for config fields:
- Maximum iterations: a parameter of
execute(max_iterations=…), default 512. - Retries and timeouts: hard-coded in the loop (at most 3 retries, exponential backoff, 900-second streaming timeout).
- Display layer and web service parameters: constructor parameters of
Display/WebDisplay/WebDisplayService, plus CLI arguments. - Command and path allow lists: runtime state of the current agent, managed with
/policy. - Containers and multi-user: command-line arguments of
xunc/xunx.