Plugin bindings in manifests¶
How an agent spec names a plugin and passes its parameters. Applies to
every cardinality-one slot (design_pattern, context_manager, assembler,
memory shorthand) and to list slots (governance, observability,
context_sources).
Schema: docs/schemas/runtime/agent.schema.yaml · Code:
mas.runtime.spec.plugin_binding.normalize_plugin_binding
Omitting a slot, writing the plugin name, and writing the full object with
schema defaults are the same runtime behaviour. mas-ctl compile prints
the full object so you can diff it — see
Compiled agent defaults for a worked example
(Tutorial 1's minimal manifest, compiled).
Two shapes¶
1. Singleton slot (one plugin)¶
The spec key is the role (design_pattern, context_manager, assembler).
The value is the plugin name, optionally with parameters.
String shorthand and object form are equivalent:
# shorthand — plugin name only
spec:
design_pattern: cot # ≡ {type: cot} (allowed)
context_manager: summarising
assembler: assembler
memory: semantic
There is no _plugin suffix on spec keys. Registry type names match the slot
(design_pattern, context_manager, assembler). Sub-plugins (today:
context_manager.params.summarizer) use the same shorthand:
summarizer: llm ≡ {type: llm}.
params (alias config on design_pattern only) are constructor/kernel
kwargs. ref is the long locator (mas.cm.stack, module://…) when you are
not using a short name.
2. List slot (several plugins)¶
The spec key is still the role. Each list item is the plugin name, either bare or as a one-key map of parameters:
spec:
governance:
- sample_governance:
hitl_on_tool: true
hitl_mode: interactive
- no_undeclared_tool
- retry_on_error:
error_recovery_plugin: retry_on_error
error_policy:
transient: retry
fatal: block
observability:
- native
YAML fields such as error_recovery_plugin and error_policy may appear
on any governance stanza; the parser flattens them and installs the
recovery plugin on the ingress chain (not on KernelConfig).
Full chain: governance.md. Retry defaults:
reliability.md.
Default for every list slot is empty (no plugins). Native observability is
attached by the flavour / CLI, not by omitting spec.observability.
Package defaults and equivalent explicit config¶
Omitted fields are filled from defaults.yaml (overridable in workspace
config.yaml defaults:). Compile writes the object form below.
design_pattern (default react)¶
Omit the field, write design_pattern: react, or:
spec:
design_pattern:
type: react # aliases: react@v1
params:
max_steps: 512 # optional kernel dispatch cap (omit = no cap)
max_cot_pass: 1 # extra CoT refinement passes
parallel: true # parallel tool calls
design_pattern: cot is the same shape with type: cot (same default
params). Other shipped ids: single_pass, introspection, plan_execute,
tree_of_thoughts, deterministic_single, deterministic_linear,
deterministic_parallel.
| Param | Maps to | Default | Who uses it |
|---|---|---|---|
max_steps |
KernelConfig.max_auto_steps |
none | every pattern (loop cap; with-hardened sets 512) |
max_cot_pass |
KernelConfig.max_cot_pass |
1 | cot, introspection, tree_of_thoughts (min 2 internally) |
parallel |
KernelConfig.parallel_tool_calls |
true | react and tool-calling patterns |
assembler (default assembler)¶
spec:
assembler:
type: assembler # aliases: context-assembler, ctx-assembler
params:
emit_segments: true
always_reassemble: false
# token_budget: omit = no part-eviction budget
One shipped assembler (ContextAssemblerPlugin). History policy is
not assembler params; it is spec.context_manager.
context_manager (default summarising)¶
Each manager is a plugin with strategy code (not an empty shell).
spec:
context_manager:
type: summarising
params:
keep_turns: 10
hysteresis_ratio: 0.1
summarizer: llm # sub-plugin; ≡ {type: llm}. Alternative: drop
# summarizer: {type: llm, params: {model: gpt-4o-mini}} # cheaper summary LLM
working_memory_messages: 20
trimmer:
reserve_tokens: 2000 # effective completion budget
safety_margin_ratio: 0.1
sliding-window equivalent: {type: sliding-window, params: {keep_turns: 10}}
(older turns dropped, no summarizer). stack equivalent: {type: stack}
(optional max_messages). Full examples: context-assembly.md.
summarizer (sub-plugin of summarising)¶
Not a top-level spec key. Registry type summarizer, composed by the
summarising context manager:
| Plugin | Default? | Behaviour |
|---|---|---|
llm |
yes | summarizer slot (Agent → MAS → experiment.models.summarizer) else agent's resolved turn model (summarize_messages); optional params.model (a spec.models[].id or LiteLLM string) uses a different model; degrades to drop without a live engine |
drop |
discard older turns; keep keep_turns verbatim |
# default (inside summarising) — summarizer slot else this agent's turn model
params:
summarizer: llm # ≡ {type: llm}
# cheaper / dedicated summarizer
params:
summarizer:
type: llm
params:
model: gpt-4o-mini # or a spec.models[].id such as summarizer
# instructions: | # optional; default is the package system prompt
# Preserve city names and dates.
# explicit drop
params:
summarizer: drop # ≡ {type: drop}
Thresholds, prompt, logs, MCE judge: summarization.md. Example: summarizer-override. Card: summarizer.md.
memory¶
Shorthand memory: semantic ≡ plugin semantic. Full object form is
memory.types[] (see agent.md). Absent → flavour decides.
List plugins¶
| Slot | Default | Shipped plugins |
|---|---|---|
governance |
[] |
sample / sample_governance, gov_no_undeclared_tool, retry_on_error |
observability |
[] (flavour/CLI may attach native) |
native, otel |
context_sources |
[] |
native, adk, langchain (skill engines) |
providers |
[] (implicit local owns spec.tools) |
local |
Compaction¶
spec.working_memory.compaction is sugar for spec.context_manager.
The context manager owns recency: manage_history bounds the LLM view, and
after each turn commit the same cap is written back to committed_messages
and conversation chunks (folded prefix data is dropped). Hysteresis on the
context-manager instance avoids a summarizer LLM call on every in-turn step.
Prefer spec.context_manager. If both are set, context_manager wins.
compaction.model (strategy summarize) is sugar for
summarizer.params.model — summarization.md.
stack with no max_messages has no recency cap. Set max_messages, or
use the default summarising / sliding-window plugins.
Overlay merge¶
Singleton plugin slots (design_pattern, context_manager, assembler)
use plugin_binding_merge:
- A string overlay (
context_manager: stack) replaces the binding. - Same
type/ref(or a params-only patch) deep-mergesparams(nested maps keep sibling keys: patchingtrimmer.reserve_tokensdoes not droptrimmer.max_tokens). - A
type/refchange replaces the binding — leftover constructor kwargs from the previous plugin are dropped.
On design_pattern, params wins over the legacy config alias when both
are present.
# base
spec:
context_manager:
type: summarising
params: {keep_turns: 10}
# overlay — type change drops keep_turns
spec:
context_manager:
type: stack
# result: {type: stack}
# overlay — same type keeps and patches params
spec:
context_manager:
params: {hysteresis_ratio: 0.3}
# result: {type: summarising, params: {keep_turns: 10, hysteresis_ratio: 0.3}}
# overlay — nested params keep siblings
spec:
context_manager:
params:
trimmer: {reserve_tokens: 4000}
# result trimmer: {max_tokens: 128000, reserve_tokens: 4000} (if base had both)
A slot that is not a plugin name or {type, ref, params} object is a hard
error (PluginBindingError) at mas-ctl compile/validate, including
when compile runs with --no-validate — authoring is the validation
boundary, so this always fails loudly there.
The kernel's own runtime read of an already-compiled manifest is lenient by
design (normalize_plugin_binding_lenient): a malformed value that reached
the runtime anyway (a manifest built by hand in a test or a direct
embedding, bypassing mas-ctl) is treated as omission — the slot's platform
default is used — rather than failing every turn. Author your manifests
through mas-ctl compile/validate and you'll never see this distinction;
it only matters if you construct a manifest dict yourself.
Related¶
- Compiled agent defaults — Tutorial 1's minimal manifest, fully expanded
- agent.md — every agent spec field
- context-assembly.md — assembler, context managers, summarizers
- summarization.md — thresholds, summarizer/judge model overrides, logs
- runtime/docs/agent-defaults.md
- plugins-reference.md — catalog of registered plugins