Configuration Reference¶
All orchestration settings live in a single config file (default: config/orchestration.yaml). Both YAML and JSON formats are supported. The file must have a top-level Orchestration key.
JSON:
YAML (.yaml or .yml):
Use any file extension and pass the path explicitly:
YAML is often more readable for configs with long agent instructions (block scalars avoid JSON escape sequences) or complex routing tables. Both formats bind to the same schema — every field documented below works identically in either format. See config/examples/orchestration.yaml for a complete YAML example.
Top-level fields¶
| Field | Type | Default | Description |
|---|---|---|---|
Name |
string | "" |
Human-readable name displayed at startup. |
Description |
string | — | Optional description shown at startup. |
Models |
object | {} |
Named model aliases reusable across agents. See Models. |
Agents |
array | [] |
Ordered list of agents. At least one is required. |
Selection |
object | sequential | Controls which agent speaks next. See Strategies. |
Termination |
object | 10 iterations | Controls when the run ends. See Strategies. |
Security |
object | unrestricted | Sandbox constraints for plugins. See Security. |
MaxCostUsd |
number | — | Hard USD spending cap. Run stops before the next turn if exceeded. |
McpServers |
array | [] |
External MCP servers to connect at startup. See MCP. |
Compaction |
object | — | Automatic history summarization. See Sessions. |
ChangeTracking |
object | — | Cross-agent change log. Enables the Changes plugin and validator cross-reference checks. See Change tracking. |
Events |
object | — | Structured JSONL event stream. See Events. |
Validation |
object | — | Routing validator settings. See Validators. |
Telemetry |
object | — | OpenTelemetry export settings. See Telemetry. |
Checkpoint |
object | — | Checkpoint storage settings. See Checkpoint. |
ApiProfiles |
object | {} |
Named API endpoint profiles (base URL, auth headers, timeout) for the Http plugin. See ApiProfiles. |
Agent configuration¶
Each entry in Agents configures one participant in the group chat.
- Name: Developer
Description: Senior engineer who implements features.
Instructions: You are a software engineer...
Model:
ModelId: gpt-4o
Plugins:
- FileSystem
- Shell
- Git
FunctionChoice: required
| Field | Type | Default | Required | Description |
|---|---|---|---|---|
Name |
string | — | yes | Unique name used in routing and logs. |
Instructions |
string | — | yes | System prompt defining the agent's persona and behavior. |
Description |
string | — | no | Short description used by LLM selection strategies. |
Model |
string or object | — | yes | Model to use. See Models. |
Plugins |
array | [] |
no | Built-in or MCP plugin names to load into this agent's kernel. See Plugins. |
FunctionChoice |
string | "auto" |
no | Tool-use enforcement: auto, required, or none. |
TrustScore |
number | 0.7 |
no | Governance trust score (0.0–1.0) used to assign an execution ring. See Governance. |
ContextWindow |
object | — | no | Filters the conversation history before it reaches this agent. See ContextWindow. |
FunctionChoice¶
| Value | Behavior |
|---|---|
auto |
The model may call tools or respond with text. Good for planning agents. |
required |
The model must call at least one tool every turn. Prevents fabricated tool output. Use for action agents (Developer, Tester). |
none |
Tools are registered but the model is not allowed to call them. |
ContextWindow¶
Filters the conversation history before it is passed to this agent each turn. Useful for late-stage agents (e.g. a Reviewer) that only need the final text output — not hundreds of tool-call frames accumulated by earlier agents.
Filters are applied in order: TextOnly / ExcludeAgents first, then MaxTailMessages. The shared history is never mutated — only the slice passed to this agent's turn is affected.
| Field | Type | Default | Description |
|---|---|---|---|
TextOnly |
bool | false |
Strip all tool-call frames and tool-result messages. Keeps only text-bearing assistant messages and user messages. |
ExcludeAgents |
array | [] |
Remove all messages (text and tool frames) authored by these agents. Tool-result messages are also stripped when this list is non-empty. |
MaxTailMessages |
int | 0 |
After the above filters, keep only the last N messages. 0 means no limit. |
TextOnly: true is the primary lever for context reduction. A Reviewer that independently re-reads files and re-runs commands gains nothing from hundreds of tool results produced by the Developer — stripping them can reduce input tokens by 90%+ in typical sessions.
ExcludeAgents goes further: removes an entire agent's contribution from the history. Use when one agent's output is irrelevant to another (e.g. a Planner's analysis is not useful to a code Reviewer).
MaxTailMessages provides a hard message count cap after the other filters. Useful when even filtered text history is still too long for a terminal agent.
Selection strategy¶
Selection:
Type: keyword
DefaultAgent: Planner
Routes:
- Keyword: "HANDOFF TO DEVELOPER"
Agent: Developer
Validator: RequireBrief
SourceAgents:
- Planner
- Keyword: "HANDOFF TO TESTER"
Agent: Tester
Validators:
- RequireWriteFile
- RequireShellPass
RequiredCommandPattern: "go build|go test"
SourceAgents:
- Developer
- Keyword: "HANDOFF TO REVIEWER"
Agent: Reviewer
Validator: TestReportValid
SourceAgents:
- Tester
- Keyword: BUGS FOUND
Agent: Developer
SourceAgents:
- Tester
- Keyword: REVISION REQUIRED
Agent: Developer
SourceAgents:
- Reviewer
- Keyword: REPLAN REQUIRED
Agent: Planner
SourceAgents:
- Reviewer
- Keyword: APPROVED
Agent: Reviewer
Validators:
- RequireShellPass
- RequireReviewJudgement
SourceAgents:
- Reviewer
| Field | Type | Default | Description |
|---|---|---|---|
Type |
string | "sequential" |
sequential, keyword, llm, structured, or magentic. |
Routes |
array | — | Required for keyword. List of keyword → agent mappings. |
StructuredRoutes |
array | — | Required for structured. List of condition → agent mappings. See Strategies. |
DefaultAgent |
string | first agent | Fallback agent when no keyword/condition matches (keyword and structured only). |
Prompt |
string | — | Custom prompt template for llm selection. |
Model |
object | — | Required for llm selection. |
Magentic |
object | — | Required for magentic selection. See MagenticManagerConfig below. |
KeywordRoute¶
| Field | Type | Default | Description |
|---|---|---|---|
Keyword |
string | — | Case-insensitive. Must appear alone on its own line in the response (after stripping */_ markdown). A keyword embedded in a sentence or used as a prose section header does not match. |
Agent |
string | — | Agent to activate when the keyword fires. When Agent matches one of SourceAgents, the route is terminal — the session ends. |
Validator |
string | — | Optional single validator name. Blocks the route until validation passes. Built-in: RequireBrief, RequireWriteFile, RequireAllFilesWritten, RequireShellPass, TestReportValid, RequireReviewJudgement. See Validators. |
Validators |
array | — | Optional multiple validators (AND semantics). Use instead of Validator when chaining checks (e.g. ["RequireWriteFile", "RequireShellPass"]). |
SourceAgents |
array | any | Optional. When set, the route only fires if the message author is in this list. Prevents agents from triggering routes that belong to other roles. Also determines terminal behavior — see Agent above. |
RequiredCommandPattern |
string | — | Optional. Used with RequireShellPass. The passing command must contain at least one pipe-separated substring (e.g. "go build\|go test"). |
RequireHumanApproval |
bool | false |
When true, the operator must explicitly approve (y) before the route fires. If rejected, the source agent is re-invoked with a "route blocked" message. See Human-in-the-loop. |
MagenticManagerConfig¶
Required when Selection.Type is magentic. Configures the manager LLM that drives the two-level planning and coordination loop.
Selection:
Type: magentic
Magentic:
Model:
ModelId: gpt-4o
MaxRoundCount: 20
MaxStallCount: 3
MaxResetCount: 2
EnablePlanReview: false
| Field | Type | Default | Description |
|---|---|---|---|
Model |
string or object | — | Required. Model for the manager LLM. A reasoning-capable model is strongly recommended. |
Instructions |
string | built-in | Optional system instructions. A sensible default is used when omitted. |
MaxRoundCount |
int | 20 |
Hard cap on inner-loop coordination rounds before the session terminates. |
MaxStallCount |
int | 3 |
Consecutive rounds without forward progress before a replan is triggered. |
MaxResetCount |
int | 2 |
Maximum number of replanning cycles. After this limit the session terminates. |
EnablePlanReview |
bool | false |
When true, pauses after the initial plan and waits for HITL review before starting coordination. |
Note: for magentic selection, the Termination section is ignored. Session end is controlled entirely by the three count fields above. See Strategies — magentic for full detail.
See Strategies for full detail.
Termination strategy¶
Termination:
Type: composite
MaxIterations: 40
Strategies:
- Type: regex
Pattern: \bAPPROVED\b
AgentNames:
- Reviewer
- Type: maxiterations
MaxIterations: 40
| Field | Type | Default | Description |
|---|---|---|---|
Type |
string | "composite" |
regex, maxiterations, or composite. |
Pattern |
string | — | Required for regex. Regex applied to message content. |
MaxIterations |
int | 10 |
Hard cap on agent turns (applies to all types as a safety net). |
AgentNames |
array | all agents | Optional: restrict regex check to these agents only. |
Strategies |
array | — | Required for composite. Stops when any child fires. |
See Strategies for full detail.
Security constraints¶
Security:
FileSystemSandboxPath: /home/user/projects/myapp
HttpAllowedHosts:
- api.github.com
- registry.npmjs.org
| Field | Type | Default | Description |
|---|---|---|---|
FileSystemSandboxPath |
string | — | Restricts FileSystem and Shell plugins to this directory tree. |
HttpAllowedHosts |
array | [] |
Hostname allowlist for the Http plugin. Empty = unrestricted (private IPs always blocked). |
AllowPrivateHosts |
bool | false |
Bypass the private/loopback IP check. For local dev and sandbox environments only — do not set in production. |
See Security for full detail.
Cost cap¶
The run stops before the next agent turn if the cumulative estimated cost exceeds this value. The session is saved and can be resumed. Pricing is estimated from a built-in model pricing table (or ~/.fuseraft/pricing.json if present).
Change tracking¶
When present, the orchestrator attaches a ChangeTracker to every agent's kernel. After each agent text turn it flushes a structured JSON entry recording exactly which tool calls completed: files written or deleted, shell commands run (with pass/fail status), and git commits made.
The log is consumed in two ways:
- Agents — add
"Changes"to a Tester or Reviewer agent'sPluginslist and callchanges_read_latestto see what the previous agent did. See Plugins. - Validators — set
Validation.ChangeLogPathto the same path to enable check 8 inTestReportValid(cross-referencing report commands against actually-run commands) and to allowRequireAllFilesWrittento count files written in prior turns.
| Field | Type | Default | Description |
|---|---|---|---|
Path |
string | .fuseraft/changes.json |
Path to write the change log. Relative paths resolve against the current working directory. |
Omit ChangeTracking entirely if you don't need cross-agent observability or the command cross-reference check.
Events¶
Emit a structured JSONL stream of session events to a file on disk:
Each line is a JSON object:
{ "ts": "2025-10-01T12:00:00Z", "session": "a3f92c1d", "agent": "Tester", "turn": 5, "event_type": "turn_end", "payload": { "input_tokens": 1200, "output_tokens": 340, "cost_usd": 0.0045 } }
{ "ts": "2025-10-01T12:00:02Z", "session": "a3f92c1d", "agent": "Developer", "turn": 6, "event_type": "validation_fail", "payload": { "validator": "RequireWriteFile", "consecutive": 1 } }
| Field | Description |
|---|---|
ts |
ISO-8601 UTC timestamp |
session |
Session ID |
agent |
Agent name (null for session-level events) |
turn |
1-based turn counter |
event_type |
One of: turn_end, validation_fail, hitl_escalation |
payload |
Event-specific JSON object |
turn_end payload: { input_tokens, output_tokens, cost_usd } — accumulated across all API calls within the turn.
validation_fail payload: { validator, consecutive } — name of the blocking validator and how many times in a row it has fired for this agent.
hitl_escalation payload: { message } — the error message surfaced to the user when a validator fires 3 consecutive times and the session stalls.
Omit Events if you don't need the event stream.
Conversation compaction¶
| Field | Type | Default | Description |
|---|---|---|---|
TriggerTurnCount |
int | 50 |
Compaction fires when message count reaches this value. Must be greater than KeepRecentTurns. |
KeepRecentTurns |
int | 10 |
Number of most-recent turns preserved verbatim after compaction. |
Model |
object | first agent's model | Model used for generating the summary. |
See Sessions for full detail.
Routing validators¶
Validation:
BriefPath: .fuseraft/brief.json
TestReportPath: .fuseraft/test-report.json
TestAssertionPatterns:
- tester::assert
- "if .+ throw"
- \bassert\b
- \bexpect\b
| Field | Type | Default | Description |
|---|---|---|---|
BriefPath |
string | .fuseraft/brief.json |
Canonical path for the project brief. Required by RequireBrief and TestReportValid. |
TestReportPath |
string | .fuseraft/test-report.json |
Canonical path for the test report. Required by TestReportValid. |
ChangeLogPath |
string | — | Path to changes.json produced by ChangeTracking (must match ChangeTracking.Path). Enables check 8 in TestReportValid and prior-turn file detection in RequireAllFilesWritten. |
TestAssertionPatterns |
array | see above | Regex patterns that identify real assertion calls in test files. |
See Validators for full detail.
Telemetry¶
Export traces and metrics to any OpenTelemetry-compatible backend (Jaeger, Grafana Tempo, Honeycomb, Datadog, etc.):
| Field | Type | Default | Description |
|---|---|---|---|
OtlpEndpoint |
string | "http://localhost:4317" |
OTLP gRPC endpoint for both traces and metrics. |
ServiceName |
string | orchestration Name |
Service name reported in trace/metric attributes. |
What is exported
Traces — one span per agent turn (agent.turn/<AgentName>), tagged with agent.name, model.id, turn.index, tokens.input, tokens.output, duration_seconds, and cost_usd. MAF internal AI spans are forwarded automatically via Microsoft.Agents.AI*.
Metrics
| Instrument | Type | Unit | Description |
|---|---|---|---|
fuseraft.agent.turns |
counter | — | Agent turns completed |
fuseraft.tokens.input |
counter | — | Total input tokens consumed |
fuseraft.tokens.output |
counter | — | Total output tokens produced |
fuseraft.agent.duration_seconds |
histogram | s | Wall-clock seconds per turn |
fuseraft.session.cost_usd |
histogram | USD | Estimated cost per turn |
All instruments carry agent.name and model.id attributes so you can slice by agent or model.
Quick start with Jaeger
Then add "Telemetry": { "OtlpEndpoint": "http://localhost:4317" } to your config and open http://localhost:16686.
Omit Telemetry entirely if you don't need OTel export.
Checkpoint¶
Controls where session checkpoints are stored. Checkpoints enable --resume and protect against losing progress if a session is interrupted.
| Field | Type | Default | Description |
|---|---|---|---|
Mode |
string | "json" |
"json" — write each checkpoint as an individual JSON file. "memory" — keep checkpoints in memory only; nothing is written to disk and --resume is unavailable. |
Path |
string | ~/.fuseraft/sessions/ |
Directory for checkpoint files (json mode only). Relative paths resolve against the working directory. Use a project-local path (e.g. .fuseraft/checkpoints) to keep checkpoints alongside the project instead of in the global user store. |
When to use a project-local path
By default, all sessions land in ~/.fuseraft/sessions/ regardless of which project they belong to. Setting Path to .fuseraft/checkpoints scopes sessions to the project directory:
fuseraft sessions(which always reads the global store) will no longer show these sessions unless you also set the path there — usefuseraft run --resumefrom the project directory instead- If you add
.fuseraft/checkpoints/to.gitignore, checkpoints stay local and off version control
When to use memory mode
Use "Mode": "memory" for short-lived or automated runs where persistence is not needed (e.g. CI pipelines, integration tests). The session runs normally but leaves no files behind.
Omit Checkpoint entirely to use the default (json mode, global ~/.fuseraft/sessions/ path).
ApiProfiles¶
Named API endpoint profiles that agents can reference via the profile parameter of any Http plugin function. A profile bundles a base URL, default headers, and a timeout so agents can make authenticated API calls without embedding credentials in their instructions.
ApiProfiles:
snow:
BaseUrl: "https://mycompany.service-now.com/api/now"
TimeoutSeconds: 60
DefaultHeaders:
Authorization: "Bearer ${SNOW_API_TOKEN}"
Accept: "application/json"
Content-Type: "application/json"
github:
BaseUrl: "https://api.github.com"
TimeoutSeconds: 30
DefaultHeaders:
Authorization: "token ${GITHUB_TOKEN}"
Accept: "application/vnd.github+json"
| Field | Type | Default | Description |
|---|---|---|---|
BaseUrl |
string | "" |
Base URL prepended to relative paths passed by agents. Absolute URLs passed by agents are used as-is. |
DefaultHeaders |
object | {} |
Headers merged into every request that uses this profile. Per-call headers override these on conflicts. Values support ${ENV_VAR} expansion (see below). |
TimeoutSeconds |
int | 30 |
Request timeout for this profile. Used when the agent does not supply an explicit timeout. |
${ENV_VAR} token expansion¶
Both HttpAllowedHosts entries and ApiProfiles values (base URL and all header values) support ${VARIABLE_NAME} tokens. Tokens are expanded at startup using the process environment — the resolved values are never written back to disk or shown in logs.
Security:
HttpAllowedHosts:
- "${SNOW_HOST}" # expanded once at startup
ApiProfiles:
snow:
BaseUrl: "https://${SNOW_HOST}/api/now"
DefaultHeaders:
Authorization: "Bearer ${SNOW_API_TOKEN}"
Tokens that reference unset variables are replaced with an empty string (matching shell behaviour). Profile header keys are not expanded — only values are.
How profiles are used by agents¶
An agent with the Http plugin can reference a profile by name:
This resolves to:
GET https://mycompany.service-now.com/api/now/table/incident?state=1&limit=10
Authorization: Bearer <value of $SNOW_API_TOKEN>
Accept: application/json
The allowlist (HttpAllowedHosts) is still enforced after profile resolution — a profile whose resolved host is not on the list is denied.
See Plugins → Http for the full function reference including the profile parameter.
Minimal config¶
The smallest valid config that does something useful:
Orchestration:
Name: SingleAgent
Agents:
- Name: Assistant
Instructions: You are a helpful assistant with filesystem access.
Model:
ModelId: gpt-4o
Plugins:
- FileSystem
Selection:
Type: sequential
Termination:
Type: maxiterations
MaxIterations: 5
JSON is also supported (same schema, Orchestration: becomes "Orchestration": {}). See the intro at the top of this page.