Webhooks
Get a signed HTTPS call when a run or a workflow run ends. The envelope, how to verify it, and the payload of workflow_run.completed and workflow_run.failed.
A webhook endpoint is a public HTTPS URL that webagent calls with one JSON body when something happens. Add endpoints in the dashboard under Settings, then Webhooks, or with POST /v1/settings/webhooks (admin role). Pick the events each endpoint receives. The signing secret is shown once, when you create the endpoint. Send a test.ping with POST /v1/settings/webhooks/:id/test (admin role). Recent deliveries are at GET /v1/settings/webhooks/:id/deliveries.
The URL must be public: the same guard as for the cloud browser applies, so a private or loopback address is refused. A Slack incoming-webhook URL gets { "text": "…" } instead of the envelope below.
The envelope
Every event has the same outer shape:
| Field | Meaning |
|---|---|
id | The id of the event. It stays the same when a failed delivery is retried, so you can drop duplicates |
type | The event name |
created_at | ISO 8601 time |
data | The payload of that event |
| Event | Sent when | data |
|---|---|---|
run.started | A skill run starts | runId, skill, version, sessionId |
run.completed | A skill run ends with passed | runId, skill, status, summary and reportUrl (both optional) |
run.failed | A skill run ends with failed, error, cancelled or denied | The same fields as run.completed |
workflow_run.completed | A workflow run settles with a verdict that is not fail or error | Workflow run payload |
workflow_run.failed | A workflow run settles with the verdict fail or error | Workflow run payload |
test.ping | You send a test. It always goes through | message |
Verify the signature
Every call has the header webagent-signature: t=<unix seconds>,v1=<hex>. v1 is the HMAC-SHA256, with your endpoint secret as the key, of the text <t>.<raw body>. Compute it over the raw body, before you parse it. Reject a call with a wrong signature or an old t. Roll the secret with POST /v1/settings/webhooks/:id/roll-secret.
Answer with a 2xx status. A failed delivery is retried with growing pauses for about a day, then given up. The deliveries list shows each attempt.
Workflow run events
A workflow run is one run of your tests, from the dashboard, the API, MCP, a schedule or CI. When it settles, one event is sent. workflow_run.failed is for the verdicts fail and error. workflow_run.completed is for every other settled run, and data.verdict says which. error means the test could not run to a result. It is not an app failure, so read data.verdict and data.counts before you open a bug.
{
"id": "<event id>",
"type": "workflow_run.failed",
"created_at": "2026-11-13T02:14:01.000Z",
"data": {
"runId": "wfr_us_xxxxxxxxxxxxxxxxxxxxxxxx",
"workflowId": "wf_us_xxxxxxxxxxxxxxxxxxxxxxxx",
"workflowKey": "checkout-flow",
"workflowVersion": 3,
"verdict": "fail",
"trigger": "ci",
"counts": { "cases": 2, "passed": 1, "failed": 1, "errored": 0, "running": 0 },
"ci": { "provider": "github", "repo": "acme/web", "pr": 12 },
"costMicros": 1200,
"startedAt": 1794536000000,
"endedAt": 1794536041000,
"durationMs": 41000,
"dashboardUrl": "https://webagent.lookover.ai/workflows/runs/wfr_us_xxxxxxxxxxxxxxxxxxxxxxxx"
}
}| Field | Meaning |
|---|---|
runId | The workflow run id (wfr_…) |
workflowId, workflowKey, workflowVersion | The saved workflow the run belongs to. null for an ad hoc run with no saved workflow, and workflowKey is null when the workflow has no key |
verdict | pass, fail, error or running. A settled run is not running |
trigger | manual, api, mcp, ci or schedule |
counts | cases, passed, failed, errored and running, and when set flaky and optionalFailed |
ci | Where a CI run came from: provider (github or other) and, when known, repo, ref, sha, pr and buildUrl. null when the run did not come from CI |
costMicros | The cost in millionths of a US dollar |
startedAt, endedAt | Unix time in milliseconds |
durationMs | How long the run took, in milliseconds |
dashboardUrl | The run page in the dashboard. Members of your project can open it |
The event has no case list. Read the full report with GET /v1/workflow-runs/:id or GET /v1/workflow-runs/:id/report.md, using runId. A CI key can read both.