# Approving and rejecting a draft

Approving runs the send immediately, through the same boundary a person's own send uses, and records who released it. Rejecting stops that message, records the decision against the thread, and prevents the engine from immediately producing the same reply again. Neither decision changes what Connect knows — that takes a separate, deliberate act.

- **Status:** Available
- **Audience:** both
- **Channels:** email
- **In the app:** #/needs-you, #/approvals, #/autonomy-audit
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/email/approve-reject/

## Approve

An approval is a send instruction, not a filing action. The reply leaves at once through `outbound.py` — the single boundary shared by the engine and by every person — and the outcome is written back with the provider's own acknowledgement attached. Until that acknowledgement exists the state is *uncertain*, and it is shown as uncertain rather than presented as sent.

Two things are still checked between your click and the message leaving: compliance on the recipients as they now stand, and the daily allowance. An approval that meets a spent allowance is not lost — it is recorded and the send waits, which is why an approved item can sit in the queue a little longer without anything being wrong.

## Reject

A rejection ends one message. It is recorded against the thread, and the engine does not turn round and produce the same reply on the next pass — which is the behaviour that makes rejecting safe to use rather than a way of starting an argument with a queue.

What it does not do is generalise. A rejection is a decision about one message; it carries no reason unless you give one, and no future thread inherits it. If the same thing would be wrong next week, the fix is a memory or a standing instruction, recorded at the right tier, as set out on [Giving guidance on a thread](/docs/email/guidance/) and argued in [Making a correction actually change behaviour](/research/memory-correction-that-sticks/).

> **Note** Rejecting three replies in a row to the same customer with no direction recorded produces a fourth. That is not stubbornness; it is the honest consequence of a control that does not silently infer rules from refusals.

## What each decision leaves behind

|  | Approve | Reject |
|---|---|---|
| Message state | Sent, or uncertain until acknowledged | Not sent; nothing reaches any provider |
| Recorded against | The thread and the person who released it | The thread and the person who refused it |
| In the decision log | Yes — what was decided, under which rule, and what happened | Yes. A refusal is a decision |
| Effect on future threads | None by itself | None by itself |
| Counts against the allowance | Yes, once it sends | No |

The last row of the middle column is the one people ask about later. Because refusals are logged as decisions, "nobody replied to this customer for three days" has an answer with a name and a timestamp on it rather than a silence. The same log is what makes the [Decision Log](/docs/autonomy/) usable in a dispute.

## Who may decide

- Any workspace member with permission to send on that channel. The approval is attributed to them individually, not to the workspace.
- The Connect Assistant can approve, send now or reject with `approve_draft`, `send_draft_now` and `reject_draft` — within rights that are deliberately narrower than a person's. It has no pricing authority and cannot clear a do-not-contact entry.
- Nothing approves on a timer. A reply left in the queue stays in the queue; there is no auto-release after a delay, because a deadline that sends unreviewed mail is worse than a backlog.

For the wider argument about why the agent's authority is kept separate from the person's rather than merged into one permission model, see [Separating the agent's authority from the person's](/research/authority-separation/).

## Questions

### Can I undo an approval?

Only before the send actually runs, which in practice is a very short window. Email has no unsend, and Connect does not imply one. What you have afterwards is the record and, if the message was wrong, a follow-up correction sent deliberately.

### Does rejecting delete the reply?

The decision is recorded and that message stops. What is kept is the trail — which is the useful part, since "we chose not to answer that" is a defensible position only if it is written down somewhere.

### Why did a reply go out that I never approved?

Almost always autonomy at a narrower scope: `autonomous` on one contact or one mailbox beats `ask_before_send` on the channel. The decision log names the rule that permitted it, which is the fastest way to find the scope you did not know was set.

## Related

- [Held drafts](https://connectbyjbrh.com/docs/email/held-drafts/)
- [Editing a draft before it goes](https://connectbyjbrh.com/docs/email/edit-draft/)
- [Proof that a message was sent](https://connectbyjbrh.com/docs/email/send-evidence/)
- [What Connect may do](https://connectbyjbrh.com/docs/autonomy/)
- [Separating the agent's authority from the person's](https://connectbyjbrh.com/research/authority-separation/)

## What this page is based on

- GENERAL.md §5 — approvals, Needs You and the audit trail
- GENERAL.md §8 — Assistant tools and their narrower rights
- CHANNELS.md §1 — the one send boundary
- `backend/app/autonomy.py`, `autonomy_api.py`
- `backend/app/audit.py`
