WorkflowRun
A WorkflowRun is one execution of the request chain an agent returned under workflow — see Agent workflows for how an agent produces one.
It is read-only over the API: a run exists because an agent produced it, and nothing outside the agent runner can create one.
Purpose
- Record what was called after an e-mail was processed, and what each destination answered.
- Make a failure diagnosable without re-running: the stored request and response are enough to see what happened.
- Give a webhook subscriber a terminal signal (
workflow.run.succeeded/workflow.run.failed) to act on.
Lifecycle
pending ──▶ running ──▶ success
└──▶ failed
Steps execute sequentially, and every step is attempted: a failing step is failed on its own, a step that references one that did not succeed is skipped (never sent), and the run is failed if any step failed. Nothing is retried automatically — a step is an arbitrary request to your systems, and repeating it could duplicate whatever it created.
Schema
| Field | Type | Description |
|---|---|---|
id | UUID | Internal id. |
workspace_id | UUID | Owning workspace. |
inbox_id / email_id / agent_id / agent_run_id | UUID | null | What produced the run. |
status | enum | pending, running, success, failed. |
definition | array | The workflow array exactly as the agent returned it, with placeholders not resolved. |
summary.total | int | Number of steps. |
summary.succeeded | int | How many completed successfully. |
summary.error | int | total - succeeded: steps that are failed plus steps that are skipped because they depended on one that did not succeed. A run can have several of each. |
error | string | null | Set when the run failed: every failed step, one per line, each as step <position>: <error>. |
duration_ms | int | null | Wall time of the whole chain. |
started_at / finished_at | datetime | null | |
created_at / updated_at | datetime | |
steps | array | Only on GET /v1/workflow-runs/{id} — the listing omits them. |
Step
| Field | Type | Description |
|---|---|---|
id | UUID | Internal id. |
position | int | 0-based index in the workflow, also the execution order. |
type | enum | request (the only step type today). |
status | enum | pending, running, success, failed, skipped. |
request.method | string | null | |
request.url | string | null | The URL as sent, with secret values replaced by [REDACTED]. |
request.headers | object | null | Same redaction. |
request.body | string | null | Same redaction, truncated to 4000 characters. An e-mail attachment referenced as base64 is shown as [attachment N: filename, content type, size], never as its bytes. |
request.form | object | null | Multipart fields of a form step, as sent. A file field is a { attachment, filename, content_type, size } descriptor of the e-mail attachment that was uploaded. null for a body step. |
response.status | int | null | |
response.headers | object | null | |
response.body | string | null | Truncated to 4000 characters. |
response.expected_status | int | null | The status that counts as success. null means any 2xx. |
error | string | null | Why the step failed. |
duration_ms | int | null | |
started_at / finished_at | datetime | null |
Endpoints
| Method | Path | Notes |
|---|---|---|
GET | /v1/workflow-runs | List. Keyset-paginated; filter by status, email_id, inbox_id, agent_id, agent_run_id, date ranges. |
GET | /v1/workflow-runs/{id} | One run with every step, in execution order. |
Scope: inbox/workflow_runs.
Example
{
"id": "9c8b7a65-4321-4fed-9876-0123456789ab",
"workspace_id": "a8b2c1d4-9e7f-4a3b-8c5d-1f2e3a4b5c6d",
"email_id": "e5f6a7b8-9c0d-4e1f-2a3b-4c5d6e7f8a9b",
"agent_run_id": "d5e6f7a8-9b0c-4d1e-2f3a-4b5c6d7e8f9a",
"status": "failed",
"definition": [
{
"type": "request",
"method": "POST",
"url": "https://erp.example.com/payables",
"headers": { "Authorization": "Bearer ${{secrets.FINANCE_TOKEN}}" },
"expected_status": 201
}
],
"summary": { "total": 1, "succeeded": 0, "error": 1 },
"error": "step 0: expected status 201, got 422",
"duration_ms": 318,
"steps": [
{
"position": 0,
"type": "request",
"status": "failed",
"request": {
"method": "POST",
"url": "https://erp.example.com/payables",
"headers": { "Authorization": "Bearer [REDACTED]" },
"body": null,
"form": null
},
"response": {
"status": 422,
"headers": null,
"body": "{\"error\":\"supplier not found\"}",
"expected_status": 201
},
"error": "expected status 201, got 422",
"duration_ms": 318
}
]
}