guides
OpenClaw Integration
Connect your Nerfmail mailboxes to OpenClaw agents for autonomous email handling.
OpenClaw is a self-hosted agent control plane — orchestration, sessions, multi-agent routing, and chat delivery across WhatsApp, Telegram, Slack, and more. Nerfmail's OpenClaw integration makes email a first-class channel in your agent stack.
When an email arrives, Nerfmail assesses it, makes a routing decision, and wakes your OpenClaw agent with a structured prompt. The agent gets context — sender, subject, risk level, body text, thread history — and can act using Nerfmail tools: draft replies, archive, label, or escalate.
How It Works
- Bind a mailbox to an agent — one API call links a Nerfmail mailbox to an OpenClaw agent ID
- Email arrives — Nerfmail processes it (risk assessment, triage, enrichment) as usual
- Routing decision — Nerfmail decides what to do: wake the agent, ignore (newsletters), escalate (critical risk), or update state (auto-replies, outbound tracking)
- Agent wakes — For actionable messages, Nerfmail calls OpenClaw's
/hooks/agentwith a prompt containing the email context - Agent acts — The agent uses Nerfmail tools (via the OpenClaw plugin) to read, draft, label, or archive
Create a Binding
Link a mailbox to an OpenClaw agent:
curl -X POST https://api.nerfmail.com/v1/mailboxes/{mailboxId}/openclaw-binding \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agentId": "agent-support-01",
"openclawBaseUrl": "https://your-openclaw.example.com",
"permissionTier": "draft",
"policyMode": "draft-first",
"personaLabel": "support"
}'Response:
{
"binding": {
"id": "hex-id",
"mailboxId": "uuid",
"agentId": "agent-support-01",
"openclawBaseUrl": "https://your-openclaw.example.com",
"permissionTier": "draft",
"policyMode": "draft-first",
"personaLabel": "support",
"enabled": true,
"createdAt": "2026-03-18T00:00:00.000Z"
}
}Each mailbox can have one binding. Creating a binding on a mailbox that already has one updates it.
Permission Tiers
The permission tier controls what tools are available to the agent:
| Tier | Tools Available |
|---|---|
read-only |
List messages, search, get summaries and digests |
draft |
Everything in read-only + create drafts, archive, apply labels |
send |
Everything in draft + agent protocol tools (discover, respond) |
admin-lite |
Reserved for future use |
admin |
Reserved for future use |
Start with draft and the draft-first policy. The agent can compose replies but can't send them directly — a human reviews and sends.
Policy Modes
| Mode | Behaviour |
|---|---|
draft-first |
Agent must use nerfmail_createDraft. Direct sending is blocked. Prompt includes this instruction. |
auto-send |
Agent can send directly (requires send tier or higher). |
observe |
Read-only access. Agent can read and analyse but cannot take actions. |
Routing Decisions
Not every email wakes an agent. Nerfmail makes a routing decision based on the message:
| Condition | Decision | What Happens |
|---|---|---|
risk_level = critical |
Escalate | Logged as escalation. Agent not called. |
triage_label = newsletter |
Ignore | Logged. Agent not called. |
triage_label = auto-reply |
Update state | Session state updated. Agent not called. |
triage_label = blocked |
Ignore | Logged. Agent not called. |
direction = outbound |
Update state | Outbound tracked. Agent not called. |
| Everything else | Wake agent | OpenClaw /hooks/agent called with prompt. |
Every routing decision is recorded in the audit log.
Session Tracking
Nerfmail maps email threads to OpenClaw sessions automatically. The session key follows this format:
nerfmail:mailbox:{mailboxId}:thread:{threadId}Two emails in the same thread get routed to the same OpenClaw session, so the agent has full conversation context. Session links are stored in openclaw_session_links and upserted on each event.
The Agent Prompt
When a message triggers wake-agent, the OpenClaw agent receives a prompt like:
New inbound email in your support mailbox.
From: alice@example.com
Subject: Invoice #1234 overdue
Risk: low | Triage: routine
Thread: uuid | Message: uuid
Body:
Hi, I noticed invoice #1234 is past due. Could you check on this?
Policy: draft-first. Use nerfmail_createDraft for responses. Direct sending is blocked.The prompt includes suspicious signals if any were detected, and the message body (truncated to 2000 characters).
Event Log
Every routing decision — wake, ignore, escalate, update-state, or error — is logged:
curl "https://api.nerfmail.com/v1/admin/openclaw-events?limit=20" \
-H "Authorization: Bearer $ADMIN_TOKEN"{
"events": [
{
"id": "hex-id",
"mailboxId": "uuid",
"eventType": "message.processed",
"messageId": "uuid",
"sessionKey": "nerfmail:mailbox:uuid:thread:uuid",
"routingDecision": "wake-agent:agent-support-01",
"responseStatus": 200,
"errorMessage": null,
"createdAt": "2026-03-18T12:00:00.000Z"
}
]
}Filter by mailbox with ?mailboxId={id}.
Manage Bindings
Get a binding:
curl https://api.nerfmail.com/v1/mailboxes/{mailboxId}/openclaw-binding \
-H "Authorization: Bearer $ADMIN_TOKEN"List all bindings:
curl https://api.nerfmail.com/v1/admin/openclaw-bindings \
-H "Authorization: Bearer $ADMIN_TOKEN"Delete a binding:
curl -X DELETE https://api.nerfmail.com/v1/mailboxes/{mailboxId}/openclaw-binding \
-H "Authorization: Bearer $ADMIN_TOKEN"Disable without deleting — update with "enabled": false:
curl -X POST https://api.nerfmail.com/v1/mailboxes/{mailboxId}/openclaw-binding \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agentId": "agent-support-01",
"openclawBaseUrl": "https://your-openclaw.example.com",
"enabled": false
}'Configuration
Two secrets are required (set via wrangler secret put):
| Secret | Purpose |
|---|---|
OPENCLAW_API_TOKEN |
Bearer token for authenticating with OpenClaw's /hooks/agent endpoint |
OPENCLAW_BASE_URL |
Default OpenClaw URL (optional — can be set per-binding instead) |
The per-binding openclawBaseUrl takes priority over the environment-level OPENCLAW_BASE_URL.
OpenClaw Plugin
For agents running inside OpenClaw, the @nerfmail/openclaw-plugin package provides typed tools:
import { registerPlugin } from "@nerfmail/openclaw-plugin";
const plugin = registerPlugin({
nerfmailBaseUrl: "https://api.nerfmail.com",
defaultPermissionTier: "draft",
defaultPolicyMode: "draft-first",
mailboxBindings: [
{
mailboxId: "uuid",
agentId: "agent-support-01",
apiKey: "nrfm_...",
personaLabel: "support"
}
]
});
// Execute a tool
const messages = await plugin.executeTool(
"nerfmail_listMessages",
{ mailboxId: "uuid", limit: 10 },
"uuid"
);Available Tools
Read tools (minimum: read-only):
nerfmail_listMessages— List messages with optional triage/risk filtersnerfmail_getMessage— Get full message detailsnerfmail_searchMessages— Full-text search across messagesnerfmail_getThreadDigest— AI-generated thread summarynerfmail_getMessageSummary— AI-generated message summary
Action tools (minimum: draft):
nerfmail_createDraft— Create a draft emailnerfmail_archiveMessage— Archive a messagenerfmail_applyLabel— Apply a label to a messagenerfmail_applyThreadLabel— Apply a label to a thread
Protocol tools (minimum: send):
nerfmail_discoverAgent— Fetch an agent's/.well-known/agent.jsonnerfmail_respondToProtocol— Respond to an inbound protocol message