Skip to content

Agent Governance Toolkit

fuseraft-cli integrates with the Agent Governance Toolkit (AGT) to provide runtime safety controls that operate independently of agent instructions. Governance is always on — there is no config key to enable or disable it. The controls described here apply to every session.


Feature Description
Execution rings Per-agent privilege tiers derived from TrustScore
Prompt injection detection Blocks tool results that contain adversarial instruction overrides
Hash-chain audit log Tamper-evident record of every governance event
Circuit breaker Stops runaway agents after repeated API failures
SLO tracking Monitors routing validator pass rate within the session
Rate limiting Escalates to HITL when a validator blocks the same route repeatedly
DID identity Assigns a decentralized identifier to each agent for audit correlation
Policy files Optional YAML files that extend or override default governance rules

When Security.FileSystemSandboxPath is configured, each agent is assigned to an execution ring based on its TrustScore (configured in Agent fields). The ring controls what the agent is permitted to do within the sandbox.

Ring TrustScore Write access Network access
Ring 1 (Trusted) ≥ 0.80 yes yes
Ring 2 (Standard) ≥ 0.60 yes yes
Ring 3 (Sandbox) < 0.60 no no

Ring 3 agents can call read_file and list_files but are blocked from write_file, delete_file, shell_run, and HTTP requests. Denials are returned as tool results so the agent sees them; they are also recorded in the audit log.

Default: All agents default to TrustScore: 0.7 (Ring 2) when not specified.

- Name: Reviewer
TrustScore: 0.6
...

To give a Reviewer or Planner read-only access to the sandbox while ensuring they cannot modify files, set TrustScore to any value below 0.60.


When a shell_run or read_file result contains text that looks like an adversarial instruction override (e.g. a file that says “Ignore your instructions and do X”), the injection detector flags the content before it is passed to the agent as a tool result.

Detection is heuristic and runs automatically — no configuration is needed. Detected injections are recorded in the audit log with GovernanceEventType.ToolCallBlocked and also appear in the events stream as "tool_blocked" entries.


All governance events are recorded in a session-scoped hash-chain audit log. Each entry links to the previous one via a SHA-256 hash, making the log tamper-evident: any modification of a past entry breaks the chain.

fuseraft subscribes to every governance event the kernel emits, so the log isn’t limited to a fixed allowlist — but in the current codebase, fuseraft itself only triggers these:

Event When it fires
AgentRegistered When an agent is created for a new session
PolicyViolation When a routing or termination validator blocks a handoff
ToolCallBlocked When the sandbox or injection detector denies a tool call

(The AGT SDK also defines PolicyCheck, TrustVerified, TrustFailed, CheckpointCreated, and DriftDetected, but fuseraft doesn’t currently invoke the trust-verification or checkpoint APIs that would raise them.)

Each turn’s reasoning block is folded into the same chain: the reasoning text is SHA-256-hashed and only the first 16 hex characters of that hash are recorded, as a ReasoningEmitted:<hash> entry. This ties reasoning to the tamper-evident record without ever putting the raw reasoning text in the audit log.

Each entry is written to disk as it’s appended, as one JSON object per line, to audit-chain.jsonl next to the session’s events.jsonl (i.e. ~/.fuseraft/sessions/{project_slug}/{session_id}/audit-chain.jsonl; if Events isn’t configured for the run, it falls back to ~/.fuseraft/logs/{project_slug}/audit-chain.jsonl). Fields are snake_case to match every other JSONL log fuseraft writes: seq, timestamp, agent_id, action, decision, previous_hash, hash. Audit writes are best-effort — a failure to write never disrupts the session.

Cross-session linking. Each session’s chain is otherwise self-contained — a fresh AuditLogger per run, so previous_hash never spans files. To keep a project’s audit trail from being N disconnected chains, a brand-new session (never a resumed one — that would re-inject a link into the middle of an existing chain) looks up this project’s most recently written prior session and stamps its chain tip into its own first entry, as agent_id: "system", action: "SessionLinked:prev=<hash>". That claim is covered by the entry’s own hash like any other field, so it’s tamper-evident the same way; it isn’t a real previous_hash link (the SDK doesn’t expose a way to seed one), so confirming it means checking that some sibling session’s file genuinely ends with the claimed hash — which is what --verify does. This proves the claimed predecessor state really existed in this project’s history; it does not independently prove no session was skipped or that ordering wasn’t manipulated by whoever controls the filesystem.

fuseraft log audit reads the chain back: with no flags it lists entries (filterable by --session, --agent, --decision, --last); with --verify it independently recomputes every hash, reports whether each file’s chain is intact (exiting non-zero if any entry’s stored hash, chain link, or sequence number doesn’t match what’s recomputed), and resolves any cross-session link claim against sibling sessions. --verbose output also includes governance events as they fire, for watching the chain build up live.


A circuit breaker wraps every agent invocation. If the underlying model API returns 5 consecutive failures, the circuit opens and the session is stopped with an error message rather than continuing to retry.

Parameter Value
Failure threshold 5 consecutive failures
Reset timeout 30 seconds
Half-open probe calls 1

When the circuit is open, the session is stopped and the checkpoint is saved so it can be resumed once the API is healthy again.


The governance kernel tracks a policy-compliance SLO: the fraction of routing validator checks that pass within the session. Target: 95%.

Burn-rate alerts fire when compliance degrades faster than the budget allows:

Alert Burn rate Window
Warning 2× 1 hour
Critical 5× 10 minutes

SLO events appear in the governance audit log. They do not currently surface in the terminal output but are visible in --verbose mode.


A failure counter tracks bad turns per agent. A “bad turn” is any turn that results in a correction being injected: no routing keyword, a keyword that belongs to a different role, multiple keywords in one response, or a keyword whose validator rejected the handoff.

With Selection.Type: graph, a single counter covers all of these uniformly and escalates at Selection.Graph.MaxRetries (default 4). With keyword/statemachine, only validator/contract failures are counted this way, classified by type and escalated per FailureHandling.<Type>.Threshold (default 3, or 2 for ConflictingEvidence); a bare missing-keyword/signal turn is not covered by this counter (see Validators — Stuck detection for the full breakdown). Either way, when the threshold is reached, ValidatorStuckException is thrown and the session stops with a descriptive error. The checkpoint is saved so the session can be resumed after diagnosing the issue.

GovernanceKernel’s rate limiter enforces the same threshold via a 10-minute rolling window alongside the consecutive-turn count: if that many failures accumulate within the window, escalation fires immediately rather than waiting for the consecutive-turn count to catch up.

This prevents infinite correction loops where an agent keeps re-emitting a broken handoff without making progress. The counter does not reset when the failure mode changes — alternating between validator failures and no-keyword turns hits the threshold at the same rate as repeated identical failures.


Each agent is assigned a Decentralized Identifier at session start in the form did:fuseraft:<agentName>:<sessionId>. DIDs are used as the agentId field in all audit log entries so events from different sessions can be distinguished even when the same agent name is reused.

DIDs are regenerated fresh for each StreamAsync call (each session). They are not persisted.


YAML policy files extend or override the default governance rules. When a file exists at policies/default.yaml in the same directory as the orchestration config, it is loaded automatically.

.fuseraft/config/
orchestration.yaml
policies/
default.yaml

Policy files are optional. If no file exists, the kernel uses built-in defaults (all features enabled, thresholds as documented above). Refer to the Agent Governance Toolkit documentation for the policy YAML schema.


The governance rings extend the filesystem sandbox: the sandbox controls which paths an agent may access; the ring controls what operations the agent may perform within those paths. Both checks must pass for a tool call to proceed.

See Security & Sandbox for path-level containment details.