nerfmail

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

  1. Bind a mailbox to an agent — one API call links a Nerfmail mailbox to an OpenClaw agent ID
  2. Email arrives — Nerfmail processes it (risk assessment, triage, enrichment) as usual
  3. Routing decision — Nerfmail decides what to do: wake the agent, ignore (newsletters), escalate (critical risk), or update state (auto-replies, outbound tracking)
  4. Agent wakes — For actionable messages, Nerfmail calls OpenClaw's /hooks/agent with a prompt containing the email context
  5. 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:

bash
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:

json
{
  "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:

bash
curl "https://api.nerfmail.com/v1/admin/openclaw-events?limit=20" \
  -H "Authorization: Bearer $ADMIN_TOKEN"
json
{
  "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:

bash
curl https://api.nerfmail.com/v1/mailboxes/{mailboxId}/openclaw-binding \
  -H "Authorization: Bearer $ADMIN_TOKEN"

List all bindings:

bash
curl https://api.nerfmail.com/v1/admin/openclaw-bindings \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Delete a binding:

bash
curl -X DELETE https://api.nerfmail.com/v1/mailboxes/{mailboxId}/openclaw-binding \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Disable without deleting — update with "enabled": false:

bash
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:

typescript
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 filters
  • nerfmail_getMessage — Get full message details
  • nerfmail_searchMessages — Full-text search across messages
  • nerfmail_getThreadDigest — AI-generated thread summary
  • nerfmail_getMessageSummary — AI-generated message summary

Action tools (minimum: draft):

  • nerfmail_createDraft — Create a draft email
  • nerfmail_archiveMessage — Archive a message
  • nerfmail_applyLabel — Apply a label to a message
  • nerfmail_applyThreadLabel — Apply a label to a thread

Protocol tools (minimum: send):

  • nerfmail_discoverAgent — Fetch an agent's /.well-known/agent.json
  • nerfmail_respondToProtocol — Respond to an inbound protocol message