approval-md
v0.4.7
Published
Human approval for agent actions. CLI runtime for the approval.md convention (pre-release).
Readme
approval.md
A harness-agnostic, open-source framework for approving agent actions with a human in the loop.
Let your agents work. Decide where they need you.
Write an APPROVAL.md that says which actions can happen freely, which need a tap, and which stay in human hands. Approve from Telegram, a terminal, or a local web queue. Keep the policy and the record of decisions in files you can read and verify.
Let an agent draft your email, but ask before sending it. Let it edit your project, but stop before pushing to main. Review a sample of routine work instead of every action.
Website · Extended guide · Specification · CLI reference
Get started
Node.js 20 or newer. In your project directory:
npm install -g approval-md
approval quickstartThe walkthrough asks who you are, where approvals should arrive, and which action families should always ask. It shows the policy before you attest it. Telegram setup is included when you choose it.
The quickstart gives other classified, reversible actions an autonomous default. Change defaults.autonomy to manual for a more conservative policy, then re-attest. Runtime safety floors and unclassified-command refusals still apply.
Activate the environment using the command the walkthrough prints. From the same project directory:
eval "$(approval env)"
approval upThis starts the daemon and configured channel listeners. It does not install a harness hook: connect your agent below. For terminal decisions, run approval channel cli in another human-controlled terminal.
Prefer to build the policy yourself? Start with approval init and follow the manual setup. For unreleased features or contributions, use a source checkout.
Define what needs approval
Five autonomy levels, chosen per action class:
| Level | What happens |
| --- | --- |
| autonomous | Proceeds without asking, subject to the policy and runtime checks. |
| supervised-retro | Proceeds; a configured sample is reviewed afterwards. |
| supervised-live | A declared fraction pauses for approval; the rest proceeds. |
| manual | Each action waits for human approval. |
| human-only | The human performs the action. An agent cannot request permission to do it. |
An APPROVAL.md can look like this. This example uses a more conservative default than the quickstart; replace you with your chosen approver ID.
# Approval Policy
Work freely inside this project. Ask before reaching outside it.
```yaml approval-policy
version: "0.1"
defaults: { autonomy: manual, channel: cli, approval_ttl: 24h }
approvers:
you: { channels: [cli] }
classes:
read.*: { autonomy: autonomous }
read.file.out_of_scope: { autonomy: manual }
files.write.workspace: { autonomy: autonomous }
vcs.push.main: { autonomy: manual }
communicate.email.external: { autonomy: manual }
financial.spend: { autonomy: manual, limits: { per_action_usd: 25 } }
account.credential: { autonomy: human-only }
```Class names describe actions; they do not install an integration for them. supervised-live needs a live_rate and sampling setup. The deprecated supervised spelling remains an alias of supervised-retro.
An edit invalidates the previous attestation. To land a change, run the amendment ceremony: it shows the semantic diff, attests the exact bytes, and commits the policy and the log together. In a git repository, add --pr and it opens the pull request for you.
approval policy amend --require-load --as human:youapproval policy attest --as human:you is the bare attestation for a policy you have already reviewed by other means. Loosen some rules, tighten others, amend, keep going. Policy details.
Add your voice
The file can also carry an optional yaml approval-values block: what you love, like, dislike, and how you prefer to communicate. approval values and approval feedback make that guidance available to agents; approval journal write gives them a channel back.
Values and reactions inform the work. They do not change permissions. Values and feedback.
Gate your coding agent
Use the integration for the harness you actually run. A hook controls the tool calls it is wired to receive, not every possible action on the machine.
| Integration | Route and important distinction |
| --- | --- |
| Claude Code | approval hook claude-code; wire pre-execution and outcome hooks. |
| Cursor | approval hook cursor; the hook entry requires failClosed: true. |
| Claude Agent SDK | Python HookMatcher shim calling the same Claude Code hook. |
| Codex | MCP, an app-server bridge, and constrained-workspace tooling; native hook enforcement remains experimental. |
| Grok Build / Muse Code | Dedicated hooks; both have documented harness-level fail-open limitations. |
| Hermes Agent | New source-only hook; live verification is still pending. |
| Any MCP client | approval mcp serve; exposes gate tools, but does not intercept the client's native tools. |
Inspect a shell command's classification without running it:
approval hook classify -- git push origin mainThe extended guide covers wiring, read scope, coverage gaps, and what each route has actually demonstrated.
Put approvals on your phone
Telegram prompts separate runtime-computed facts from agent claims and show the payload being approved. A tap records the decision; the agent can continue through the appropriate execution path. The terminal and loopback web queue use the same log.
Telegram walkthrough · Channel setup and identity
Hand a grant to a real credential
The runtime includes adapters for SMTP email, AgentMail drafts, and zzz.bot threads and replies, plus a public adapter API.
Keep the sending credential in the runtime's vault, not in the agent's hands. On paths requiring approval, a single-use grant binds the payload before the adapter executes. Explicitly permitted autonomous or supervised paths do not require a human grant.
Know the boundary
approval.md is an oversight layer for broadly cooperative agents, not blanket containment for a hostile process on a machine it controls. Credential custody, hook wiring, and the harness's failure behavior determine what is enforced. Local human identity is config-declared; a hash-chained log is tamper-evident, not proof of personhood or an immutable history by itself.
Before committing real data: the scaffold does not ignore the event log or stored approval payloads. Decide what should remain private before putting messages or other sensitive material in a public repository.
Read on
The extended guide covers policy controls, channels, credentials, the event log, troubleshooting, and development. The specification, schemas, and CLI reference carry the detailed contracts.
Contributing · Conformance · Changelog · Governance
Code: Apache 2.0. Specification and schemas: CC0 1.0. Releases are approved through approval.md.
