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

# Background Runs

> Submit and inspect background automation runs through the BindAI REST API.

# Background Runs

BindAI v0.1 provides a REST API for submitting automation runs for background execution.

Background runs allow a client to submit work without keeping the original HTTP request open until the automation completes.

The API provides two endpoints:

```http theme={null}
POST /api/v1/runs
GET /api/v1/runs/{run_id}
```

The first endpoint submits a run.

The second endpoint retrieves the current or completed state of a run.

***

# Background Run Architecture

The v0.1 architecture is:

```text theme={null}
Client
   |
   | POST /api/v1/runs
   v
BindAI API
   |
   v
AutomationWorker
   |
   v
AutomationDefinition
   |
   v
AutomationRun
```

The client receives a run identifier and can later use that identifier to inspect the run.

Conceptually:

```text theme={null}
Submit
   |
   v
Run ID
   |
   v
Background Execution
   |
   +---- Running
   |
   +---- Completed
   |
   +---- Failed
```

The exact run state is determined by the current `AutomationRun` implementation.

***

# Authentication

Background-run endpoints are protected by the BindAI API authentication layer.

Clients must provide:

```http theme={null}
Authorization: Bearer <API key>
```

For example:

```bash theme={null}
curl \
  -H "Authorization: Bearer your-secret-key" \
  http://localhost:8000/api/v1/runs/example-run
```

The API key is configured through:

```text theme={null}
BINDAI_API_KEY=your-secret-key
```

See the [Authentication](./10.8%20authentication) page for details.

***

# Submit a Background Run

A new background run is submitted with:

```http theme={null}
POST /api/v1/runs
```

The request body contains:

```json theme={null}
{
  "automation_id": "my-automation",
  "input": {
    "message": "Process this request"
  }
}
```

The `automation_id` identifies an automation definition that has already been configured in the BindAI API application.

The `input` field is optional and can contain application-specific data.

The current API stores the supplied input on the resulting `AutomationRun`.

It should not be assumed that the current automation worker automatically passes this input into `AutomationDefinition.run()`. Applications should treat the stored run input and the automation definition's execution input as separate concerns until explicit input propagation is implemented.

***

# Example Request

Using cURL:

```bash theme={null}
curl \
  -X POST \
  -H "Authorization: Bearer your-secret-key" \
  -H "Content-Type: application/json" \
  -d '{
    "automation_id": "my-automation",
    "input": {
      "message": "Process this request"
    }
  }' \
  http://localhost:8000/api/v1/runs
```

The API looks up the configured automation and submits it to the `AutomationWorker`.

***

# Submission Response

A successful submission returns HTTP `202 Accepted`.

The response contains information about the created run.

A response can look like:

```json theme={null}
{
  "id": "run-id",
  "definition_id": "my-automation",
  "definition_version": 1,
  "status": "pending",
  "input": {
    "message": "Process this request"
  },
  "output": null,
  "error": null,
  "created_at": "2026-01-01T12:00:00Z",
  "started_at": null,
  "completed_at": null
}
```

The exact values depend on the current execution state.

The returned `id` is the run identifier used to query the run later.

***

# HTTP 202 Accepted

Background execution uses HTTP `202 Accepted` because the request submits work for execution rather than waiting for the automation to finish.

The request lifecycle is:

```text theme={null}
HTTP Request
     |
     v
Validate Request
     |
     v
Find Automation
     |
     v
Create Run
     |
     v
Submit to Worker
     |
     v
202 Accepted
     |
     v
Background Execution
```

The client should not interpret `202 Accepted` as successful completion of the automation.

It means that the run has been accepted for background execution.

***

# Get Run Status

A submitted run can be inspected with:

```http theme={null}
GET /api/v1/runs/{run_id}
```

For example:

```bash theme={null}
curl \
  -H "Authorization: Bearer your-secret-key" \
  http://localhost:8000/api/v1/runs/run-id
```

The API checks the available automation worker state and run history and returns the stored run state when the run is available.

***

# Run Response

A run response contains fields corresponding to the `AutomationRun` model:

```text theme={null}
id
definition_id
definition_version
status
input
output
error
created_at
started_at
completed_at
```

A completed run can look like:

```json theme={null}
{
  "id": "run-id",
  "definition_id": "my-automation",
  "definition_version": 1,
  "status": "completed",
  "input": {
    "message": "Process this request"
  },
  "output": {
    "result": "completed"
  },
  "error": null,
  "created_at": "2026-01-01T12:00:00Z",
  "started_at": "2026-01-01T12:00:01Z",
  "completed_at": "2026-01-01T12:00:05Z"
}
```

The exact output depends on the automation definition.

Clients should use the returned `status` rather than assuming a particular state immediately after submission.

***

# Run Lifecycle

The `AutomationWorker` creates an `AutomationRun` before submitting background execution.

The run is then updated as execution progresses.

Conceptually:

```text theme={null}
Run Created
    |
    v
Run Started
    |
    +--------> Completed
    |
    +--------> Failed
```

The run contains timestamps that describe this lifecycle:

```text theme={null}
created_at
    |
    v
started_at
    |
    v
completed_at
```

Some timestamps may be `null` while a run is still in progress.

***

# Polling

A client can poll the run endpoint until execution reaches a terminal state.

For example:

```text theme={null}
POST /api/v1/runs
       |
       v
    run-id
       |
       v
GET /api/v1/runs/{run-id}
       |
       +---- running ------+
       |                   |
       |                   v
       |              GET again
       |
       +---- completed
       |
       +---- failed
```

A client should use a sensible polling interval rather than repeatedly requesting the endpoint as quickly as possible.

For workloads with many long-running executions, a dedicated application-level notification mechanism may be more appropriate.

***

# Python Client Example

A Python application can submit a background run using an HTTP client.

For example:

```python theme={null}
import requests

base_url = "http://localhost:8000"

headers = {
    "Authorization": "Bearer your-secret-key",
    "Content-Type": "application/json",
}

response = requests.post(
    f"{base_url}/api/v1/runs",
    headers=headers,
    json={
        "automation_id": "my-automation",
        "input": {
            "message": "Process this request",
        },
    },
)

response.raise_for_status()

run = response.json()
run_id = run["id"]

print(f"Run submitted: {run_id}")
```

The client can then query the run:

```python theme={null}
status_response = requests.get(
    f"{base_url}/api/v1/runs/{run_id}",
    headers={
        "Authorization": "Bearer your-secret-key",
    },
)

status_response.raise_for_status()

print(status_response.json())
```

***

# JavaScript Example

A JavaScript application can submit a run using `fetch`:

```javascript theme={null}
const response = await fetch(
  "http://localhost:8000/api/v1/runs",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer your-secret-key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      automation_id: "my-automation",
      input: {
        message: "Process this request",
      },
    }),
  },
);

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const run = await response.json();

console.log("Run ID:", run.id);
```

The returned run ID can then be used to retrieve execution state.

***

# Run Input

The submission request supports an optional `input` value:

```json theme={null}
{
  "automation_id": "my-automation",
  "input": {
    "customer_id": "123",
    "operation": "process"
  }
}
```

The supplied value is stored on the `AutomationRun`.

The meaning of the input is application-specific.

An important v0.1 detail is that the current `AutomationWorker` stores this input on the run but invokes the automation definition using:

```python theme={null}
definition.run()
```

It does not currently call:

```python theme={null}
definition.run(input)
```

Therefore, the API's `input` field should currently be understood as **run metadata/state**, not as an automatic argument passed to the automation definition.

Applications that require input-driven execution should explicitly connect their input data to the automation's execution logic.

***

# Automation Definition

The `automation_id` identifies an automation definition configured in the BindAI application.

Conceptually:

```text theme={null}
automation_id
      |
      v
AutomationDefinition
      |
      v
AutomationWorker
      |
      v
AutomationRun
```

The API does not dynamically create arbitrary automation definitions from the HTTP request.

The automation must already be configured and available to the BindAI API application.

***

# Definition Version

Background runs include the automation definition version.

This allows a run to identify the version of the automation definition associated with it.

For example:

```json theme={null}
{
  "definition_id": "daily-report",
  "definition_version": 3
}
```

This information can be useful when diagnosing executions after an automation definition has changed.

***

# Run State

The run contains execution metadata such as:

```text theme={null}
id
definition_id
definition_version
status
created_at
started_at
completed_at
```

The timestamps provide a basic execution timeline:

```text theme={null}
created_at
    |
    v
started_at
    |
    v
completed_at
```

Not every timestamp is necessarily available at every stage.

For example, a newly created run may not yet have a `started_at` or `completed_at` value.

***

# Successful Runs

A completed run can contain an output value.

Conceptually:

```json theme={null}
{
  "status": "completed",
  "output": {
    "result": "success"
  },
  "error": null
}
```

The output format depends on the automation.

Clients should not assume that every automation returns the same structure.

***

# Failed Runs

A failed run can contain an error description.

Conceptually:

```json theme={null}
{
  "status": "failed",
  "output": null,
  "error": "Automation execution failed."
}
```

A failed run represents an automation execution failure rather than an authentication or HTTP submission failure.

For example:

```text theme={null}
Valid API key
      |
      v
Run accepted
      |
      v
Automation execution
      |
      v
Failure
```

The API authentication can therefore succeed even when the background automation itself fails.

The worker records exceptions from automation execution as run failures.

***

# Run Not Found

If a requested run does not exist in the available worker state or history, the API returns a not-found response.

For example:

```http theme={null}
GET /api/v1/runs/unknown-run
```

results in:

```text theme={null}
404 Not Found
```

Clients should handle missing run IDs separately from failed executions.

***

# Background Worker

The v0.1 API uses an `AutomationWorker` for background execution.

The worker uses an in-process `ThreadPoolExecutor`.

Its responsibilities include:

* creating `AutomationRun` instances
* persisting run state
* submitting background work
* updating run lifecycle state
* recording completed or failed runs in history

Conceptually:

```text theme={null}
BindAI API Process

+-- FastAPI
|
+-- AutomationWorker
      |
      +-- Thread
      +-- Thread
      +-- Thread
      +-- Thread
```

The default worker configuration uses four worker threads.

Applications can configure the worker separately when using it directly.

***

# Worker Submission

The worker exposes two related background-submission operations.

The simple form returns a `Future`:

```python theme={null}
future = worker.submit(
    automation,
    input=payload,
)

run = future.result()
```

The lower-level form returns both the run and future immediately:

```python theme={null}
run, future = worker.submit_with_run(
    automation,
    input=payload,
)
```

`submit_with_run()` persists the newly created `AutomationRun` before background execution starts.

This allows the API to return the run information without waiting for the automation to complete.

***

# Synchronous Worker Execution

`AutomationWorker` also supports synchronous execution:

```python theme={null}
run = worker.run(
    automation,
    input=payload,
)
```

This executes the automation in the current thread.

The REST background-run endpoint uses background submission rather than synchronous execution.

***

# Process-Local Execution

The most important v0.1 limitation is that the worker is process-local.

The worker exists inside the application process:

```text theme={null}
Application Process

+---- BindAI API

+---- AutomationWorker
         |
         +---- Background Run
```

It is not a separate distributed worker service.

***

# What Process-Local Means

If the application process stops, background work running inside that process can be interrupted.

For example:

```text theme={null}
Application
    |
    v
Background Run
    |
    X
Process Stops
```

The run is not automatically transferred to another server or worker process.

This behavior is acceptable for the initial v0.1 deployment model but should be considered when designing production workloads.

***

# No Distributed Queue

The v0.1 background-run implementation does not provide a distributed message queue.

It does not automatically coordinate:

```text theme={null}
API Instance A
       |
       +---- Worker A

API Instance B
       |
       +---- Worker B
```

Each process has its own worker.

There is no built-in cross-process coordination between these workers.

***

# Horizontal Scaling

Running multiple API instances does not automatically create one shared background execution system.

For example:

```text theme={null}
Load Balancer
      |
      +---- API Instance A
      |         |
      |         +---- Worker A
      |
      +---- API Instance B
                |
                +---- Worker B
```

Worker A and Worker B operate independently.

A production deployment that requires coordinated background execution should introduce a persistent queue and dedicated workers.

***

# Durable Execution

The v0.1 worker should not be considered a durable distributed job system.

Durable execution generally requires persistent state and coordination outside the application process.

A future architecture can look like:

```text theme={null}
Client
   |
   v
BindAI API
   |
   v
Persistent Queue
   |
   +---- Worker A
   +---- Worker B
   +---- Worker C
   |
   v
Persistent Run State
```

This architecture allows work to be coordinated across multiple processes and machines.

That capability is outside the v0.1 scope.

***

# Background Runs vs Streaming

Background runs and streaming serve different purposes.

Background runs:

```text theme={null}
Client
   |
   v
Submit
   |
   v
Run ID
   |
   v
Background Execution
```

Streaming:

```text theme={null}
Client
   |
   v
Agent
   |
   +---- Output
   +---- Output
   +---- Output
```

Use background runs when the client does not need to maintain a live response connection.

Use streaming when the client wants to consume agent output progressively.

See the [Streaming](./10.9%20streaming) page for the streaming API.

***

# Background Runs vs Synchronous Execution

Synchronous execution keeps the request open while execution completes.

```text theme={null}
Client
   |
   v
API
   |
   v
Execution
   |
   v
Complete Result
   |
   v
Client
```

Background execution separates submission from execution:

```text theme={null}
Client
   |
   v
API
   |
   v
Run ID
   |
   v
Background Execution
```

This can be useful for longer-running operations.

***

# Background Runs and Automation Scheduling

Background runs are different from scheduled automation.

A background run is explicitly submitted through the API:

```text theme={null}
HTTP Request
    |
    v
Background Run
```

A scheduled automation is triggered according to an application's scheduling configuration:

```text theme={null}
Scheduler
    |
    v
Automation
```

Scheduling and background execution can be combined, but they represent different concerns.

***

# Background Runs and Observability

Background executions can produce runtime events through BindAI's event system.

Relevant events can include:

* agent events
* workflow events
* node events
* model events
* tool events
* memory events

BindAI Runtime also provides an in-memory `EventRecorder` for recording events emitted through an execution context's event bus.

This can support:

* debugging
* execution inspection
* custom logging
* future metrics integrations
* future tracing integrations

The event recorder is not a distributed background-run state store.

These are separate concerns:

```text theme={null}
Background Run Execution
        |
        v
AutomationWorker


Execution Events
        |
        v
EventBus / EventRecorder
```

***

# Error Handling

Background execution can fail for the same reasons as other BindAI executions.

Potential failures include:

* model provider errors
* tool errors
* workflow errors
* connection failures
* external-service failures
* invalid automation configuration
* application errors

The worker records execution failures on the `AutomationRun`.

Clients should inspect the run's `status` and `error` fields rather than assuming that a successfully submitted run will always complete successfully.

***

# Retries

The current `AutomationWorker` does not automatically retry failed runs.

Retry behavior, where supported by higher-level automation or workflow configuration, should be treated separately from the worker's basic execution lifecycle.

Clients should not blindly resubmit failed background runs.

For example:

```text theme={null}
Run
 |
 +---- Failure
        |
        v
     Retry?
        |
        +---- Yes
        |
        +---- No
```

Particular care is required for operations with external side effects.

A repeated run can create duplicate external operations if the original execution actually succeeded but its final state was not observed.

***

# Idempotency

Background operations should be designed with idempotency in mind.

This is especially important when an automation performs:

* API writes
* notifications
* emails
* database updates
* deployment operations
* ticket creation
* external workflow changes

Before retrying a run, determine whether repeating its external operations is safe.

Where an external service supports idempotency keys, applications should use them when appropriate.

***

# Security

Background runs can execute tools and connections with access to external services.

Protect the run endpoints accordingly.

Recommended practices include:

* use strong API keys
* use HTTPS
* protect external credentials
* limit connection permissions
* validate automation inputs
* avoid exposing secrets through run input or output
* avoid logging sensitive run data
* restrict access to state-changing automations

A valid API key provides access to the configured background-run API surface, so the API key should be treated as a privileged credential.

***

# Input and Output Data

Run input and output can contain application data.

For example:

```text theme={null}
Client Input
    |
    v
Background Run
    |
    v
Automation
    |
    v
Run Output
```

Applications should consider whether this data contains:

* personal information
* credentials
* internal identifiers
* confidential business data
* external-service responses

Do not expose sensitive run data unnecessarily.

Remember that the current worker stores submitted input on the run but does not automatically pass it to `AutomationDefinition.run()`.

***

# Production Considerations

Before using background runs in production, consider:

* process lifetime
* deployment restarts
* container restarts
* worker capacity
* execution duration
* external-service reliability
* retry behavior
* idempotency
* monitoring
* run-state persistence
* failure recovery

The process-local worker is suitable for the initial v0.1 deployment foundation but is not intended to replace a durable distributed job system.

***

# Docker

Background runs work inside the same BindAI API container when using the v0.1 Docker deployment.

Conceptually:

```text theme={null}
Docker Container

+---- BindAI API
|
+---- AutomationWorker
         |
         +---- Background Run
```

If the container stops, in-process background work can be interrupted.

Running additional containers does not automatically create a coordinated worker pool.

***

# Docker Compose

Docker Compose can run the BindAI API locally:

```bash theme={null}
docker compose up --build
```

The background worker runs inside the API process according to the v0.1 architecture.

This is suitable for local development and simple deployments.

A distributed production worker architecture requires additional infrastructure beyond the current Compose setup.

***

# API Health vs Run Health

The `/health` endpoint indicates basic API service availability:

```http theme={null}
GET /health
```

It does not indicate that a particular background run is successful.

These are separate checks:

```text theme={null}
/health
   |
   v
API Service Health


/api/v1/runs/{run_id}
   |
   v
Specific Run State
```

A healthy API can contain failed background runs.

Likewise, a particular run can fail while the API itself remains healthy.

***

# Testing

The API package includes tests for the background-run endpoints.

Run the API tests with:

```bash theme={null}
uv run pytest packages/bindai-api/tests -q
```

The broader repository tests can be run with:

```bash theme={null}
uv run pytest tests -q
```

Automation worker behavior is tested at the automation package level:

```bash theme={null}
uv run pytest packages/bindai-automation/tests -q
```

Relevant tests should cover:

* run submission
* run lookup
* authentication
* missing runs
* successful execution
* failed execution
* worker submission
* synchronous worker execution
* run state transitions
* history recording

***

# Current v0.1 Scope

BindAI v0.1 provides:

* background run submission
* run identifiers
* run status lookup
* run input storage
* run output
* run errors
* creation timestamps
* start timestamps
* completion timestamps
* in-process automation workers
* thread-pool background execution
* API-key authentication

The implementation is intentionally lightweight.

***

# Current Limitations

The v0.1 background-run system does not provide:

* distributed queues
* durable distributed workers
* cross-instance worker coordination
* Kubernetes-native job execution
* built-in worker autoscaling
* managed cloud workers
* guaranteed execution after process failure
* a distributed run-state database
* automatic worker retries
* dead-letter queues

These capabilities are outside the initial v0.1 scope.

***

# Future Distributed Execution

A future BindAI architecture can introduce a persistent queue:

```text theme={null}
Client
   |
   v
BindAI API
   |
   v
Persistent Queue
   |
   +---- Worker A
   +---- Worker B
   +---- Worker C
   |
   v
Persistent Run State
```

Such an architecture could provide:

* durable job submission
* worker coordination
* multiple worker processes
* multiple worker machines
* retry recovery
* queue monitoring
* horizontal scaling
* better process-failure recovery

Queue-based execution is planned for a future BindAI release and is not required for v0.1.

***

# Recommended Usage

For v0.1, background runs are appropriate when:

* the work can execute inside the API process
* losing in-process work during a process restart is acceptable
* a lightweight background execution model is sufficient
* the deployment does not require coordinated workers
* the application can handle the current persistence limitations

For workloads requiring durable distributed execution, use an external job system or wait for a future BindAI queue-based execution architecture.

***

# Example End-to-End Flow

A complete background-run flow can look like:

```text theme={null}
1. Client
      |
      | POST /api/v1/runs
      v
2. BindAI API
      |
      | Validate API key
      v
3. Find AutomationDefinition
      |
      v
4. AutomationWorker
      |
      | Submit execution
      v
5. AutomationRun
      |
      v
6. Background Execution
      |
      +---- Agent
      +---- Workflow
      +---- Tool
      +---- Connection
      |
      v
7. Run State / History
      |
      v
8. Client
      |
      | GET /api/v1/runs/{run_id}
      v
9. Result
```

The client does not need to keep the original submission request open while the automation executes.

***

# Summary

BindAI v0.1 provides background automation execution through:

```http theme={null}
POST /api/v1/runs
GET /api/v1/runs/{run_id}
```

A client submits an automation and receives a run ID:

```text theme={null}
Submit
  |
  v
Run ID
```

The client can then retrieve the run state:

```text theme={null}
Run ID
  |
  v
Run Status
  |
  +---- Running
  +---- Completed
  +---- Failed
```

The current implementation uses an in-process `AutomationWorker` backed by a thread pool.

The worker creates and tracks `AutomationRun` instances, executes automation definitions in background threads, persists state, and records completed or failed runs in history.

The current API's `input` value is stored on the run. It is not automatically passed as an argument to `AutomationDefinition.run()` by the current worker implementation.

The most important deployment limitation is:

```text theme={null}
Application Process
       |
       v
AutomationWorker
       |
       v
Background Run
```

If the application process stops, in-process work can be interrupted.

Distributed queues, coordinated workers, durable execution, and Kubernetes-based worker infrastructure are intentionally deferred beyond the v0.1 release.

For the initial public release, the background-run API provides a simple way to submit and inspect automation work while keeping the deployment architecture lightweight.
