Files
paperclip/packages/adapters/openclaw
Dotta a251a53571 fix(openclaw): embed explicit heartbeat workflow in wake text
Include the full Paperclip API workflow (checkout, fetch, update) and
endpoint bans in the wake text sent to OpenClaw agents, preventing
them from guessing non-existent endpoints. Applied to both openclaw
and openclaw_gateway adapters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:52:01 -06:00
..
2026-03-04 14:51:33 -06:00
2026-02-26 16:32:59 -06:00

OpenClaw Adapter Modes

This document describes how @paperclipai/adapter-openclaw selects request shape and endpoint behavior.

Transport Modes

The adapter has two transport modes:

  • sse (default)
  • webhook

Configured via adapterConfig.streamTransport (or legacy adapterConfig.transport).

Mode Matrix

streamTransport configured URL path behavior
sse /v1/responses Sends OpenResponses request with stream: true, expects text/event-stream response until terminal event.
sse /hooks/* Rejected (openclaw_sse_incompatible_endpoint). Hooks are not stream-capable.
sse other endpoint Sends generic streaming payload (stream: true, text, paperclip) and expects SSE response.
webhook /hooks/wake Sends wake payload { text, mode }.
webhook /hooks/agent Sends agent payload { message, ...hook fields }.
webhook /v1/responses Compatibility flow: tries /hooks/agent first, then falls back to original /v1/responses if hook endpoint returns 404.
webhook other endpoint Sends legacy generic webhook payload (stream: false, text, paperclip).

Webhook Payload Shapes

1) Hook Wake (/hooks/wake)

Payload:

{
  "text": "Paperclip wake event ...",
  "mode": "now"
}

2) Hook Agent (/hooks/agent)

Payload:

{
  "message": "Paperclip wake event ...",
  "name": "Optional hook name",
  "agentId": "Optional OpenClaw agent id",
  "wakeMode": "now",
  "deliver": true,
  "channel": "last",
  "to": "Optional channel recipient",
  "model": "Optional model override",
  "thinking": "Optional thinking override",
  "timeoutSeconds": 120
}

Notes:

  • message is always used (not text) for /hooks/agent.
  • sessionKey is not sent by default for /hooks/agent.
  • To include derived session keys in /hooks/agent, set:
    • hookIncludeSessionKey: true

3) OpenResponses (/v1/responses)

When used directly (SSE mode or webhook fallback), payload uses OpenResponses shape:

{
  "stream": false,
  "model": "openclaw",
  "input": "...",
  "metadata": {
    "paperclip_session_key": "paperclip"
  }
}

Auth Header Behavior

You can provide auth either explicitly or via token headers:

  • Explicit auth header:
    • webhookAuthHeader: "Bearer ..."
  • Token headers (adapter derives Authorization automatically when missing):
    • headers["x-openclaw-token"] (preferred)
    • headers["x-openclaw-auth"] (legacy compatibility)

Session Key Behavior

Session keys are resolved from:

  • sessionKeyStrategy: fixed (default), issue, run
  • sessionKey: used when strategy is fixed (default value paperclip)

Where session keys are applied:

  • /v1/responses: sent via x-openclaw-session-key header + metadata.
  • /hooks/wake: not sent as a dedicated field.
  • /hooks/agent: only sent if hookIncludeSessionKey=true.
  • Generic webhook fallback: sent as sessionKey field.

SSE (streaming endpoint)

{
  "url": "http://127.0.0.1:18789/v1/responses",
  "streamTransport": "sse",
  "method": "POST",
  "headers": {
    "x-openclaw-token": "replace-me"
  }
}

Webhook (hooks endpoint)

{
  "url": "http://127.0.0.1:18789/hooks/agent",
  "streamTransport": "webhook",
  "method": "POST",
  "headers": {
    "x-openclaw-token": "replace-me"
  }
}

Webhook with legacy URL retained

If URL is still /v1/responses and streamTransport=webhook, the adapter will:

  1. try .../hooks/agent
  2. fallback to original .../v1/responses when hook endpoint returns 404

This lets older OpenClaw setups continue working while migrating to hooks.