Webhooks
Tulsk uses webhooks to receive results from OpenClaw agents running on remote VPS instances.
Agent result webhook
When an agent finishes work on an OpenClaw cluster, the bridge sidecar sends the result back to Tulsk via webhook.
Endpoint
POST /api/openclaw/webhook
Authentication
The request includes a webhookToken in the Authorization: Bearer header. This token is unique to each OpenClaw instance and stored in the database.
Payload
{
"success": true,
"response": "The agent's response text...",
"metadata": {
"agentRunId": "uuid",
"taskId": "uuid",
"agentId": "uuid",
"commentId": "uuid"
},
"runtime_metadata": {
"personaVersion": 1
},
"tokens_used": 1500,
"duration_ms": 25000
}What Tulsk does with it
- Verifies the webhook token
- Looks up the AgentRun record
- Updates the placeholder comment with the response text
- Marks the AgentRun as COMPLETED or FAILED
- Publishes a real-time event via Redis
- Increments the agent’s monthly run counter
- If the run has a
chatId, pushes the result as a Message to the EMA chat
Streaming webhook
For real-time token streaming, the bridge sends incremental chunks.
Endpoint
POST /api/openclaw/webhook/stream
When Redis is configured
The bridge publishes streaming chunks directly to Redis (Upstash REST API), bypassing the Tulsk API for lower latency. The frontend receives these via SSE from the task comments stream endpoint.
Heartbeat
The bridge sends a heartbeat every 60 seconds to confirm the VPS is alive.
Endpoint
POST /api/openclaw/heartbeat
What it does
- Updates the instance’s
lastSeenAttimestamp - Sets health status to HEALTHY
- If the instance was PROVISIONING, transitions to RUNNING
- Returns any pending config updates