← Back to Plugins
Tools

Held Drafts

123Satyajeet123 By 123Satyajeet123 👁 7 views ▲ 0 votes

OpenClaw plugin: nothing sends until you've read it — approval cards on outbound sends, append-only audit ledger, deterministic per-scope trust ladder

GitHub

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

Loading comments...