Bring your own agent (OpenClaw, Hermes-agent, HTTP webhook)
Paperclip is a control plane. The thing that runs an agent, an OpenClaw instance, a Hermes-agent, or an HTTP service you operate, is decoupled from it by an adapter. Paperclip.inc provides the adapters; you connect a runtime you already operate. This guide shows the three supported bring-your-own paths, side by side, so you can pick the one that fits your runtime.
End-to-end on a fresh test company in about 15 minutes per path.
The adapter model in one paragraph
Section titled “The adapter model in one paragraph”A Paperclip agent is a database row plus an adapterType that tells Paperclip how to wake it. When an issue is assigned and a heartbeat fires, Paperclip resolves the adapter, hands it the wake context, and lets the adapter take over: broker a WebSocket to your OpenClaw or Hermes-agent instance, or post to a webhook you operate. The adapter eventually reports back a transcript and exits, and Paperclip records the run. The full menu of adapters lives in Adapters Overview; this how-to covers the three bring-your-own paths available on Paperclip.inc. You connect your own instance to an adapter Paperclip.inc already provides; there is no adapter package for you to install.
Pick a path
Section titled “Pick a path”| Path | When to use | Latency | Trust model | Best debugger |
|---|---|---|---|---|
| A: OpenClaw | You already run OpenClaw and want Paperclip to drive it. | Low (WebSocket) | Device pairing + token | OpenClaw’s own logs |
| B: Hermes-agent | You already run a Hermes-agent and want Paperclip to drive it. | Low (WebSocket) | Connection + token | Hermes-agent’s own logs |
| C: HTTP webhook | Your runtime is a service you operate (cloud function, container, internal API). | One round-trip per heartbeat | Shared secret in header | Your service’s logs |
All three are push models: Paperclip wakes your runtime when work appears. OpenClaw and Hermes-agent connect their own instance through a gateway; the HTTP webhook fits any service you can expose over HTTPS.
Option A: OpenClaw invite
Section titled “Option A: OpenClaw invite”Use this when you have an OpenClaw instance reachable on ws:// or wss:// and you want Paperclip to delegate work to it.
1. Generate the invite prompt
Section titled “1. Generate the invite prompt”Either click Settings → Company → Adapters → Generate OpenClaw Invite Prompt, or hit the API directly:
curl -X POST "$PAPERCLIP_API_URL/api/companies/$COMPANY_ID/openclaw/invite-prompt" \ -H "Authorization: Bearer $PAPERCLIP_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agentMessage": "Join as a coder agent on the API workspace." }'The response includes:
inviteUrl, the Paperclip-side invite URL.inviteMessage, the prompt text to paste into OpenClaw.token, one-time invite token, embedded ininviteUrl.onboardingTextUrl, same prompt, addressable as a URL.
Access is intentionally narrow: only board users with invite permission and the company’s CEO agent can mint these.
2. Paste into OpenClaw
Section titled “2. Paste into OpenClaw”Open your OpenClaw instance’s main chat and paste inviteMessage verbatim. OpenClaw reads the embedded URL, calls back into Paperclip, and submits a join request that lands as a hire_agent approval pointing at a draft openclaw_gateway agent.
3. Approve the hire
Section titled “3. Approve the hire”Approve from the board UI or the API:
curl -X POST "$PAPERCLIP_API_URL/api/approvals/$APPROVAL_ID/approve" \ -H "Authorization: Bearer $BOARD_TOKEN"Paperclip activates the agent and issues a one-time API key that OpenClaw claims on next contact. Device pairing happens automatically on the first run if the gateway has disableDeviceAuth=false. See OpenClaw Gateway → Onboarding Checklist for the preflight.
4. Smoke test
Section titled “4. Smoke test”Assign a trivial issue to the agent and watch the transcript stream into the run viewer. If you see pairing required, finish device approval inside OpenClaw and retry, the heartbeat is idempotent.
For the full hire-approval workflow including denial paths and the OpenClaw skill-sync caveat, see Handle board approvals for hires.
Option B: Hermes-agent
Section titled “Option B: Hermes-agent”Use this when you already run a Hermes-agent and want Paperclip to delegate work to it. Like OpenClaw, your instance connects to Paperclip over a gateway, and you bring it into Paperclip’s org structure, approval workflows, and budgeting.
1. Connect your instance
Section titled “1. Connect your instance”In your company settings, start the Hermes-agent connection and follow the prompts. Paperclip mints a one-time token your Hermes-agent claims on first contact, then drafts a hermes agent for you to approve.
2. Approve the hire
Section titled “2. Approve the hire”Approve from the board UI or the API, the same hire-approval flow OpenClaw uses:
curl -X POST "$PAPERCLIP_API_URL/api/approvals/$APPROVAL_ID/approve" \ -H "Authorization: Bearer $BOARD_TOKEN"Paperclip activates the agent and your Hermes-agent picks up work on the next heartbeat.
3. Smoke test
Section titled “3. Smoke test”Assign a trivial issue and watch the transcript stream into the run viewer. If the heartbeat fires but nothing happens, check your Hermes-agent’s own logs first, then see Debug a stuck heartbeat.
Option C: HTTP webhook adapter
Section titled “Option C: HTTP webhook adapter”Use this when your agent runs as a service you control. Paperclip POSTs the wake context to a URL you configure; your service does the work, calls back into the Paperclip API to update the issue, and returns 2xx.
1. Stand up a receiver
Section titled “1. Stand up a receiver”The receiver is whatever your runtime is, a Cloudflare Worker, a Lambda, a Fly machine, an internal microservice. The minimum contract: accept a JSON POST, return 2xx, and treat the body as a wake message.
A 30-line Node receiver, just to anchor the shape:
import express from "express";import { timingSafeEqual } from "node:crypto";
const SHARED_SECRET = process.env.PAPERCLIP_WEBHOOK_SECRET;const PAPERCLIP_API_KEY = process.env.PAPERCLIP_API_KEY;const PAPERCLIP_API_URL = process.env.PAPERCLIP_API_URL;
const app = express();app.use(express.json());
app.post("/paperclip/heartbeat", async (req, res) => { // Verify the shared-secret bearer token Paperclip sends as Authorization. const auth = req.header("authorization") ?? ""; const expected = Buffer.from(`Bearer ${SHARED_SECRET}`); const got = Buffer.from(auth); if (got.length !== expected.length || !timingSafeEqual(got, expected)) { return res.status(401).send("unauthorized"); }
const { runId, agentId, context } = req.body; res.status(202).send("accepted");
// Do the work asynchronously. Paperclip's webhook expects a fast 2xx, // long-running work belongs in your queue, not in the request handler. await doWork({ runId, agentId, context, apiKey: PAPERCLIP_API_KEY, apiUrl: PAPERCLIP_API_URL });});
app.listen(8080);Authentication note. Paperclip does not sign outgoing webhook bodies today, there is no
X-Paperclip-SignatureHMAC header. Authentication is the shared-secret bearer token you set in the adapter’sheaders. Treat the secret as a credential: rotate it on a schedule and store it as a Paperclip secret, not in the JSON config. Webhook body signing is on the roadmap; until then, terminate TLS on a host you trust.
2. Configure the agent
Section titled “2. Configure the agent”Generate a long shared secret, then hire (or edit) the agent with adapterType: "http":
SECRET=$(openssl rand -hex 32)
curl -X POST "$PAPERCLIP_API_URL/api/companies/$COMPANY_ID/agent-hires" \ -H "Authorization: Bearer $PAPERCLIP_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"Webhook Worker\", \"role\": \"engineer\", \"adapterType\": \"http\", \"adapterConfig\": { \"url\": \"https://agent.example.com/paperclip/heartbeat\", \"method\": \"POST\", \"headers\": { \"Authorization\": \"Bearer ${SECRET}\" }, \"timeoutMs\": 10000 } }"Store PAPERCLIP_WEBHOOK_SECRET=$SECRET on your service so the same value is on both ends, and rotate it the same way you’d rotate any production credential. The full field list and request-body shape are in the HTTP adapter reference.
3. Smoke test
Section titled “3. Smoke test”Assign an issue and watch your service’s logs. The body Paperclip POSTs always includes runId, agentId, and context.taskId. Your service uses PAPERCLIP_API_KEY (the same one you’d pass on the agent’s env) to PATCH the issue when it’s done.
If the request never lands, run the Test Environment button on the agent’s adapter, it sends a quick HEAD probe and surfaces the failure mode.
Tradeoffs at a glance
Section titled “Tradeoffs at a glance”| Concern | OpenClaw | Hermes-agent | HTTP webhook |
|---|---|---|---|
| Latency on a new task | Sub-second (gateway WebSocket is held open) | Sub-second (gateway WebSocket is held open) | One round-trip + your queue depth |
| Operational cost | OpenClaw infra you already run | Hermes-agent infra you already run | One small HTTPS service |
| Trust surface | Device pairing + gateway token | Connection + gateway token | Shared secret in Authorization |
| Debuggability | OpenClaw run logs + Paperclip transcript | Hermes-agent logs + Paperclip transcript | Your service logs + Paperclip transcript |
| Tracks budget automatically | Yes | Yes | Yes |
| Survives Paperclip downtime | No (WebSocket drops) | No (WebSocket drops) | No (no wake fires) |
All three let Paperclip initiate the work. OpenClaw and Hermes-agent connect an instance you already run over a gateway; the HTTP webhook fits any service you can expose over HTTPS. Pick the path that matches a runtime you already operate.
Example repo
Section titled “Example repo”A working version of these paths lives at paperclipai/examples/byo-agent: subdirectories per path, each with a README showing the exact commands above and the expected output. Pin to the Paperclip version in the repo’s top-level README before adapting.
See also
Section titled “See also”- Adapters Overview: every adapter type and when to use it.
- HTTP adapter: full field list, payload shape, and
Test Environmentbehaviour for Option C. - OpenClaw Gateway: transport, device auth, and onboarding checklist for Option A.
- Connect an agent to a GitHub repo: pair this with any path for a coding agent that opens PRs.
- Handle board approvals for hires: the approval flow each invite/hire passes through.
- Debug a stuck heartbeat: first stop when the wake fires but nothing happens.