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

# Author a backend

> Build a worker backend engine.

Author a worker backend plugin — the engine that runs background, scheduled, and distributed tools.

A backend is where tools run when they leave the request path — background, scheduled, and distributed execution. It is a single strategy object with one job: launch the task runtime that pulls work from the broker. The app core depends only on the `Backend` ABC and stays backend-agnostic; a concrete backend (celery, rq, arq) implements it and registers through the handle.

## Implement the contract

Subclass `Backend` and implement `launch` — start the worker runtime for the backend and keep it running. That is the whole abstract surface. This example has no separate runtime, so its `launch` returns immediately:

```python examples/backend/inline_backend.py theme={null}
"""A minimal fictional worker backend.

A backend is where tools run when they leave the request path — background,
scheduled, and distributed execution. It is a single strategy object with one
job: launch the task runtime that pulls work from the broker. The app core
depends only on the ``Backend`` ABC and stays backend-agnostic; a concrete
backend (celery, rq, arq) implements it and registers through the handle.

Propagating a config change across the fleet is NOT a backend concern — it is
the app's own internal worker bus. A backend-runtime process receives fleet ops
through that bus exactly like a serving HTTP worker, so a backend that registers
here requires the bus: set ``TAI_BUS_REDIS_URL`` (a placeholder host below), or
the boot rules refuse to start.

    # TAI_BUS_REDIS_URL=redis://redis.internal:6379/0
"""

from collections.abc import Sequence

from tai42_contract.app import tai42_app
from tai42_contract.backend import Backend


@tai42_app.backends.register_backend
class InlineBackend(Backend):
    async def launch(self, args: Sequence[str]) -> None:
        # Start the worker runtime that consumes the broker. An inline backend
        # has no separate runtime, so this returns immediately.
        return None
```

Propagating a config change across the fleet is **not** a backend concern. That is the app's own [worker bus](/concepts/worker-bus), internal infrastructure outside the plugin system. A backend-runtime process receives fleet ops through the bus exactly like a serving HTTP worker, so a backend carries no control-plane surface of its own — no subscription to join, no dispatchers to implement, no broadcast to confirm.

## Register through the handle

Decorate the class with `@tai42_app.backends.register_backend`, as the example does. Usable bare or called.

## Load it

The host selects the backend by naming its module under `backend_module`, then starts its worker runtime with `tai backend`.

```yaml manifest.yml theme={null}
backend_module: your_package.backend
```

```bash theme={null}
tai backend --manifest-path manifest.yml
```

A registered backend makes the deployment multi-process, so it **requires the worker bus** — the backend-runtime and server processes must converge on config reloads. Set `TAI_BUS_REDIS_URL`, or `tai backend` refuses to start.

Keep any broker driver behind an optional extra; document broker URLs and worker settings in your repository's README.

## Shipped implementations

Shipped backends appear in the [ecosystem catalog](/reference/catalog), each linking to its own repository.

## See also

* [Backends](/concepts/backends) — the execution model.
* [Schedule a tool](/guides/schedule-a-tool) — scheduled runs execute on the backend.
* [Python SDK reference](/reference/python-sdk) — the `Backend` contract surface.
