Skip to main content

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:
The first endpoint submits a run. The second retrieves the available state of a run. The current implementation uses an in-process AutomationWorker backed by a thread pool. Run state and history use in-memory stores by default, so they should not be treated as durable across process restarts.

Background Run Architecture

The v0.1 architecture is:
The client receives a run identifier and can later use that identifier to inspect the run. Conceptually:
The exact state depends on when the run is inspected. A run may finish before the client makes its first status request.

Authentication

Background-run endpoints are protected by the BindAI API authentication layer. Clients must provide an API key using the Authorization header:
The server’s API key is configured through the BINDAI_API_KEY environment variable:
For example, retrieve a run with cURL:
When the server has a configured API key, a missing or invalid client key results in HTTP 401 Unauthorized. If BINDAI_API_KEY is not configured on the server, the authentication dependency raises a server-side configuration error instead. See the Authentication page for details.

Submit a Background Run

A new background run is submitted with:
The request body contains an automation identifier and an optional input value:
The automation_id identifies an automation definition already 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. Important: The current worker does not automatically pass this input into AutomationDefinition.run(). The stored run input and the automation’s execution input are separate concerns in v0.1.

Example Request

Using cURL:
The API looks up the configured automation and submits it to the AutomationWorker.

Submission Response

A successful submission returns HTTP 202 Accepted. The response includes information about the created run. For example:
This is an illustrative response. The actual status and timestamps depend on the run’s state when the response is constructed. Background execution can begin before the client receives the response, so the status may differ from pending. The returned id is the run identifier used to query the run later.

What HTTP 202 Accepted Means

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:
A 202 Accepted response does not mean the automation completed successfully. It means the request was accepted for background execution.

Get Run Status

A submitted run can be inspected with:
For example:
The API checks the worker’s state store and run history. If the run is available in either source, the API returns its stored state. Otherwise, it returns HTTP 404 Not Found.

Run Response

A run response contains fields corresponding to the AutomationRun model:
A completed run can look like this:
The output structure depends on the automation definition. Clients should inspect the returned status rather than assume a particular state immediately after submission.

Run Lifecycle

The AutomationWorker creates an AutomationRun before scheduling its background execution. The run lifecycle is conceptually:
The run records timestamps for its lifecycle:
  • created_at — when the run was created.
  • started_at — when execution started.
  • completed_at — when execution reached a completed or failed state.
Timestamps that have not yet been set are null. Timestamps are represented as UTC-aware datetimes in the run model and serialized in the API response. The current status values include pending, running, completed, and failed.

Polling

A client can poll the run endpoint until execution reaches a terminal state:
Use a sensible polling interval rather than repeatedly requesting the endpoint as quickly as possible. For workloads with many long-running executions, an application-level notification mechanism may be more appropriate. Notifications are not provided by these two endpoints.

Python Client Example

A Python application can submit a background run using the requests library:
The client can then query the run:
These examples demonstrate submission and retrieval. They do not implement a polling loop or guarantee that the run has completed when the first response is received.

JavaScript Example

A JavaScript application can submit a run using fetch:
The returned run ID can then be used to retrieve the execution state:

Run Input

The submission request supports an optional input value:
The supplied value is stored on the AutomationRun. Its meaning is application-specific. An important v0.1 detail is that the current AutomationWorker invokes the automation definition using:
It does not currently invoke:
Therefore, the API’s input field should be understood as stored run data, not as an argument automatically passed to the automation definition. Applications that require input-driven execution must 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:
The API does not dynamically create arbitrary automation definitions from the HTTP request. The referenced automation must already be configured and available to the BindAI API application.

Definition Version

Background runs include the automation definition version. For example:
This information identifies the definition version associated with the run and can help when diagnosing executions after an automation definition changes. It should not be interpreted as a guarantee that the entire execution environment, external services, or dependencies are reproducible.

Run State

Run state includes execution metadata such as:
Not every field will have a meaningful value at every stage. For example, a newly created run may not yet have started_at, completed_at, output, or error populated.

Successful Runs

A completed run can contain an output value:
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:
This is an illustrative response; the actual error value depends on the execution failure. A failed run represents an execution failure rather than an authentication or submission failure. For example:
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 HTTP 404 Not Found. For example:
returns a not-found response. Clients should handle a missing run ID separately from a run whose status is failed. Because the default stores are in memory, a previously known run may no longer be available after the application process restarts.

Background Worker

The v0.1 API uses an AutomationWorker for background execution. The worker uses an in-process ThreadPoolExecutor, with a default of four worker threads. Its responsibilities include:
  • Creating AutomationRun instances.
  • Saving run state.
  • Submitting background work.
  • Updating the run lifecycle state.
  • Recording completed or failed runs in history.
Conceptually:
Applications using the worker directly can configure it separately. The thread-pool implementation is process-local; it is not a distributed worker service.

Worker Submission

The worker exposes two related background-submission operations. The simple form returns a Future:
Calling future.result() waits for that future to finish. It should not be used in the HTTP request path if the intention is to return immediately without waiting for execution. The lower-level form returns both the run and the future:
submit_with_run() saves the newly created AutomationRun before background execution proceeds. This lets the API obtain the run information without waiting for the automation to finish. Note: In the current worker implementation, input is stored on the run; it is not passed as an argument to AutomationDefinition.run().

Synchronous Worker Execution

AutomationWorker also supports synchronous execution:
This executes the automation in the current thread. As with background submission, the supplied input is stored on the run but is not automatically passed to AutomationDefinition.run(). 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 runs inside the application process:
It is not a separate distributed worker service. If the application process stops, in-process background work can be interrupted. The run is not automatically transferred to another process or server.

In-Memory State and History

The default run state store and run history are in-memory implementations. They support storing and retrieving run information while the process is running, but their contents do not survive a process restart. The current implementation therefore does not provide durable run-state storage by default. The worker’s state-store and history interfaces allow alternative implementations, but durable persistence depends on configuring and implementing a suitable backend. It should not be assumed to exist in a default v0.1 deployment.

No Distributed Queue

The v0.1 background-run implementation does not provide a distributed message queue. For example:
Each process has its own worker. There is no built-in cross-process coordination between these workers, and their default in-memory state and history are separate.

Horizontal Scaling

Running multiple API instances does not automatically create one shared background execution system. For example:
Worker A and Worker B operate independently. A production deployment that requires coordinated background execution should introduce a suitable queue and shared persistence layer.

Durable Execution

The v0.1 worker should not be considered a durable distributed job system. A distributed architecture might look like:
Such an architecture can support coordination across multiple processes and machines, depending on its implementation. Persistent queues, coordinated workers, and durable run-state storage are outside the current default v0.1 implementation.

Background Runs vs Streaming

Background runs and streaming serve different purposes. Background runs:
Streaming:
Use background runs when the client does not need to keep the original submission request open until execution finishes. Use streaming when the client wants to consume agent output progressively through a live HTTP response. See the Streaming page for the streaming API.

Background Runs vs Synchronous Execution

Synchronous execution keeps the request open while execution completes:
Background execution separates submission from execution:
This can be useful for longer-running operations, provided the process-local execution and persistence limitations are acceptable.

Background Runs and Automation Scheduling

Background runs are different from scheduled automation. A background run is explicitly submitted through the API:
Scheduling determines when work should be due to run:
Scheduling and background execution can be combined by application code, but they represent different concerns. The background-run endpoints do not themselves provide a complete recurring scheduler.

Background Runs and Observability

BindAI’s event system can emit runtime events during execution. Depending on the execution path, 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, and custom logging. Additional metrics or tracing integrations require separate implementation. The event recorder is not a distributed background-run state store. Event recording and run-state persistence are separate concerns:
Do not assume that every event is automatically stored with the run or exposed through the run-status endpoint.

Error Handling

Background execution can fail for reasons similar to other BindAI executions, including:
  • Model provider errors.
  • Tool errors.
  • Workflow errors.
  • Connection failures.
  • External-service failures.
  • Invalid automation configuration.
  • Application errors.
The worker records execution exceptions as run failures. Clients should inspect the run’s status and error fields rather than assume that a successfully submitted run will always complete successfully.

Retries

The current AutomationWorker does not automatically retry failed runs. Retry behavior configured elsewhere in an automation or workflow should be treated separately from the worker’s basic execution lifecycle. Clients should not blindly resubmit failed background runs, especially when external side effects are involved. For example:
A repeated run can create duplicate external operations if the original operation 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 or 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 automations that use tools and connections to external services. Protect the run endpoints accordingly. Recommended practices include:
  • Use strong API keys.
  • Use HTTPS outside trusted local development environments.
  • 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 grants access to the protected API endpoints. Treat it as a privileged credential.

Input and Output Data

Run input and output can contain application data.
Applications should consider whether this data contains personal information, credentials, internal identifiers, confidential business data, or external-service responses. Avoid exposing 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 and deployment restarts.
  • Container restarts.
  • Worker capacity and execution duration.
  • External-service reliability.
  • Retry behavior and idempotency.
  • Monitoring and alerting.
  • Run-state persistence.
  • Failure recovery.
  • Access control for automation execution.
The process-local worker provides a lightweight background execution mechanism. It is not a replacement for a durable distributed job system when reliable recovery, shared state, or cross-instance coordination is required.

Docker

Background runs execute inside the BindAI API process in the v0.1 deployment model. Conceptually:
If the container stops, in-process background work can be interrupted. The default in-memory run state and history are also lost when the process terminates. Running additional containers does not automatically create a coordinated worker pool.

Docker Compose

Docker Compose can run the BindAI API locally:
The background worker runs inside the API process according to the current architecture. This can be suitable for local development and deployments where the process-local execution limitations are acceptable. A distributed production worker architecture requires additional infrastructure and configuration beyond the current setup.

API Health vs Run Health

The /health endpoint indicates basic API service availability:
It does not indicate that a particular background run is successful. These are separate checks:
A healthy API can contain failed background runs. Likewise, a run can fail while the API itself remains healthy.

Testing

The API package tests can be run with:
The broader repository tests can be run with:
Automation worker tests can be run with:
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.
These commands assume the corresponding test directories exist in the checked-out repository.

Current v0.1 Scope

The current background-run implementation provides:
  • Background run submission through the REST API.
  • Run identifiers.
  • Run status lookup.
  • Run input storage.
  • Run output and error fields.
  • Creation, start, and completion timestamps.
  • In-process automation workers.
  • Thread-pool background execution.
  • API-key authentication.
  • In-memory state and history implementations.
The implementation is intentionally lightweight. In-memory state and history should not be mistaken for durable storage.

Current Limitations

The default v0.1 background-run system does not provide:
  • A distributed message queue.
  • Durable distributed workers.
  • Cross-instance worker coordination.
  • Kubernetes-native job execution.
  • Built-in worker autoscaling.
  • Managed cloud workers.
  • Guaranteed execution after process failure.
  • Durable run-state storage by default.
  • Automatic worker retries.
  • Dead-letter queues.
  • Automatic propagation of the submitted input into AutomationDefinition.run().
These capabilities require additional implementation or infrastructure.

Future Distributed Execution

A future BindAI architecture could introduce a persistent queue:
Depending on its design, such an architecture could support durable job submission, worker coordination, multiple worker processes or machines, retry recovery, queue monitoring, horizontal scaling, and improved recovery after process failures. Queue-based execution is outside the current v0.1 implementation. For v0.1, background runs are appropriate when:
  • Work can execute inside the API process.
  • Interruptions during process restarts are acceptable.
  • A lightweight background execution model is sufficient.
  • Coordinated workers across multiple instances are not required.
  • The application can tolerate the default persistence limitations.
For workloads requiring durable distributed execution, use an external job system or implement a suitable persistent queue and worker architecture.

Example End-to-End Flow

A complete background-run flow looks like this:
The client does not need to keep the original submission request open while the automation executes. It can use the returned run ID to request the run’s available state separately.

Summary

BindAI v0.1 provides background automation execution through:
A client submits an automation and receives a run ID. It can then retrieve the run’s current state, including its status, output, error, and timestamps. The current implementation uses an in-process AutomationWorker backed by a thread pool. It stores run state and history in memory by default and does not automatically retry failed runs. The API’s input value is stored on the run. The current worker does not automatically pass it as an argument to AutomationDefinition.run(). The most important deployment limitation is that execution is process-local:
If the application process stops, in-process work can be interrupted, and default in-memory state and history do not survive the restart. Distributed queues, coordinated workers, and durable execution require additional infrastructure. For the initial v0.1 release, the background-run API provides a lightweight way to submit and inspect automation work without keeping the original HTTP request open until execution completes.