Configuration mixins
Mixins are named reusable configuration fragments for providers, agents, and other mixins.
Basic use
{
"mixins": {
"portable-system-message": {
"system_message": {
"variables": {
"AGENTS": {
"text": "${file:${env:WORKING_DIR}/AGENTS.md}"
}
}
}
},
"openai-base": {
"mixin_refs": ["portable-system-message"],
"provider": "openai_compatible",
"model": "gpt-5-mini"
}
},
"providers": {
"openai": {
"mixin_refs": ["openai-base"],
"api_key": "${env:OPENAI_API_KEY}"
}
},
"agents": {
"default": {
"provider": "openai",
"system_message": {
"template": "{{AGENTS}}"
}
}
}
}
Keys
Top-level keys:
mixins: mapping of mixin ID to config fragment;mixin_policy.default_merge:shallowby default ordeep;mixin_policy.max_depth: positive recursion limit, default16.
Provider, agent, and mixin mappings may use:
mixin_refs: ordered list of mixin IDs;mixin_merge: compatibility spelling for a rootshallowordeepmerge;$merge: recursive merge policy.
Precedence
- Referenced mixins are resolved recursively.
- References are applied in
mixin_refsorder. - Later references override earlier references.
- Local mixin/provider/agent values override referenced values.
- Agent configuration overlays provider configuration.
Missing references, cycles, invalid merge policies, and excessive recursion are startup errors.
Merge modes
Shallow merge replaces a colliding direct value. If both mappings contain
request_options, the overlay's complete request_options value replaces the
base value.
Deep merge recursively merges colliding mappings. Arrays and scalar values still replace.
String form:
{
"$merge": "deep",
"request_options": {
"temperature": 0.2
}
}
Parent-scoped object form:
{
"$merge": {
"default": "deep",
"shallow": ["request_options"],
"deep": ["headers"]
},
"request_options": {
"thinking": {
"type": "adaptive"
}
},
"headers": {
"x-feature": "enabled"
}
}
The lists name direct sibling keys:
request_optionsuses shallow merge and replaces the complete colliding value;headersuses deep merge;- other keys use
default.
Nested mappings can define another policy for their children:
{
"$merge": "deep",
"request_options": {
"$merge": {
"default": "deep",
"shallow": ["thinking"]
},
"thinking": {
"type": "adaptive",
"display": "summarized"
},
"output_config": {
"effort": "high"
}
}
}
Key lists use direct names, not dotted paths. One key cannot appear under both
shallow and deep.
Compatibility
Existing configurations can continue using:
{
"mixin_merge": "deep"
}
At a provider, agent, or mixin root this is equivalent to:
{
"$merge": "deep"
}
If both forms are present, they must specify the same string mode.
Arrays
Arrays replace in shallow and deep modes. They are not recursively interpreted for mixins, variants, or merge controls.