Agent BrainsAgent Brains

Connect an external operator to a web chat

Subscribe to signed webhooks, load conversation history, and hand an active web chat to an external operator.

Use the public API to mirror AgentBrains web chats into your own application. A webhook reports new messages and control changes. Your application can fetch structured history, take over an active web chat, send operator replies and return control to the AI.

Create a key and a subscription

In System Integration → API Keys, create a key with webhooks:manage, conversations:read and conversations:write. Set API_KEY in your shell and replace the example HTTPS URL and employee ID. Use a dedicated test employee and a fresh web chat for the first run.

API=https://api.agent-brains.com

curl --fail-with-body -sS "$API/webhooks" \
  -H "x-api-key: $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://receiver.example.com/agentbrains/events",
    "events": ["message.created", "conversation.control_changed"],
    "employee_ids": ["YOUR_TEST_EMPLOYEE_ID"]
  }'

Save the returned id as WEBHOOK_ID and store signing_secret in your receiver's secret storage. The create response returns the signing secret once. Pass an explicit employee filter to limit which chats can be forwarded. Omitting employee_ids or passing null subscribes to all employees in the workspace.

The receiver must use public HTTPS. Private addresses and redirects are unsupported. For a local receiver, forward only the test endpoint through an HTTPS tunnel and verify signatures before handling events. Use synthetic message text in a regular web chat with your test employee. Conversations flagged as synthetic QA tests are excluded from external webhook delivery.

Verify and process events

Every delivery is an HTTPS POST with these headers.

HeaderValue
X-AgentBrains-Event-IdStable event ID across retries
X-AgentBrains-TimestampDelivery attempt timestamp in Unix seconds
X-AgentBrains-Signaturev1= followed by a hex-encoded HMAC-SHA256

Compute the HMAC over the exact bytes of the timestamp, a dot, and the raw request body. Use the returned signing secret as a UTF-8 string. Reject timestamps more than five minutes from your clock and compare the signatures in constant time. Verify the signature before parsing JSON.

The event type reference documents the complete envelope and both payloads. Events contain a stable id, type, version, conversation_id, employee_id, sequence and data. The message.created data includes message_id, text, direction and sender type. It reports that RMS stored the message. The conversation.control_changed data includes the previous mode, current mode and control version.

Return a 2xx response after storing or durably enqueuing the event. Deduplicate by event ID and use sequence to order events within a conversation. Deliveries can arrive out of order. AgentBrains retries network failures, HTTP 408, 429 and 5xx for up to 24 hours. HTTP 410 disables the subscription. Use delivery history to inspect attempts and retry a retained failure while its subscription is still enabled with the same configuration.

Load state and history

Send a message in the fresh web chat and take conversation_id from the event. Store it as CONVERSATION_ID.

curl --fail-with-body -sS "$API/conversations/$CONVERSATION_ID" \
  -H "x-api-key: $API_KEY"

curl --fail-with-body -sS "$API/conversations/$CONVERSATION_ID/messages?limit=50" \
  -H "x-api-key: $API_KEY"

Pass next_cursor back as the URL-encoded cursor parameter to fetch the next page. To build a local history without missing concurrent updates, activate the subscription before fetching history, buffer events during pagination, and merge messages by message ID. The subscription starts with new events and does not replay old messages.

Take over, reply and resume

Read the current control_version before sending a control request. The example assumes the fresh chat returned 0. Use the version from your response.

curl --fail-with-body -sS -X PATCH "$API/conversations/$CONVERSATION_ID/control" \
  -H "x-api-key: $API_KEY" -H 'Content-Type: application/json' \
  -d '{"mode":"human","expected_version":0}'

curl --fail-with-body -sS "$API/conversations/$CONVERSATION_ID/messages" \
  -H "x-api-key: $API_KEY" -H 'Content-Type: application/json' \
  -d '{"body":"This is a test operator reply.","client_message_id":"operator-smoke-001"}'

The operator reply returns 202 Accepted. A sent delivery status means RMS handed the message to the channel. Retry a lost response with the same client_message_id and the same payload to get the existing message. Reusing that ID with different content returns 409.

Confirm the reply appears in the web chat and that the receiver gets a message.created event. Switch back to AI with the latest control version returned by takeover. In this example that version is 1.

curl --fail-with-body -sS -X PATCH "$API/conversations/$CONVERSATION_ID/control" \
  -H "x-api-key: $API_KEY" -H 'Content-Type: application/json' \
  -d '{"mode":"ai","expected_version":1}'

On a version conflict, read conversation state again before deciding whether to retry. After resuming, send a new message in the web chat to check that the AI replies. Messages received during human mode are not automatically replayed.

Finish the test

Review delivery status, then delete the temporary subscription. Deleting it cancels queued deliveries. An HTTP request already in progress can finish.

curl --fail-with-body -sS "$API/webhooks/$WEBHOOK_ID/deliveries?limit=50" \
  -H "x-api-key: $API_KEY"

curl --fail-with-body -sS -X DELETE "$API/webhooks/$WEBHOOK_ID" \
  -H "x-api-key: $API_KEY"

Revoke the temporary key and stop the test receiver when finished. See the API reference for request schemas and error responses.

On this page