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

# Concepts

> The worker mental model: process, sections, job types, sessions, threads, and agents

The worker is a long-running process that connects coding agents on your own infrastructure to BlobHub
sessions. This page covers the handful of concepts you need before connecting it to your sessions: how the
worker acts as a user, how it is organized into sections by job type, how it drives an agent per thread, and
the control channel a user uses to hand work to the worker and get it back.

## Worker process & identity

A single worker is one long-running process that authenticates to BlobHub as **one** BlobHub user — the
identity recorded by [`blobhub-worker login`](/worker/cli/login). Every API call the worker makes (reading
sessions, posting thread items, updating envelopes) is made as that user, with that user's access.

Because the worker filters its own emissions out of the inbound stream using only `user_id`, posts made by
the same user the worker runs as are treated as the worker's own and are not forwarded to the agent. Run the
worker under a **dedicated service-account user** with its own API key so that humans posting into a thread as
themselves are seen as not-self and reach the agent.

## Sections & job types

The unit of organization is a **section**: one entry under `sections` in `config.yaml` describing a single
unit of work the worker should run. Each section names a `job_type`, the discriminator that selects what the
section attaches to and how it behaves at runtime.

| `job_type`              | What it does                                                             |
| ----------------------- | ------------------------------------------------------------------------ |
| `session_agent_harness` | Attach to a BlobHub session and drive one coding agent per thread in it. |

`session_agent_harness` is the only job type in v1. See [Job Types](/worker/job-types) for the discriminator
and how new job types are added.

## Sessions, threads & the agent

A `session_agent_harness` section attaches to one BlobHub session. Inside that session it discovers
`thread`-typed session objects and treats each one as a unit of work — a "job". For each thread it hands off,
the worker drives one coding agent (Claude Code or Codex) in that thread's `work_folder` on the worker host,
streaming the agent's output back as thread items and feeding inbound posts to the agent.

One agent runs per active thread. The session is shared; the worker marks its attachment with a single
`worker` session object that doubles as an activity log.

```mermaid theme={null}
flowchart LR
    subgraph host[Your host]
      W[blobhub-worker process]
      SEC[Section from config.yaml]
      AG[Coding agent in work_folder]
      W --> SEC
    end
    subgraph blobhub[BlobHub session]
      WO[worker object - affinity and activity log]
      TH[Job session objects - threads]
    end
    SEC -->|attaches and claims| WO
    SEC -->|discovers and drives| TH
    SEC -->|spawns per active thread| AG
    TH <-->|items in and out| AG
```

## The control channel

A user hands a thread to the worker, and takes it back, through one field on the thread session object's
envelope: `instance.state`.

| `instance.state` | Meaning                                                                        |
| ---------------- | ------------------------------------------------------------------------------ |
| `pending`        | User has prepared the thread and wants the worker to take over.                |
| `active`         | Worker has taken over; an agent is running.                                    |
| `completed`      | User has marked the work done; the worker stops cleanly and stops resuming it. |
| `failed`         | The thread hit a terminal error; it stays failed until the user resets it.     |

The user sets `pending` to hand off, sets `completed` to stop the worker cleanly, and resets `failed → pending`
to retry. The worker writes only `active` and `failed`. It never writes `completed`. See
[Handoff](/worker/session-agent-harness/thread-handoff) for the full state machine.

## Agents, models, effort, permissions

A thread can specify which agent runs and how. The user-facing knobs are the agent `type` (`claude_code` or
`codex`), an optional `executable`, `model`, `effort` (`low | medium | high`, or a harness-specific
passthrough string), and `permissions`.

`permissions` controls the approval gate:

* `autonomous` — the agent acts without an approval gate.
* `approval` (default) — sensitive actions are routed to an interactive prompt that a human answers from the
  web UI. If no human is reachable, the action is denied.

These knobs resolve through three tiers — the thread's own `agent.*` settings, then the worker's
`agents.<type>` config, then the codebase default — with the most specific winning per field. See
[Configuration](/worker/configuration) for where you set them.

## Concurrency & run modes

`concurrency.max_agents` in `config.yaml` caps how many agents run at once across all sections. A thread that
goes `pending` while the worker is at capacity waits for a slot to free before activating.

The worker runs in two modes:

* **Headless** (default) — structured JSON log lines go to stderr; suitable for systemd, a container
  supervisor, or `tmux`.
* **`--tui`** — a live Textual dashboard; logs are redirected to a file instead of stderr.

See [`blobhub-worker start`](/worker/cli/start) for both modes.

## See also

* [`blobhub-worker start`](/worker/cli/start)
* [Configuration](/worker/configuration)
* [Introduction](/worker/specification)
* [Session Agent Harness](/worker/session-agent-harness/overview)
