# How to write your first approval policy (with examples) (/blog/write-your-first-approval-policy)

![Illustration: A human hand hangs a small blank wooden sign on a low garden gate.](/blog/write-your-first-approval-policy/hero.webp)

An approval policy is plain English text written in Dashboard → Approvals. Every write your agents make through CoreSpeed is judged against it and gets one of three verdicts: Allow, Ask or Deny. Reads are never gated. Smart Approval is off until an organization turns it on, so a new organization has no policy and no gate.

**From blank page to a live gate**

1. **Write one sentence of context** (who the agent is and what its job looks like)
2. **Add fine, ask and never sentences** (routine writes; writes a person checks; writes nobody makes)
3. **Choose the default behavior** (Relaxed, Balanced, Strict or Lockdown) — Written rules beat the default.
4. **Check the failure setting** (a failed evaluation goes to Ask or Deny; Ask is the default) — No failure path lets a write run.
5. **Run Test policy** (one call per sentence, plus one the policy never mentions) — Same evaluation as the gate; nothing executes.
6. **Connect a channel** (the dashboard queue always; email or Slack as well)
7. **Save and turn it on** (every save is a new policy version with history)

Sentences, a default, a test run, a channel, then on.

## What goes in a policy? \[#what-goes-in-a-policy]

Sentences, read in context, for every judged call. There is no rule builder and nothing is compiled. The example from the docs covers the three kinds of sentence you need.

```text
Sam handles support. Replies to customers who have written to us first are
fine. Ask me before anything goes to a public channel or an external company,
and before any refund over $100. Never post on our behalf about pricing,
funding, or anything that reads like a product promise.
```

| Sentence from the example                                     | Kind   | Verdict for a matching write       |
| ------------------------------------------------------------- | ------ | ---------------------------------- |
| "Replies to customers who have written to us first are fine." | fine   | Allow: runs, logged                |
| "Ask me before any refund over $100."                         | ask    | Ask: held, a card reaches a person |
| "Never post on our behalf about pricing."                     | never  | Deny: refused                      |
| A write none of your sentences address                        | silent | your default behavior decides      |

The first sentence, "Sam handles support", is context. It tells the judge who the caller is and what their work looks like, so the sentences after it read the way you meant them.

## How do you write and enable it? \[#how-do-you-write-and-enable-it]

1. Open Dashboard → Approvals. Smart Approval shipped in public beta in late September 2026; the [launch post](/blog/introducing-smart-approval) shows the whole flow.
2. Start with one sentence of context about the agent and its job.
3. Add a "fine" sentence for the routine writes you never want to see. Add an "ask" sentence for the writes a person should check. Add a "never" sentence for the writes nobody should make.
4. Choose the default behavior for writes your text never mentions. Relaxed runs them. Balanced, the default, runs them unless the call is destructive, then asks. Strict asks for every write. Lockdown refuses every write. Written rules beat the default, and "destructive" is judged from what the call would do; a tool's `destructiveHint` is a hint.
5. Check the failure setting. A failed evaluation, from a timeout, an outage or a call too large to read, goes to a separate Ask or Deny setting. Ask is the default. No failure path lets a write run.
6. Run Test policy. It sends a hypothetical call through the same evaluation the gate uses without executing anything. Try one call per sentence and one the policy never mentions.
7. Connect a channel. The dashboard queue always has the card and is the only place the full call is shown. Email adds the tool, who asked, and approve and deny links; the arguments stay out of the mail. For Slack, an admin installs the workspace once from the dashboard, then each member picks the Slack account that identifies them.
8. Save and turn it on. Every save is a new policy version with history, so a decision from last week is explained by the text that was active last week.

Members can add their own text on top of the organization's. It can only make things stricter for their own calls. The organization's text is the ceiling.

## What does the agent see when a call is held? \[#what-does-the-agent-see-when-a-call-is-held]

The held call returns at once with an error-shaped receipt: "Approval required, not run, call `manage__approval_wait` with this id". The agent calls that tool. `approval_wait` blocks until a person decides, then returns the original tool's real result, or an error saying the action was denied or the card expired. Clients that send a progress token, as Claude Code does, get a progress notification every ten seconds.

The agent must not send the call again. A fresh `tools/call` is a new request, judged on its own, and it can raise a second card. The call is frozen when held, so the arguments you approve are the arguments that run, and two simultaneous approvals hand it over once.

The card lives as long as the agent waits. If the agent stops waiting, the card expires about thirty seconds later. A card nobody decides expires after an hour. Who can decide: the member who made the call, or the owner of the agent or API key that made it. An agent cannot approve its own action. Admins can see every card, and seeing is not deciding.

## What does the judge see? \[#what-does-the-judge-see]

Your policy, the tool's name and description, its annotations, who is calling and from which client, how often this caller used the same tool recently, and the argument values. You can turn argument values off with "Let the judge read call arguments" on the policy page. The agent's conversation is never sent. The judge is Jev, TypeSafe's System One model; it answers typed questions with calibrated probabilities in one pass, and two guards sit above every verdict: a low-confidence answer becomes Ask, and an Allow that looks like prompt injection becomes Ask.

The gate sits in front of the tools, so one rulebook covers every agent and client on the team. It only sees calls made through CoreSpeed. Every decision lands in the [activity trail](/docs/activity) with its approval id.

## FAQ \[#faq]

**Do reads ever ask?** No. A search, a listing, reading a message: these go straight through. Only writes are judged.

**Does one policy cover Claude Code, Codex and a bot at once?** Yes, for everything they do through CoreSpeed. A write made directly to a vendor, outside CoreSpeed, is not seen by the gate.

**On Balanced, does an ordinary unmentioned write run?** Yes. If that is not what you want, write the sentence, or raise the default to Strict. The sentence is usually better because it is specific and versioned.

**What if two people approve the same card?** The action runs once. The second person sees who decided. The full rules are on the [approvals page](/docs/approvals).