Skip to main content

Module scope

Module scope 

Source
Expand description

Capability scoping — the granted MCP subset, interpreted as a Rule-of-Two trust budget.

agentd has no policy engine; a subagent’s authority is the subset of MCP servers/tools its parent grants. Two invariants this module encodes:

  1. Monotonic narrowing. A child’s scope is the intersection with its parent’s — a child can never widen beyond what its parent holds. Because narrowing only ever shrinks, a check made over the root grant bounds every descendant, which is what lets the trifecta gate run once at startup rather than at every spawn.
  2. Rule of Two. Servers and tools are tagged untrusted_input / sensitive / egress; granting one agent all three legs of the lethal trifecta is refused unless the operator overrides it (security.allow_trifecta).

Everything here is pure logic with no I/O; callers apply it. Config validation folds the whole root grant, so startup and --validate-config can never reach different verdicts, and the subagent.run tool folds the child’s requested server subset before minting the child.

Structs§

ToolScope
A subagent’s tool scope: which MCP servers it may reach, and (optionally) which tools within them. Both must pass for a call to be allowed.
Trifecta
The three legs of the “lethal trifecta”. An agent holding all three — it reads untrusted content, can touch sensitive data, and can send data out — is the dangerous combination: one injected instruction in the content it reads is enough to make it fetch a secret and forward it.

Enums§

RuleOfTwo
The verdict on a grant. Ok ≤ 2 legs; all 3 legs → Refuse (or Warn with --allow-trifecta).
Scope
A whitelist over names: everything, or an explicit set. BTreeSet for deterministic ordering (stable logs/serialization).
TrifectaTag
One leg of the lethal trifecta — an operator-declared risk capability a tool carries. Tags come from the operator’s own config and nowhere else: never from a tool description, a model’s claim about itself, or anything an MCP server advertises, because a server able to tag itself could simply declare itself harmless and buy back the leg it was meant to be charged.
TrifectaVerdict
The verdict on a grant’s trifecta exposure. A refusal is never a crash — each caller turns it into an outcome its layer can act on:

Functions§

check_trifecta
Pure Rule-of-Two check. Folds the tags of a granted tool set (OR across legs) and judges the accumulated budget:
evaluate
Evaluate a grant’s trifecta exposure. The Rule of Two is satisfied at ≤2 legs; 3 legs violates it — refused unless allow_trifecta downgrades the refusal to a loud warning.