Outbox & Background Workers
Relevant source files
The following files were used as context for generating this wiki page:
Opificia AI utilizes an outbox pattern and background workers to manage the lifecycle of AI-driven software tasks. These components ensure that agent actions—such as reading tickets, writing code in sandboxes, and opening pull requests—are processed reliably and asynchronously.
The system is built as a TypeScript-based NestJS application, utilizing PostgreSQL for persistence and a worker-based architecture to handle long-running "runs" that transform tickets into code changes.
Sources: AGENTS.md, CHANGELOG.md, README.md
Architecture Overview
The background worker system operates as part of the core server. It processes the "run" lifecycle, which transition through various stages such as planning and implementation. The architecture emphasizes self-hosting and model-agnosticism, allowing the workers to interact with different AI harnesses like Claude.
This diagram shows the flow of information from the database through the outbox worker to the external execution environments.
Sources: apps/server/src/worker/outbox.worker.ts, apps/server/src/worker/effects.service.ts, README.md
Components and Services
Outbox Worker
The Outbox Worker is responsible for monitoring the database for pending events or tasks that require side effects. It ensures that every stage transition in a run (e.g., run.queued to stage.started) is handled by the appropriate backend logic without blocking the main API response.
Key responsibilities include:
- Polling for unprocessed outbox entries.
- Dispatching tasks to the Effects Service.
- Managing task retries and failures.
Sources: apps/server/src/worker/outbox.worker.ts, apps/web/fixtures/runs.ts:18-35
Effects Service
The Effects Service executes the actual side effects required by the AI agents. When a run enters a specific stage, the Effects Service interacts with sandboxes and AI models to perform the work.
| Component | Description |
|---|---|
| Sandbox Isolation | Executes code and tests in a secure, isolated environment. |
| Harness Integration | Communicates with AI models (e.g., Claude) to generate plans and implementations. |
| Event Logging | Records agent.tool and agent.message events back to the database. |
Sources: apps/server/src/worker/effects.service.ts, AGENTS.md, apps/web/fixtures/runs.ts:40-60
Run Lifecycle and Event Flow
Background workers drive the "Loop" that Opificia is built around. This loop consists of five distinct steps that transition through background tasks.
- Ticket Ingestion: An issue is identified and a run is queued (
run.queued). - Planning Stage: The worker triggers the agent to read the repository and propose a plan (
plan.proposed). - Human Approval: The worker waits for a human to approve the plan (
plan.approved). - Implementation: The worker instructs the agent to write changes in the sandbox and run tests (
implementation.finished). - Pull Request: The worker opens a pull request with the finalized changes (
pr.opened).
Sources: apps/web/fixtures/runs.ts:20-150, README.md
Implementation Details
The implementation uses NestJS for structured service management. The OutboxWorker is typically decorated to run on a schedule or listen to a queue, while the EffectsService provides the logic for external communication.
Key Event Types processed by Workers
The following event types are commonly handled within the worker context:
run.queued: Initializes the background processing for a new ticket.stage.started: Sets up the environment for planning or implementation.agent.tool: Records an action taken by the AI agent (Read, Write, Bash, etc.).checks.completed: Finalizes the automated verification of the agent's work.
Sources: apps/web/fixtures/runs.ts:25-50, CHANGELOG.md
Summary
The Outbox and Background Worker system forms the engine of Opificia AI. By decoupling the agent's complex, long-running tasks from the user interface, the system provides a reliable way to automate software engineering while maintaining human oversight through approval gates. This architecture supports the project's goals of being self-hostable and resilient, as tasks can be resumed or retried by workers if the environment experiences interruptions.