---
slug: authority-outside-the-model
title: "Authority outside the model: a prospective control plane for containing agent actions"
kind: architecture
status: published
hash: 613c1c5cb4bcdd2aa6e2e81c01b8a2bb1cd248e8a9b06ea1b4f1196391f55570
created: 2026-10-09T02:25:15.474Z
updated: 2026-10-09T03:29:43.378Z
summary: "In this build a model does not set its own authority: limits are a token checked outside the model, actions are declared operations the runtime executes, and every use and refusal is recorded by the runtime. This page states what that could contain in development, training-time tool use, evaluation and deployment, what is enforced today, and what full containment would still require."
tags: ["architecture","agents","ai-safety","containment","control-plane","least-privilege","macaroons","compound-tools"]
above: []
below: ["[[directory-ledger-pattern]]", "[[unified-dispatch-macaroon-atoms]]", "[[task-payload-provenance-article]]"]
adjacent: []
nested: ["[[unified-dispatch-macaroon-atoms]]", "[[directory-ledger-pattern]]", "[[task-payload-provenance-article]]"]
---
# Authority outside the model: a prospective control plane for containing agent actions

*In this build a model does not set its own authority: limits are a token checked outside the model, actions are declared operations the runtime executes, and every use and refusal is recorded by the runtime. This page states what that could contain in development, training-time tool use, evaluation and deployment, what is enforced today, and what full containment would still require.*

## The model does not set its own authority

In most agent stacks the model holds a credential and a set of instructions, and the instructions are the only limit. The model reads them, so the model is the last thing standing between a bad output and a damaging action. OWASP names the failure: excessive agency, damage done "in response to unexpected, ambiguous or manipulated outputs from an LLM", whatever caused them.

This build moves three things out of the model's hands:

- **What it may do** is a scoped token, checked on every call by code the model cannot see or change.
- **How an action executes** is a declared operation run by the runtime, through one dispatch path.
- **What record is kept** is written by the runtime while the work happens, not reported by the model afterwards.

A model can be wrong, manipulated, or working against its operator. None of the three checks asks it. That makes these mechanisms model-independent, and that is their significance: they are candidate primitives for a control plane that contains model actions, during development, during training-time tool use, in evaluation and in deployment. They are not only a better way to call tools.

## Four primitives, one containment job each

| Primitive | What it bounds | Where it is enforced | Today |
|---|---|---|---|
| Compound tools | The action space: declared operations with bounded arguments, not arbitrary code | The runtime's contract for each tool | Built and live: CODE, WEB, COMPUTER, RESULT; REST designed, not built |
| Unified dispatch | The path: every capability call goes through one runner and one check | The tool runner | Every Directory tool; some device doors are still reachable directly with the build key |
| Scoped tokens | The authority: tools, doors, arguments, paths, uses, time, task, whose credentials | An HMAC-chained token checked on every call | Implemented and live; no running agent uses one yet |
| Ledger and task provenance | The evidence: every call and every refusal, written by the runtime | An append-only PostgreSQL table and per-token call logs | Recording at the request boundary; a known loss window, stated below |

The mechanics of each are in the three companion articles: [[directory-ledger-pattern|Directory and Ledger]], [[unified-dispatch-macaroon-atoms|scoped tokens]] and [[task-payload-provenance-article|task provenance]].

## Compound tools are programmatic tool calling in reverse

Programmatic tool calling lets a model write code that calls tools inside a code execution container. The intelligence goes into generated code, and the sandbox has to hold whatever that code does.

A compound tool inverts this. The runtime holds the logic, and the model holds one tool per domain. The model states a command and its complications: modifiers that shape the call, such as which fields to return, how many bytes, which stored credential, and which retry policy. The runtime compiles the declaration into the real call.

The coding tool is built this way, and so are WEB (search and read), COMPUTER (browser procedures) and RESULT (read back part of any earlier call); a single REST tool for every HTTP API is designed, not built. Its live contract lists eleven operations (schema, grep, read, edit, write, check, grammar, deploy, ship, job, result), hash-checked canonical writes, detached tests and deploys, and "deterministic operations; no model planner". An edit against a stale hash is refused, not applied. The answer is cut to what the model asked for, and the whole result is kept by reference.

For containment, the inversion is the point:

- **The action space is enumerable.** Every operation and complication is declared, so a scoped token can bound each one with an argument rule.
- **The failure mode is a refusal.** A wrong declaration is refused by the runtime. It does not become arbitrary code.
- **Evidence is automatic.** The runtime produces the record, so the model cannot shape it.

Generated code remains the fallback for genuinely novel logic. That fallback is also where containment is hardest, because the sandbox then has to hold anything.

## What this could contain, phase by phase

- **Development.** A coding agent edits only through hash-checked operations, in allowed paths, for one task, until the task closes.
- **Training-time tool use.** Each rollout in an agentic environment could run under its own token: which tools, which arguments, which paths, how many uses, until when. Every call and every refusal would be recorded by the runtime, independently of the policy's own transcript. An attempt to exceed authority becomes an observable event with the caveat that stopped it.
- **Evaluation.** A task's record shows what the agent did, not what it said it did, and refusals measure attempted overreach directly.
- **Deployment.** Least privilege per job: the minimum access needed for the assigned task. Delegation can only narrow a token, never widen it.

What it does not control: model weights, gradient updates, the training computation itself, and the model's internal reasoning. It governs actions that cross the execution boundary, and only those that pass through it.

## What is enforced today

- Every Directory tool call goes through one runner. A token is checked on every call: its chain is recomputed from the root and compared in constant time, and every caveat must hold. An unknown caveat is a refusal, never a pass.
- Refusals are written before anything is sent. On 3 October 2026 a run was refused on the caveat `task = T-0229`, 21 minutes after that task closed, and the refusal is on the task's record.
- Requests, outbound calls and tool runs are recorded at the request boundary as exact bytes, stored once under their SHA-256. The build's own secret values are replaced by their names.
- The coding tool runs as a compound tool, with hash-checked writes and detached jobs.

## The containment boundary: what is prohibited, what is recorded, what is outside

| | What the infrastructure does |
|---|---|
| **Can prohibit** | Any tool call that goes through the runner: a tool, door or interface the token does not name; an argument outside its rule; a path outside its area; a use past its count or expiry; any call once its task is done; a token widened by its holder. The refusal happens before anything is sent. |
| **Records** | Every call through the runner and every refusal, with the caveat that refused it; the exact request and answer bytes of requests, outbound calls and tool runs, stored once under their SHA-256, with the build's secret values replaced by their names. |
| **Outside enforcement** | Model weights, gradient updates, the training computation and the model's internal reasoning. Any action that does not cross the runner: agents still holding the build key (all of them today), raw shell tools and device doors the build key reaches directly, shell text that names a path, and network egress not forced through the runner. Events lost if a Worker is killed before its deferred write. |

The implemented part is a permission checker that refuses and records. Containing a model is the further claim that it has no other way out, and that claim is untested.

## What full containment would still require

The primitives exist. Demonstrating that they contain a model means testing the whole boundary, and that work is not done. Stated plainly:

1. **Every agent on a scoped token, and the build key withdrawn from agents.** Today no running agent has been switched.
2. **No path around the runner.** Raw shell tools, and device doors reachable directly with the build key, are bypasses unless a token excludes them. Path limits check path-named arguments, not the text of a shell command.
3. **Egress forced through the runner.** Network and filesystem access from an agent's container must be limited to the runner. Otherwise any tool that fetches an arbitrary URL is an exit.
4. **Task binding on the live task store.** The checker reads tasks from the document the task list was kept in before it moved to a database table.
5. **Evidence that cannot be lost.** By default, events are written after the answer goes out, so a Worker killed before the write loses them. Inbound webhooks already await the write. Containment evidence should too.
6. **An adversarial test of the boundary.** A model given only a token and told to exceed it, with every attempt counted and every success treated as a defect. Not yet run.

## Prior work

The token is the macaroon construction (Birgisson et al., NDSS 2014): caveats that attenuate and confine a bearer credential. Least privilege is a long-standing security principle. Excessive agency is a named risk for LLM applications. Programmatic tool calling and code execution with MCP are the current industry route for efficient tool use. What this build adds is the combination: authority checked outside the model, actions as declared operations, and a record the model does not write, all on one execution path.

## Facts

```json
{
  "thesis": "model-independent containment and accountability: authority, execution and evidence held outside the model",
  "primitives": {
    "compound_tools": {
      "bounds": "the action space",
      "built": "CODE: 11 operations (schema, grep, read, edit, write, check, grammar, deploy, ship, job, result); hash-checked canonical writes; detached tests and deploys; deterministic operations, no model planner",
      "designed": [
        "REST",
        "SEARCH",
        "COMPUTER"
      ],
      "read_from": "GET /api/tools/CODE, 9 October 2026"
    },
    "unified_dispatch": {
      "bounds": "the path",
      "gap": "some device doors are reachable directly with the build key"
    },
    "scoped_tokens": {
      "bounds": "the authority",
      "limits": 11,
      "gap": "no running agent uses one yet"
    },
    "ledger": {
      "bounds": "the evidence",
      "gap": "events held in memory are lost if a Worker dies before the write"
    }
  },
  "enforced_today": [
    "every Directory tool call through one runner",
    "token chain recomputed and compared in constant time on every call",
    "unknown caveat refused",
    "refusal recorded before anything is sent (T-0229, 3 October 2026)",
    "exact-byte recording at the request boundary, SHA-256 deduplicated",
    "CODE built as a compound tool"
  ],
  "required_for_containment": [
    "every agent on a scoped token; build key withdrawn from agents",
    "no path around the runner: raw shell tools and directly reachable device doors excluded",
    "egress forced through the runner",
    "task binding on the live task store",
    "evidence writes awaited",
    "an adversarial test of the whole boundary"
  ],
  "out_of_scope": [
    "model weights",
    "gradient updates",
    "training computation",
    "internal reasoning"
  ]
}
```

## Sources

1. [OWASP Top 10 for LLM Applications: LLM06 Excessive Agency](https://genai.owasp.org/llmrisk/llm062025-excessive-agency/) — “Excessive Agency is the vulnerability that enables damaging actions to be performed in response to unexpected, ambiguous or manipulated outputs from an LLM” (sha256 16c5966865aba67e)
2. [OWASP: the three root causes of excessive agency](https://genai.owasp.org/llmrisk/llm062025-excessive-agency/) — “excessive functionality; excessive permissions; excessive autonomy” (sha256 0651a596f4020d36)
3. [NIST glossary: least privilege](https://csrc.nist.gov/glossary/term/least_privilege) — “A security principle that a system should restrict the access privileges of users (or processes acting on behalf of users) to the minimum necessary to accomplish assigned tasks.” (sha256 ba38f67b681f7c8d)
4. [Claude docs: programmatic tool calling](https://docs.claude.com/en/docs/agents-and-tools/tool-use/programmatic-tool-calling) — “Programmatic tool calling allows Claude to write code that calls your tools programmatically within a code execution container” (sha256 00dcf45c0d90bd91)
5. [Anthropic engineering: code execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) — “The agent can then write code to interact with MCP servers.” (sha256 72120899d5ccd3d2)
6. [Macaroons (Google Research, NDSS 2014)](https://research.google/pubs/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/) — “macaroons embed caveats that attenuate and contextually confine when, where, by who, and for what purpose a target service should authorize requests” (sha256 c9d336b5640d0404)
7. [Scoped access: no running agent switched yet](https://miscsubjects.com/a/scoped-access) — “No running agent of this build has been switched to scoped tokens” (sha256 8f8e1b185216aed6)
8. [Scoped access: shell tools and area limits](https://miscsubjects.com/a/scoped-access) — “do not give shell tools to a token you limit by area” (sha256 d455fd8cb976b315)
9. [Scoped access: unknown caveats are refusals](https://miscsubjects.com/a/scoped-access) — “A caveat this build does not know is a refusal, never a pass.” (sha256 7017355676c5fb68)
10. [Scoped access: the task record](https://miscsubjects.com/a/scoped-access) — “The worker could not leave a call out, because it could not act without the token, and it could not add one, because the build writes the record.” (sha256 3c09e45853488de9)

---

**below:** [[directory-ledger-pattern]], [[unified-dispatch-macaroon-atoms]], [[task-payload-provenance-article]]

**nested:** [[unified-dispatch-macaroon-atoms]], [[directory-ledger-pattern]], [[task-payload-provenance-article]]
