> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bigdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Running a Workflow

> Submit a workflow that runs independently of your connection, read its result, watch it live, and cancel it.

A workflow can stream its result on the connection that started it, or run
independently of that connection. Those are the synchronous and asynchronous
execute endpoints.

Use the asynchronous endpoint for production integrations. The run is unaffected
if your client disconnects, its result is always stored, and you can attach to
it, cancel it, or come back to it later.

|                              | Synchronous                             | Asynchronous                                    |
| ---------------------------- | --------------------------------------- | ----------------------------------------------- |
| **Endpoint**                 | `POST /v1/workflow/execute`             | `POST /v1/workflow/execute/async`               |
| **Returns**                  | An SSE stream of the whole run          | An `execution_id`, immediately                  |
| **If your connection drops** | The run is cancelled                    | The run continues                               |
| **Result stored**            | Only with `persistence_mode: "enabled"` | Always                                          |
| **How you read the result**  | From the stream                         | Retrieve the run, or attach to its event stream |
| **Cancel**                   | Close the connection                    | Call the cancel endpoint                        |

The synchronous endpoint is still the shortest path to a first result, so the
[Workflows quickstart](/getting-started/quickstart_guide_workflows) uses it.
Reach for the asynchronous endpoint as soon as a run has to survive a dropped
connection, a page reload, or a deploy of your own service.

## Submit a run

`POST /v1/workflow/execute/async` takes the same body as the synchronous
endpoint -- a `template` (inline or a stored template id), `input`, `time_range`,
and `model_name` -- and returns `202 Accepted` straight away.

```python theme={null}
import requests

headers = {"X-API-KEY": my_api_key, "Content-Type": "application/json"}

resp = requests.post(
    "https://agents.bigdata.com/v1/workflow/execute/async",
    headers=headers,
    json={
        "template": template_id,
        "input": {"company_id": "D8442A"},
        "time_range": "last_30_days",
        "model_name": "base",
    },
    timeout=30,
)
resp.raise_for_status()
submitted = resp.json()

execution_id = submitted["execution_id"]
print(submitted["status"])   # pending
```

The `execution_id` is the handle for everything that follows: reading the
result, attaching to the event stream, cancelling, and resuming the run if it
stops early. Store it: nothing else identifies the run.

<Note>
  `persistence_mode` is not accepted here. Every submitted run is stored, because
  the stored run is how you read its result once the request that started it has
  returned. See [Stored runs and retention](#stored-runs-and-retention) below.
</Note>

## Read the result

Retrieve the run with `GET /v1/workflow/executions/{execution_id}` and check its
`status`. A run is finished when its status is `completed`, `error`, or
`cancelled`; while it is `pending` or `running`, its `events` are `null`.

```python theme={null}
import time

TERMINAL = {"completed", "error", "cancelled"}


def wait_for_run(execution_id: str, timeout_s: float = 1800.0) -> dict:
    url = f"https://agents.bigdata.com/v1/workflow/executions/{execution_id}"
    deadline = time.monotonic() + timeout_s
    delay = 2.0

    while time.monotonic() < deadline:
        run = requests.get(url, headers={"X-API-KEY": my_api_key}, timeout=30).json()
        if run["status"] in TERMINAL:
            return run
        time.sleep(delay)
        delay = min(delay * 1.5, 30.0)

    raise TimeoutError(f"{execution_id} did not finish in time")


run = wait_for_run(execution_id)

answer = "".join(
    event["content"] for event in run["events"] or [] if event["type"] == "ANSWER"
)
print(answer)
```

The `events` list is the run's streamed messages replayed in order, using the
same message types you get live. A handler written for the live stream replays a
stored run without changes. See
[Streaming responses](/how-to-guides/agents/concepts/streaming-responses) for the
full set, and [Execution history](/how-to-guides/agents/workflows/execution-history)
for the rest of the retrieval response.

## Watch a run live

Polling is enough for most integrations. If you want to show progress as it
happens -- the research plan filling in, the answer arriving token by token --
attach to the run's event stream:

`GET /v1/workflow/execute/async/{execution_id}/stream`

```python theme={null}
import json

url = f"https://agents.bigdata.com/v1/workflow/execute/async/{execution_id}/stream"

with requests.get(url, headers={"X-API-KEY": my_api_key}, stream=True, timeout=None) as r:
    r.raise_for_status()
    for raw_line in r.iter_lines(decode_unicode=True):
        if not raw_line or not raw_line.startswith("data: "):
            continue
        event = json.loads(raw_line[6:])
        delta = event.get("delta", {})
        if delta.get("type") == "ANSWER":
            print(delta.get("content", ""), end="", flush=True)
```

The run proceeds whether or not anything is listening, and disconnecting does
not stop it. You can attach after the run has already produced output and still
receive everything from the start.

### Resume a dropped stream

Every event on this stream carries an SSE `id`. If the connection drops,
reconnect to the same URL and send the last id you received in the standard
`Last-Event-ID` header. Delivery continues from that point instead of replaying
the run from the beginning.

```python theme={null}
headers = {"X-API-KEY": my_api_key}
if last_event_id is not None:
    headers["Last-Event-ID"] = last_event_id
```

A browser `EventSource` client does this for you: it tracks the last id and
sends the header on reconnect automatically.

<Note>
  A run that had begun answering and then starts its answer again emits a
  `STREAM_ROLLBACK` event telling you which events to discard. Handle it if you
  render answer text as it arrives -- see
  [`STREAM_ROLLBACK`](/how-to-guides/agents/concepts/streaming-responses#stream_rollback).
</Note>

## Cancel a run

`POST /v1/workflow/execute/async/{execution_id}/cancel` stops a running
workflow. The response reports the run's status once the cancellation was
applied, so you do not need to poll afterwards.

```python theme={null}
resp = requests.post(
    f"https://agents.bigdata.com/v1/workflow/execute/async/{execution_id}/cancel",
    headers={"X-API-KEY": my_api_key},
    timeout=30,
)
print(resp.json()["status"])   # cancelled
```

Cancelling is safe to repeat. A run that finished while your request was in
flight reports `completed` or `error` instead of `cancelled`. A cancelled run
keeps whatever it had produced, and you can continue it later.

## Continue a run that stopped early

A run that stopped before it finished -- one you cancelled, or one that ended in
an `error` -- can be continued from where it stopped. Pass its `execution_id` in
the submit body:

```python theme={null}
resp = requests.post(
    "https://agents.bigdata.com/v1/workflow/execute/async",
    headers=headers,
    json={"template": template_id, "execution_id": execution_id},
    timeout=30,
)
```

The run picks up from its last saved point rather than starting over, and keeps
the same `execution_id`.

<Warning>
  This is a resume, not a follow-up turn. A run that is still `pending` or
  `running` cannot be continued, and neither can one that already `completed`.
  Both return `409`. To start another piece of research, submit a new run.
</Warning>

## Stored runs and retention

Every submitted run is stored, so you decide how long to keep it. List your
runs, retrieve any one of them, and delete the ones you no longer need:

* `GET /v1/workflow/executions` -- your runs, newest first
* `GET /v1/workflow/executions/{execution_id}` -- one run with its full result
* `DELETE /v1/workflow/executions/{execution_id}` -- remove a run permanently

Deleting a run that is still in progress stops it first. There is no undo.
[Execution history](/how-to-guides/agents/workflows/execution-history) covers
these endpoints in full.

## Error responses

Alongside the [usual HTTP errors](/how-to-guides/agents/concepts/error-handling),
the stream and cancel endpoints share one error contract:

| Status | Meaning                                                                   | What to do                                                                                 |
| -----: | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|  `404` | No such execution, or it is not yours.                                    | Check the `execution_id`. Do not retry.                                                    |
|  `409` | The run has already finished, so there is nothing to attach to or cancel. | Read the result from `GET /v1/workflow/executions/{execution_id}`.                         |
|  `503` | The run was accepted but is not ready to act on yet.                      | Transient. Retry the same request after the number of seconds in the `Retry-After` header. |

On submit, `409` means something different: the `execution_id` you asked to
continue cannot be continued, because it is still in progress or has already
completed.

## Next steps

<CardGroup cols={2}>
  <Card title="Execution history" icon="clock-rotate-left" href="/how-to-guides/agents/workflows/execution-history">
    List, retrieve, and delete your stored runs.
  </Card>

  <Card title="Streaming responses" icon="bolt" href="/how-to-guides/agents/concepts/streaming-responses">
    Every message type the stream can emit, and a handler that dispatches on `type`.
  </Card>

  <Card title="Creating templates" icon="file-code" href="/how-to-guides/agents/workflows/creating_templates">
    Template anatomy, input placeholders, content filters, and research plans.
  </Card>

  <Card title="Conversation continuity" icon="comments" href="/how-to-guides/agents/concepts/conversation-continuity">
    How `execution_id` compares with Research Agent chats and checkpoints.
  </Card>
</CardGroup>
