# Every tool, and who is shown it

**An agent's key is shown two tools — read the register, and ask permission —
and every tool that changes what the company stands behind needs a signed-in
person.** The table below is generated from `reynforce/mcp/server.py`'s
`NEEDS`, the one mapping of tool to scope, and `tests/docs_checks.py` reads
it: a tool added there without a row here fails the suite, and a row naming a
tool that does not exist fails too.

| tool | scope | an agent? | what it answers |
|---|---|---|---|
| `search_claims` | `register:read` | **yes** | the claims this company stands behind, with each one's status. Capped, because a register with ten thousand entries should not arrive in one reply |
| `check_action` | `check` | **yes** | whether an action is permitted, and **what to say instead** when a claim it cites is not usable. The record is written as a side effect |
| `propose_claims` | `register:write` | no | turns a document into **proposed** claims. Never entries — a proposal nobody has accepted is not something the company stands behind |
| `assign_owner` | `register:write` | no | sets who stands behind a claim. A claim with no owner is one no agent may use |
| `accept_claim` | `register:write` | no | accepts one proposed claim, which is the act that makes it citable |
| `confirm_claim` | `register:write` | no | confirms a claim is still true, which resets its revalidation clock without bumping its version |
| `raise_contest` | `register:write` | no | says a claim is wrong or contradicted. A contested claim is unusable until the contest is resolved |
| `start_agent_draft` | `register:write` | no | starts a **draft agent** for one kind of work, when somebody sets an agent up in their own Claude. A draft is not an agent: it counts towards no plan and lapses 14 days after its last change |
| `update_agent_draft` | `register:write` | no | sets what the draft does, who it talks to and how, what runs it, and the promise row and contact limits it suggests — checked by the same rules as the screen. The suggestions are saved by a person on the screen |
| `agent_draft` | `register:write` | no | reads a draft back: its choices, when it lapses, what is left, and the lines it relies on with how many are usable now |
| `setup_instructions` | `register:write` | no | how to set up an agent from a chat, **the same words as this connector's prompt** *Set up an agent with Reynforce* — for a client that shows tools and not prompts |
| `finish_link` | `register:write` | no | the address of the Reynforce screen with the draft loaded. **The agent is made there, and what it connects with is shown there once — never in a chat** |

## Why the split is where it is

**An agent reads and asks; a person decides.** Four of them are acts the
register records a person taking — `reynforce/mcp/tools.py`'s `ACTS` names them
with the verb each one writes — and an agent key cannot hold the scope they
need.

**The draft tools are a person's too**, and so is the setup prompt, and so is accepting a draft's
lines: `accept_claim` takes one line at a time, and **there is no bulk accept in
a chat** — accepting every line at once is a button on the Reynforce screen,
where the person can see each one.

`check_action` is the exception that proves it: it is the agent's one writing
tool and **it writes no claim.** What it writes is a record of the asking, which
is why it needs `check` rather than `register:write`.

## What a tool never does

| | |
|---|---|
| answer around an unusable claim | the three unusable cases all escalate and tell the buyer. *Answer anyway* is not a setting — it is not expressible |
| hide a refusal | an unusable claim is marked and never filtered out, so you can see the claim you wanted and why you may not cite it |
| write a commitment you send | there is no such tool. See `connecting.md` |
