AI agent change governance

Your agents can propose anything.
They can't approve anything.

An agent gets one credential, its SwitchTender token. It never sees an SSH key, a cloud login, or a vault password, and it can never approve a change, widen its own access, or manage identity or secrets. Everything it asks for goes through the same gate a person's request does. What it did is recorded before it happens, in a chain a third party can check without trusting your server once it is anchored.

What governed agent changes look like

Eight properties, each one testable against a running server. The first four keep an agent inside the gate. The rest make what it did evidence an auditor can rely on.

One credential per agent

Secrets are sealed on the server and decrypt only at execution, so an agent holds exactly one credential: its SwitchTender token. It never sees an SSH key, a cloud login, or a vault password. Revoking that one token shuts the door.

One gate, regardless of which tool

Ansible, Terraform, OpenTofu, Bash, PowerShell, Python, and Go all go through the same request, policy, approval, and chain. An agent that chains a Terraform change, an Ansible update, and a shell script inside one incident does not cross into a different approval model partway through: every one of those runs carries the same actor identity, the same policy evaluation, and lands in the same chain. Switching tools does not get an agent out from under the gate.

A human approval gate, bound to content

Agents can propose changes. Only authorized humans can approve them, and this gate is free on every tier. An agent's run waits for a person's approval with no policy written, its dry runs included, unless a rule with effect: exempt covers it, and its Terraform or OpenTofu apply waits twice: once before it plans, and again for the apply its plan proposes, carrying the saved plan. On Team, a rule can require an approver other than the person the agent acts for. An approval comes from a person's session, a person's own token, or a pull request comment from the forge account a person linked, and the server refuses an agent's approval at the route and again where the decision is made.

Policies can also hold people's runs for a person, refuse runs outright, or key on the operation's assessed risk, or on whether an agent or a person asked, and the approval itself is a chain entry committing a digest of the exact change released. The executor refuses a change that drifted after the decision, so what a person approved is provably what ran. An approver can record why, masked for known secrets, kept as audit evidence, and committed so a receipt holder can check it offline. Community holds plain rules of your own, as many as you need: require-approval policies and exemptions, each of which can be narrowed to a single tool, for instance, rather than holding everything. Pro adds refusing a run outright and keying on risk. The full engine is Team: scoping a rule to agents, to a named actor, or to the account a token is bound to, and requiring that the approver not be the requester.

MCP with no approve tool

An agent runtime that speaks the Model Context Protocol connects straight to switchtender mcp with its agent token. It serves seven MCP tools: list templates, propose a run, list recent runs, read a run, its log, and its evidence, and list the workflow approval steps waiting for a person. There is no approve tool and no way to widen its own reach. --allow-adhoc adds an eighth that lets the agent compose a run of its own rather than launch a template an operator wrote, and even that one is held by default and goes through the same approval policy. Hand it an admin token, which an agent could use to release its own runs, and the command exits instead of starting. Serving on one anyway means typing --allow-admin-token, which exists for a local trial and prints a warning naming the risk at every start. The safe setting is the one you get without asking for it, so the same gated, chained, fail-closed request a person makes is the only thing an agent can make.

Actor-level provenance

Every entry names the actor behind it, whether it was a person or an agent (actor_type), and whose authority it used (on_behalf_of), all committed by the entry hash. The kind is declared when the token is minted, with --agent, rather than guessed from how a request looks, so an agent's changes stay attributable instead of blurring into a shared account. The live demo seeds an agent token named remediation-agent, bound to the ops-lead account the way switchtender token new --user ops-lead --agent mints one. Every request it makes goes through the real API with that token: its restart and its Terraform apply are held for a person, the workflow that would carry the apply inside it is refused at submission, its attempt to approve its own held run is refused at the door, and its smoke test runs under a narrow exemption. A run an agent asks for records which agent, the account it is bound to, and who provisioned its token, and each approval records who approved it and how separation of duties was evaluated.

Fail-closed recording

Every mutation is written into the audit chain before its handler runs. If the record cannot be written, the change is refused with a 503 instead of performed silently. There is no path where an agent changes something and nothing is written down.

A receipt for every change

Every mutation other than signing in or out returns an Audit-Receipt header naming its sequence and hash. Keep them. A receipt later proves the chain still holds that exact entry at that exact position, so an omission is detectable by the party it happened to.

Sealed offline verification

switchtender audit bundle emits the chain as a signed LoomSeal bundle. It verifies on a machine with no network and no SwitchTender install, against the key the server publishes at /.well-known/loomseal.json.

The one-credential architecture

An agent with a pile of credentials has a pile of doors. An agent with one credential has one, and SwitchTender puts a gate on it. --user binds the token to an account so it carries that account's role instead of acting as admin. --agent is what makes it an agent's credential: the ceiling moves onto the token itself, capped at operator whatever account it is bound to, so it can submit runs but can never manage identity, access, or secrets, and can never approve its own held run. It also declares the holder at mint time, so every entry the token writes is recorded as an agent rather than as an ordinary API token. Every run the agent submits then waits for a person's approval, its dry runs included, unless a rule with effect: exempt covers it. That needs no policy and no license, so the walkthrough below runs end to end on a self-hosted install. Three commands take you from nothing to an agent whose entire history is evidence.

  1. 1

    Pick the person the agent answers to

    The agent's token is bound to that person's account, so every entry it writes names who it acted for. Create the account if they have none. It asks for their password, or reads SWITCHTENDER_PASSWORD when there is no terminal. The agent never signs in: the token in the next step is its only credential.

    switchtender user new dev-lead --role operator --db switchtender.db
  2. 2

    Mint the agent token, the only credential the agent gets

    --agent is not decoration. It caps the token at operator no matter what account it is bound to, and it marks every chain entry the token writes as actor_type: agent. Leave it off and you get an ordinary API token: the same entries record actor_type: token, indistinguishable from a person's script, so the hold an agent's runs get does not reach it, and a rule scoped to agent runs never matches it. --agent requires --user, so the human the agent acts for is on the record. The TTL forces rotation, here monthly.

    switchtender token new --name deploy-agent --user dev-lead --agent --ttl 720h --db switchtender.db
  3. 3

    Leave the gate as it ships

    There is nothing to add. An agent's run waits for a person's approval, its dry runs included, unless a rule with effect: exempt covers it, and the receipt then proves who approved the run, or which rule exempted it. An exemption that names the agent's label must also name the account its token is bound to, since a label repeats across accounts.

  4. 4

    Hand the auditor the bundle

    switchtender audit bundle --db switchtender.db --out evidence.json

The longer walkthrough, including the MCP wiring, is in the agent guide. This page is about external agents driving the API. The built-in advisory AI is a separate feature: it proposes text and never executes anything.

What the chain does not prove

The chain proves the record was not altered. It does not prove that every change in your infrastructure went through SwitchTender. A person or a process holding its own SSH key can still change a host behind the controller's back, and no audit system can write down what it never saw. For agents, credential scoping is what closes that gap. An agent that holds only a SwitchTender token has no way around the controller, so every run it asks for is recorded before it runs. For people, the side door covers how standing keys go away and how a change made around the gate still turns up.

Put a gate and a logbook between your agents and production.