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

> ## Agent Instructions
> Treat this site as the source of truth for public Osmosis behavior.
> Distinguish the web Platform, the open source Python SDK, and the CLI.
> Use documented commands, configuration fields, and public APIs exactly as written; do not infer internal endpoints or services.

# LocalBackend In-Process Execution

> Run Osmosis AgentWorkflow and Grader classes in the current Python process with LocalBackend

`LocalBackend` runs an `AgentWorkflow` and optional `Grader` in the Python process that created the backend. It is the default starting point for rollout development and the backend used by the standard rollout scaffold.

<Info>
  `LocalBackend` is an execution strategy, not a laptop-only mode. The same entrypoint can run on your machine or on Platform-managed rollout infrastructure; in either case, the workflow shares the rollout server's process and filesystem.
</Info>

## Install

`LocalBackend` is part of the base `osmosis-ai` package. Add the `server` extra when exposing it through `create_rollout_server()`:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
pip install "osmosis-ai[server]>=0.3.0rc1,<0.4"
```

## Create a Rollout Server

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
from osmosis_ai.rollout import LocalBackend
from osmosis_ai.rollout.server import create_rollout_server

backend = LocalBackend(
    workflow=MyWorkflow,
    workflow_config=my_workflow_config,
    grader=MyGrader,
    grader_config=my_grader_config,
)

app = create_rollout_server(backend=backend)
```

The constructor is keyword-only. A workflow is required; grading is optional.

| Parameter         | Type                                 | Description                                                    |
| ----------------- | ------------------------------------ | -------------------------------------------------------------- |
| `workflow`        | `type[AgentWorkflow] \| str`         | `AgentWorkflow` subclass or `"module:attr"` import path        |
| `workflow_config` | `AgentWorkflowConfig \| str \| None` | Optional config instance or import path passed to the workflow |
| `grader`          | `type[Grader] \| str \| None`        | Optional `Grader` subclass or import path                      |
| `grader_config`   | `GraderConfig \| str \| None`        | Optional config instance or import path passed to the grader   |

Multiple classes can exist in the imported module. These arguments select the workflow, grader, and configs explicitly.

## Execution Lifecycle

<Steps>
  <Step title="Create the workflow context">
    The backend passes the request prompt and metadata into `AgentWorkflowContext`. It deep-copies the configured workflow config for that execution.
  </Step>

  <Step title="Run the workflow">
    The workflow runs in the current process under an active `RolloutContext`. Its explicit return value or registered sample source becomes the rollout sample.
  </Step>

  <Step title="Run the grader when applicable">
    After a successful workflow, the configured grader runs when the request has a label or metadata. It receives the sample, label, metadata, and artifact directory through `GraderContext`.
  </Step>

  <Step title="Return the result">
    Workflow and grader results are returned separately to the rollout server. Grading remains on the rollout's critical path: its latency or failure affects the completed result.
  </Step>
</Steps>

## Process and Isolation Model

`LocalBackend` deliberately provides no sandbox boundary:

* Workflow and grader code share the server's Python interpreter, installed packages, environment variables, filesystem, and event loop.
* Breakpoints, normal logging, stack traces, and print debugging work directly.
* A process crash, blocking call, global-state mutation, or dependency conflict can affect other rollouts in that server.
* Tools that modify files or spawn processes are not isolated between executions unless your code creates that isolation.

Use [HarborBackend](/sdk/execution-backends/harbor-backend) when each rollout needs a task-owned environment or isolated process and filesystem.

## Concurrency and Timeouts

`LocalBackend` uses `workflow_config.concurrency.max_concurrent` as its in-process execution limit:

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
from osmosis_ai.rollout import AgentWorkflowConfig, ConcurrencyConfig, LocalBackend

config = AgentWorkflowConfig(
    name="my-workflow",
    concurrency=ConcurrencyConfig(max_concurrent=8),
)

backend = LocalBackend(workflow=MyWorkflow, workflow_config=config)
```

| Configuration                              | Effective limit                     |
| ------------------------------------------ | ----------------------------------- |
| No `workflow_config`                       | `4` concurrent executions           |
| `max_concurrent=<n>`                       | At most `<n>` concurrent executions |
| Config provided with `max_concurrent=None` | No backend concurrency cap          |

`LocalBackend` does not enforce `agent_timeout_sec` or `grader_timeout_sec` itself. Those request fields do not interrupt in-process code. A `TimeoutError` raised by your code is categorized as a timeout, but a custom harness must enforce any hard deadline it requires outside the backend.

## Grading Rules

The grader is constructed after each successful workflow execution rather than shared across requests. It runs only when all of the following are true:

* `grader` is configured.
* The workflow result is successful.
* The request contains a label or metadata.
* The caller requested a grader completion result, as `create_rollout_server()` does for graded rollouts.

The grader must leave a reward on its sample unless it sets `remove_sample=True` to discard that sample. If no grader is configured, the workflow result can still succeed with an ungraded sample.

## Artifacts and Persistence

When writable, the backend gives the workflow and grader an artifacts directory under `~/.osmosis/<rollout-id>/artifacts`. Failure to create that directory degrades to `artifacts_dir=None`; it does not fail the rollout by itself.

ATIF persistence belongs to `create_rollout_server()`, not `LocalBackend`. A harness that calls `run_workflow()` or `execute()` directly must persist any trajectory it needs.

## Error Categories

`LocalBackend` converts uncaught workflow and grader exceptions into structured results:

| Exception                                   | Category           |
| ------------------------------------------- | ------------------ |
| `TimeoutError`                              | `TIMEOUT`          |
| `ValueError`, `TypeError`, `AssertionError` | `VALIDATION_ERROR` |
| Other exceptions                            | `AGENT_ERROR`      |

The full traceback is logged by the rollout server process; the result contains the exception message and category.

## When to Use LocalBackend

Use `LocalBackend` when you want:

* The shortest development and debugging loop.
* One workflow to process changing dataset prompts.
* The current Python environment to supply all dependencies.
* A lightweight custom evaluation or rollout harness.

Move to Harbor template mode when the prompt-driven workflow is correct but tools or dependencies need a reusable isolated environment. Move to Harbor dataset mode when each task already owns its instruction and verifier.

## Next Steps

<CardGroup cols={2}>
  <Card title="AgentWorkflow" icon="robot" href="/sdk/agent-workflow">
    Implement the agent behavior that LocalBackend executes.
  </Card>

  <Card title="HarborBackend" icon="cube" href="/sdk/execution-backends/harbor-backend">
    Add per-trial task environments or reuse existing Harbor tasks.
  </Card>
</CardGroup>
