Skip to main content

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.

A Job Session Object is the unit of work a session_agent_harness section drives — a thread-typed session object whose metadata describes a workspace, an agent, and a control-channel state. The user prepares it; the worker watches the control channel, takes over when it goes pending, and drives one agent in the workspace. This page covers the static shape and ownership of that object; the lifecycle dynamics live in Handoff.

Wire metadata shape

Inside the thread envelope (value.thread.metadata), the worker reads and writes these blocks:
workspace:
  work_folder: /absolute/path/to/repo          # required
agent:
  type: claude_code | codex                     # required
  executable: claude                            # optional
  model: claude-sonnet-4-6                       # optional
  effort: low | medium | high | <passthrough>   # optional
  permissions: autonomous | approval            # optional (default: approval)
instance:
  state: pending | active | completed | failed  # the control channel
The envelope is created and updated via upload_session_object on the thread’s alias.

Required vs optional

  • workspace.work_folderrequired. An absolute path to the repository on the worker host.
  • agent.typerequired. One of claude_code or codex.
  • Everything else under agent.*optional. Omitted fields fall through the settings tiers below.

Field ownership and the control channel

The protocol relies on a strict ownership split; each side never modifies fields the other owns.
FieldWriter
workspace.*user only
agent.*user only
instance.stateuser and worker (see below)
instance.state is the control channel. The user drives the thread with it:
  • set pending to hand the thread to the worker,
  • set completed to stop the worker cleanly,
  • reset failed → pending to retry a failed thread.
The worker writes instance.state only to the values active and failed. It never writes completed (that is user-set), and it never writes a resume pointer or an error block to the wire. Failure detail lives locally and surfaces server-side as a thread_failed item in the worker activity thread — not on this envelope.

Agent settings resolution

Each agent setting resolves through three tiers, with the most specific winning per field:
  1. the thread’s own agent.* on this envelope,
  2. the worker’s agents.<type>.* in config.yaml,
  3. the codebase default.
Only permissions has a non-empty codebase default (approval); executable falls back to claude for claude_code and codex for codex. permissions controls the approval gate: autonomous runs without a gate, while approval routes sensitive actions to an interactive prompt that a human answers from the web UI, denying the action if no human is reachable. See Configuration for where the worker config tier is set.

Wire ↔ local mapping

The worker mirrors the envelope into a local thread.yaml on the worker host, but with a different field layout. The two must not be conflated:
Wire (envelope)Local (thread.yaml)
agent.typeworkspace.agent_type
instance.stateagent.state
The local thread.yaml keeps the agent type under workspace.agent_type and the state under agent.state, and it additionally holds two local-only fields that never appear on the wire:
  • agent.agent_session_id — the SDK resume pointer used to reattach the agent after a restart.
  • agent.error — the {code, message} detail of a local failure.
Because agent_session_id and the error block are local-only, a reader inspecting the wire envelope will never see them there; thread failures surface to other clients as a thread_failed activity item, and the local detail is what the worker uses to recover. See Filesystem Layout for the full local layout and Worker Session Object for the activity thread.

See also