# Approvals

Source: https://routineos.org/concepts/approvals

> Human in the loop for Claude routines: every send, post or delete waits at an approval gate. The first run is report-only. Fetched text is data.

Concepts

# Human in the loop for Claude routines: your yes by design

A routine reads the web, your mail and other people's text. So anything that leaves it, a send, a post or a delete, is meant to stop at an approval gate until a named person says yes, because the prompt makes it stop. This page explains how that works and what has been checked.

[Get started](https://routineos.org/#start)[Gates in the docs](https://docs.routineos.org/concepts/gates-and-approvals)

from the docsapprove then send: not piloted end to end

Gates

## What a gate is and what triggers one

A gate is a stop sign in front of any action that leaves the routine. The run prepares the action, asks a person, writes a pending record and stops. Nothing waits in memory. A later scheduled run reads the answer, and only an approved action is carried out, in that later run.

A routine that declares a send, post or delete action must also switch its gate on. If it does not, lint fails.

The outcome is one of three: approved, rejected or expired. For a gate nobody answers, the prompt tells the later run to let it expire after its timeout and send nothing.

1. **Prepare**The run drafts the action and does not run it.
2. **Ask**It asks a named person by email or Slack, on the Desk, or both.
3. **Stop**It writes the pending record and ends.
4. **Resume**A later run reads the answer and acts only on an approve.

Where you answer

## Approve on the Desk, by email or in Slack

On the [Desk](https://routineos.org/concepts/desk), an Approvals page lists each open gate with the time left, and has Approve, Reject with a reason, and Edit draft. If you approve an edited draft, the send uses your edit. A history shows what was decided.

For email and Slack, the request asks for a reply whose first line is exactly `approve` or `reject` followed by a code. The docs describe a strict reading: the reply must come from the named approver, be newer than the request, and match that line exactly.

**Joined Desks work differently**For a worker gate on a Desk someone joined (see below), the approval email is a notice only. A reply never approves it. Approval happens on the Desk, by the person who serves the lane.

**Replies and worker gates**On an ordinary gate, the approval email or Slack message asks for a reply whose first line is exactly approve or reject plus a code. The routine's prompt tells the later run to accept only such a reply from the named approver and to ignore other instructions in it. That is a prompt rule, not a check made by code. On a gate for a joined worker, the email is a notice only. A reply never approves it; only a decision made on the Desk by the person serving the lane counts.

First run

## The first run is report-only

A new routine does not send anything on its first run. The prompt forbids sending, posting and deleting, and the run writes what it would have done. You read that report before you let it do more. Every prompt also carries a line saying what the routine may never do.

- The first run sends, posts and deletes nothing: the prompt forbids it.
- A routine with a send, post or delete action and no gate fails lint.
- A run that asks does not also send. Resume is always a later run.

Untrusted text

## Fetched content is data, not instructions

A routine reads job posts, web pages and email replies. Any of it could try to give the routine orders. Each prompt includes a clause telling the routine to treat fetched text as data, and lint checks that the clause is there. That is a rule in the prompt, not a guarantee about what a model does with a hostile page.

The gate is the second line. The worst a poisoned page can do is put a request in front of you, and you can say no. It also keeps a person accountable for what goes out under their name.

Shared Desks

## Worker gates: approve only what you were shown

When teammates [join a Desk](https://routineos.org/concepts/join-a-desk), each serves a lane from their own account. A lane that sends mail is gated, and the prompt reads approvals only from the decisions of the person serving the lane. That depends on the Desk's database rules. Since 0.8.0, an approval counts only for the item and the exact content that person was shown. If the pending record is edited after the click, the approval is void, and the send uses the approved copy. The owner's approval does not count for a joiner's gate.

These access rules are documented by the platform and are not yet pilot-verified.

Honest limits

## Which channels have been checked

| Route | Status |
|---|---|
| Approval by email (Gmail connector) | Pilot-verified end to end |
| Approval by Slack, connector set to "Ask for approval" | Pilot-verified end to end |
| Push notice | One way only. Replies are not part of this route |
| A button on the Desk as the only gate | Unverified |
| Approve on the Desk, then a later run sends | Not piloted end to end. The Desk says so: "A later run acting on it is not piloted." |

The [inbox triage](https://routineos.org/templates/inbox-triage) and [content calendar](https://routineos.org/templates/content-calendar) templates are approval-gated and unpiloted. Read their first report closely. [See every platform claim with its tag](https://docs.routineos.org/introduction/honest-limits).

## Start with an approval-gated template

Install the plugin in Claude Code, then try inbox triage or content calendar. Both start report-only.

[Get started](https://routineos.org/#start)[Inbox triage](https://routineos.org/templates/inbox-triage)
