Tools
Held Drafts
OpenClaw plugin: nothing sends until you've read it — approval cards on outbound sends, append-only audit ledger, deterministic per-scope trust ladder
Install
openclaw plugins install clawhub:openclaw-held-drafts
README
# Held Drafts
**Nothing sends until you've read it.**
An OpenClaw plugin that turns every outbound message your agent tries to send into a
held draft: you get an approval card with the content preview, an append-only audit
ledger records every draft and every decision, and a deterministic trust ladder lets
routine sends earn autonomy — per recipient, never globally.
When Grok Bot launched, the sharpest review line was that the three controls that make
an always-on agent safe — *rehearsal, scope, and a record* — were exactly the three it
didn't ship. Your local agent deserves all three. This plugin is scope and record;
your sandbox is rehearsal.
## What it does
- **Holds outbound sends.** `before_tool_call` intercepts send-class calls
(`message` send/reply/forward/broadcast, `sessions_send`, plus any tools you list)
and raises OpenClaw's native approval card — Allow once / Always allow / Deny —
with the recipient and a content preview. Denials and timeouts fail closed.
- **Records everything.** Every draft and every decision is appended to
`~/.openclaw/held-drafts/ledger.jsonl`. Auto-allowed sends are recorded too —
promotion never turns off the record.
- **Earns trust per scope, deterministically.** A scope is
`agent | tool | channel | recipient`. *Always allow* promotes that one scope.
Optionally, N *Allow once* approvals auto-promote it (`autoPromoteAfter`).
The model cannot promote anything: trust changes only through your approval
decisions. Revoking is always available and only ever reduces privilege.
- **Reviewable in chat.** The `held_drafts` tool lets the agent show you the outbox:
`list` recent drafts, `show` one in full, `trust` to see promoted scopes,
`revoke` to put a scope back behind approval.
## Install
```bash
openclaw plugins install clawhub:openclaw-held-drafts # once published
# or from source:
git clone https://github.com/123Satyajeet123/openclaw-held-drafts
# add its path to plugins.load.paths and enable plugins.entries.held-drafts
```
If your config uses a `tools.allow` allowlist, add `held_drafts` to it.
## Config
```json5
{
plugins: {
entries: {
"held-drafts": {
enabled: true,
config: {
gateActions: ["send", "reply", "forward", "broadcast"],
extraTools: [], // e.g. your email plugin's send tool
exemptAgents: [], // agents whose sends bypass the gate
autoPromoteAfter: null, // e.g. 3 — promote a scope after 3 approvals
timeoutMs: 180000, // then fail closed
severity: "warning"
}
}
}
}
}
```
Approval cards resolve in any OpenClaw approval surface (Control UI buttons,
`/approve <id>` in chat). To route prompts to a specific channel, configure
`approvals.plugin` — see OpenClaw's plugin-approval docs.
## Security model
- The gate is deterministic code. No model judgment decides what is held.
- Fail closed: missing action, timeout, no approval surface — all block.
- Trust is scoped to one (agent, tool, channel, recipient) tuple; there is no
global "always allow".
- The agent-facing tool can only *read* the ledger and *revoke* trust. Promotion
is unreachable from the model.
- State is two human-readable files you can grep, diff, and back up:
`~/.openclaw/held-drafts/ledger.jsonl` and `trust.json`.
## Limitations (v0.1)
- Approval waits are capped by the gateway (10 minutes max). A draft that expires,
is cancelled, or finds no approval surface stays blocked, and the resolution the
gateway reports (e.g. `cancelled`) is appended to the ledger; ask the agent to
resend when you're back — the new attempt raises a fresh card. An async outbox that can hold drafts for hours
and send on later approval is the roadmap.
- Recipient extraction is best-effort across tool schemas; the full parameters are
always in the ledger regardless.
## Test
```bash
node --test
```
MIT.
tools
Comments
Sign in to leave a comment