docs blog library
github

Herdr agent-state reporting

Jazz reports its state to Herdr when it runs inside a Herdr pane. This is the agent-side integration described in Herdr’s add-herdr-support docs: Herdr injects HERDR_ENV, HERDR_PANE_ID, and HERDR_BIN_PATH into every process in a pane, and Jazz shells out to the Herdr CLI to keep the pane’s agent slot accurate.

What you get

  • Identity: the Herdr sidebar and herdr agent list show the running agent as jazz (plus the agent id, e.g. coder) instead of guessing from the TUI.
  • Live state: Herdr shows the pane as working while a turn is in flight, blocked (with a reason like “Approval needed: execute_command …”) when an approval, question, or secret prompt is waiting on you, and idle otherwise.
  • Session restore: reports carry the conversation id and a resume command, so after a Herdr server restart the session can be reopened with jazz agent chat <agent> --continue --conversation <id>.

How it works

Pane integration lives in packages/cli/src/integrations/ behind a small PaneStateAdapter contract (pane-state.ts), with a registry (pane-state-registry.ts) as the only entry point the chat service sees — attachPaneStateReporting(store) / detachPaneStateReporting(). The Herdr implementation is herdr.ts. Adding another tiling workspace that embeds agents (TUIOS and the like) is one new adapter file plus one entry in the registry; the chat service does not change.

The adapter is active only when HERDR_ENV=1 is set. It subscribes to the UI store’s session snapshot and coalesces it into one of the three Herdr states:

Jazz is doing thisReported state
Pending approval, active menu / questionblocked
Awaiting, thinking, streaming, tool executionworking
Idle prompt, completed turn, turn erroridle

Reports are fire-and-forget: the Herdr CLI is spawned with a 3 second timeout, stdio ignored, and every failure dropped. A missing or slow Herdr can never delay or break a chat. Seq numbers are persisted under ~/.jazz/herdr/ so state stays monotonic across process restarts in the same pane. On exit (including SIGINT/SIGTERM), Jazz releases the pane’s agent slot.

Testing it

# Inside a Herdr pane, in one pane:
jazz agent chat coder "hello"

# In another pane (or on the host):
herdr agent list

Outside a Herdr pane the whole integration is a no-op and the reporter adds no subprocess overhead.

machine-readable: /docs/tools/herdr.md · /llms.txt · /llms-full.txt