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

# Background Agent Runs — Async Execution API

> Submit agent runs that execute asynchronously and poll for completion — ideal for long-running tasks and batch processing pipelines.

Background runs let you submit an agent task and receive an immediate acknowledgement, then poll for the result at your own pace. This is the right choice for long-running analyses, batch processing, and workflow steps where you cannot hold an HTTP connection open for the full duration of execution.

All requests require a valid bearer token in the `Authorization` header.

***

## Submit a background run

```
POST /api/agents/{agentId}/runs/background
```

Queues the agent run for asynchronous execution and returns immediately with a `runId` and `status: "QUEUED"`. The request accepts the same body as the [synchronous run endpoint](/api/agents/run).

### Path parameters

<ParamField path="agentId" type="string" required>
  The unique identifier of the agent to run.
</ParamField>

### Request body

<ParamField body="message" type="string" required>
  The user's input or query for the agent.
</ParamField>

<ParamField body="sessionId" type="string">
  UUID of an existing session to continue. Omit to start a new session — the server generates one automatically.
</ParamField>

<ParamField body="userId" type="string">
  Associates the run with a specific user for memory scoping and audit trails.
</ParamField>

<ParamField body="orgId" type="string">
  Tenant identifier for multi-tenant deployments.
</ParamField>

<ParamField body="generateFollowups" type="boolean" default="false">
  When `true`, the agent generates suggested follow-up questions appended to the output.
</ParamField>

<ParamField body="media" type="object[]">
  Array of multimodal inputs. Each entry contains `type` (MIME type) and `data` (base64 or URL).
</ParamField>

<ParamField body="options" type="object">
  Optional model overrides (`model`, `temperature`, `maxTokens`).
</ParamField>

### Response

<ResponseField name="runId" type="string" required>
  Unique identifier for the queued run. Use this to poll for status.
</ResponseField>

<ResponseField name="status" type="string" required>
  Always `"QUEUED"` on successful submission.
</ResponseField>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url "http://localhost:8080/api/agents/finance_agent/runs/background" \
    --header "Authorization: Bearer {token}" \
    --header "Content-Type: application/json" \
    --data '{
      "message": "Analyze Q3 2025 earnings for the top 10 S&P 500 constituents.",
      "userId": "user_abc123",
      "sessionId": "550e8400-e29b-41d4-a716-446655440000"
    }'
  ```
</CodeGroup>

**Example response**

```json theme={null}
{
  "runId": "run_7f3a9c12-4e2b-4d1a-8c5f-abc123def456",
  "status": "QUEUED"
}
```

***

## Poll for run status

```
GET /api/agents/{agentId}/runs/{runId}/status
```

Returns the current state of a background run as an `AgentRun` entity. Poll this endpoint until `status` reaches a terminal state (`COMPLETED`, `FAILED`, or `CANCELLED`).

<ParamField path="agentId" type="string" required>
  The agent that owns the run.
</ParamField>

<ParamField path="runId" type="string" required>
  The run identifier returned when the background run was submitted.
</ParamField>

**Run status values**

| Status      | Description                                                                                       |
| ----------- | ------------------------------------------------------------------------------------------------- |
| `QUEUED`    | The run has been accepted and is waiting in the job queue.                                        |
| `RUNNING`   | The agent is actively processing the request.                                                     |
| `COMPLETED` | Execution finished successfully. Check `output` for the response.                                 |
| `FAILED`    | An unrecoverable error occurred.                                                                  |
| `PAUSED`    | The agent triggered a Human-in-the-Loop gate. Call `/runs/{runId}/continue` to approve or reject. |
| `CANCELLED` | The run was cancelled via `DELETE /api/agents/{agentId}/runs/{runId}`.                            |

<ResponseField name="id" type="string">
  The run ID.
</ResponseField>

<ResponseField name="agentId" type="string">
  The agent that executed this run.
</ResponseField>

<ResponseField name="sessionId" type="string">
  The session this run belongs to.
</ResponseField>

<ResponseField name="status" type="string">
  Current execution status.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO-8601 timestamp when the run was queued.
</ResponseField>

<ResponseField name="completedAt" type="string">
  ISO-8601 timestamp when the run reached a terminal status. `null` while still running.
</ResponseField>

<ResponseField name="output" type="string">
  The agent's response content, available when `status` is `"COMPLETED"`.
</ResponseField>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url "http://localhost:8080/api/agents/finance_agent/runs/run_7f3a9c12/status" \
    --header "Authorization: Bearer {token}"
  ```
</CodeGroup>

**Example response (completed)**

```json theme={null}
{
  "id": "run_7f3a9c12-4e2b-4d1a-8c5f-abc123def456",
  "agentId": "finance_agent",
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "COMPLETED",
  "createdAt": "2026-05-06T10:00:00Z",
  "completedAt": "2026-05-06T10:00:47Z",
  "output": "## Q3 2025 Earnings Summary\n\nApple (AAPL): Revenue $94.9B, EPS $1.64..."
}
```

***

## Batch status polling

```
GET /api/agents/{agentId}/runs/status?runIds=id1,id2,id3
```

Check the status of up to 100 background runs in a single HTTP request. Run IDs that have no corresponding record are silently omitted from the response.

<ParamField path="agentId" type="string" required>
  The agent that owns the runs.
</ParamField>

<ParamField query="runIds" type="string" required>
  Comma-separated list of run IDs to check. Maximum 100 IDs per request.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url "http://localhost:8080/api/agents/finance_agent/runs/status?runIds=run_7f3a9c12,run_8a4b2d34,run_9c5e3f56" \
    --header "Authorization: Bearer {token}"
  ```
</CodeGroup>

**Example response**

```json theme={null}
[
  {
    "id": "run_7f3a9c12-4e2b-4d1a-8c5f-abc123def456",
    "status": "COMPLETED",
    "createdAt": "2026-05-06T10:00:00Z",
    "completedAt": "2026-05-06T10:00:47Z"
  },
  {
    "id": "run_8a4b2d34-1c3e-4f2a-9d6b-bcd234ef5678",
    "status": "RUNNING",
    "createdAt": "2026-05-06T10:01:00Z",
    "completedAt": null
  }
]
```

***

## Polling loop example

The following TypeScript example submits a background run and polls for completion with exponential backoff:

<CodeGroup>
  ```typescript TypeScript theme={null}
  interface AgentRun {
    id: string;
    status: string;
    output?: string;
    completedAt?: string;
  }

  async function runInBackground(
    agentId: string,
    message: string,
    token: string
  ): Promise<AgentRun> {
    const baseUrl = "http://localhost:8080";

    // Submit the background run
    const submitRes = await fetch(
      `${baseUrl}/api/agents/${agentId}/runs/background`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ message }),
      }
    );

    const { runId } = await submitRes.json();
    console.log(`Run queued: ${runId}`);

    // Poll until terminal state
    const TERMINAL = new Set(["COMPLETED", "FAILED", "CANCELLED"]);
    let delayMs = 1000;

    while (true) {
      await new Promise((r) => setTimeout(r, delayMs));

      const statusRes = await fetch(
        `${baseUrl}/api/agents/${agentId}/runs/${runId}/status`,
        { headers: { Authorization: `Bearer ${token}` } }
      );

      const run: AgentRun = await statusRes.json();
      console.log(`Status: ${run.status}`);

      if (TERMINAL.has(run.status)) {
        if (run.status === "COMPLETED") {
          console.log("Output:", run.output);
        } else {
          console.error("Run did not complete:", run.status);
        }
        return run;
      }

      // Exponential backoff, capped at 10 seconds
      delayMs = Math.min(delayMs * 1.5, 10_000);
    }
  }

  runInBackground(
    "finance_agent",
    "Analyze Q3 2025 earnings for the top 10 S&P 500 constituents.",
    "your-token-here"
  );
  ```
</CodeGroup>

<Note>
  For batch workloads, use the batch status endpoint (`?runIds=...`) instead of individual polling calls. Checking 10 runs at once with one request every 3 seconds uses \~20 requests/minute compared to \~200 for individual polls.
</Note>
