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

# Process Manager Tools

> Coordinate spawned work with handoff lifecycle tools.

## Overview

The process manager surface centers on the `handoff` lifecycle.
Use it to spawn a worker thread, run work synchronously or asynchronously, and manage progress/results.

### Tool Name

```json theme={null}
handoff
```

### Functions

1. `handoff` - Start a visible or hidden spawned thread, optionally targeting another bot.
2. `handoff_status` - Check current status for a handoff.
3. `handoff_send` - Send follow-up guidance into an existing handoff thread.
4. `handoff_results` - Retrieve final or intermediate results.
5. `handoff_cancel` - Cancel in-progress handoff execution.
6. `handoff_list` - List delegations that are still open.
7. `get_handoff_inputs` - Pull parent-thread inputs in chained workflows.
8. `store_blueprint_outputs` - Store outputs for downstream handoff consumers.
9. `mailbox_action` - Send a message to another thread's mailbox.

## `handoff`

Use `handoff(...)` to create the worker thread. These are the customer-controlled parameters used to decide where the work runs, how visible it is, and how Genesis reports the spawned thread back to the caller.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `task` | string | none | Required work description for the spawned thread. |
| `target_bot` | string or null | `null` | Optional target agent for delegation. |
| `thread_mode` | string | `spawn` | Thread execution mode. Allowed values: `spawn` or `inline`. |
| `visibility` | string | `visible` | `'visible'` (default) - thread is accessible to the user. `'hidden'` - thread is hidden from normal UI surfaces. |
| `show_in_thread_list` | boolean | `visible -> true; hidden -> false` | Controls whether the spawned thread appears in the sidebar by default. Use `false` for internal sub-threads and background work the user does not need to see unless they enable the filter. Use `true` for deliberate user-facing handoff threads, forked work, or mission threads the user should browse normally. |
| `thread_title` | string or null | `null` | Optional explicit title for the spawned thread. |
| `context_data` | object or null | `null` | Optional structured context passed into the child thread. |
| `blueprint_name` | string or null | `null` | Optional blueprint to launch in the spawned thread. |
| `blueprint_mode` | string | `manual` | Blueprint handoff mode. Allowed values: `manual`, `continuous`, or `goal`. |
| `async_mode` | boolean | `true` | When `true`, return immediately with a running handoff; no watcher infers completion for a plain delegation. When `false`, wait for the configured watch window. |
| `timeout_seconds` | integer | `300` | Synchronous watch window in seconds. When it closes, the call returns while the child keeps running and the handoff is stamped `watch_expired`; this is not an execution limit. Async handoffs return immediately and do not start a watcher, so this value does not determine child execution. |
| `on_completion` | string | `notify` | Completion behavior. `notify` — for a plain delegation, the child must report its finished, blocked, or failed result to the source thread with `mailbox_action`; that report records the handoff as complete. Blueprint handoffs notify after the blueprint mission completes and include stored outputs. `return` — return full results to the parent synchronously. `none` — no automatic parent notification. |
| `auto_redirect` | boolean | `false` | Ask supported clients to redirect into the new thread after creation. |
| `allowed_tools` | `string[]` or null | `null` | Optional list of tool names the spawned thread may use. Omit it or pass an empty list to leave all of the target's tools available. When the list is non-empty, Genesis enforces it at tool dispatch: calls to tools outside the list are refused and do not run. The list can only narrow tools the target already has; it cannot grant additional tools. For a plain delegation using `on_completion="notify"`, Genesis keeps `mailbox_action` available so the child can report back even when the supplied list omits it. This is a narrowing convenience, not a security boundary. If the child's thread state cannot be read, the scope falls back to the target's own tool set rather than blocking the child. |
| `include_parent_context` | boolean | `false` | Include parent-thread context in the spawned thread. |
| `stop_on_timeout` | boolean | `true` | Deprecated / no-op. A synchronous watcher never cancels the child thread when its window elapses, and async handoffs have no watcher. `handoff_cancel` stops tracking but does not stop a child already working. |
| `callback_url` | string or null | `null` | Optional webhook URL for a synchronous handoff (`async_mode=false`). The waiting caller posts the result; combining `callback_url` with `async_mode=true` is rejected. For asynchronous handoffs, have the child report with `mailbox_action` instead. |

Successful calls return `handoff_id`, `thread_id`, `status`, and `thread_link`. Genesis creates and persists the spawned thread before returning `thread_link`, so the link is immediately durable and clickable in chat, tool activity, and the **Artifacts** drawer.

When a watched handoff returns a child response, its `result` contains the child's
response text without runtime tool-announcement narration. Genesis uses that same
text in the saved result and parent notification; a `watch_expired` response's
`partial_result` is filtered the same way.

Example:

```python theme={null}
result = handoff(
    task="Review the generated model and summarize open risks",
    target_bot="Adam",
    visibility="visible",
    show_in_thread_list=True,
    async_mode=True,
    thread_title="Model Review",
)
```

```json theme={null}
{
  "success": true,
  "handoff_id": "handoff_abc123",
  "thread_id": "chat_xyz789",
  "status": "started",
  "thread_link": "[Model Review](thread-handoff://chat_xyz789?bot=Adam&title=Model+Review)"
}
```

## Typical Workflow

1. Start work with `handoff(...)`.
2. If async, poll `handoff_status(...)`.
3. Send clarifications with `handoff_send(...)` when needed.
4. Read outputs with `handoff_results(...)`.
5. Cancel with `handoff_cancel(...)` when the plan changes.

## `mailbox_action`

Use `mailbox_action(...)` to send one message to another agent's thread. A
plain child created with `handoff(..., on_completion="notify")` uses this tool
to report its final result, including when the work is blocked or failed. That
report is the completion signal for the handoff; Genesis records the handoff as
complete when the message is sent to the source thread.

Messages are delivered automatically into the recipient's conversation. When a
report closes a delegation whose recipient is still mid-turn, a short notice is
queued on that thread's next tool result. The report itself remains in the
recipient's mailbox, so the recipient can call
`mailbox_action(action="READ_MAIL")` immediately without ending the turn. The
successful result's `note` says whether this notice was queued or the message
will wait for normal delivery. If the recipient is idle, or the queued wake
cannot be accepted because the thread has reached its undelivered-wake limit,
the report waits for the normal delivery path instead. The background delivery
sweep is enabled by default, runs every 30 seconds, and only wakes threads when
agent-slot capacity is available. A newly queued message brings the sweep forward
for an eligible idle recipient instead of waiting for the next 30-second tick. A
turn started by this wake-up acts as the
thread's recorded owner for downstream permission checks, including the owner's
email when it is recorded. If no owner is recorded, or the owner is the system
default while authentication is enabled, the turn carries no user identity and
permission checks can refuse the operation.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | required | `SEND_MESSAGE` sends a message to another thread's mailbox. `READ_MAIL` returns and consumes mail waiting for the current thread during a mid-turn wait. |
| `to_thread_id` | string | required for `SEND_MESSAGE` | Recipient thread ID. For a spawned thread, use the `thread_id` returned by `handoff`; omit this parameter for `READ_MAIL`. |
| `to_bot_id` | string | required for `SEND_MESSAGE` | Bot that owns the recipient thread. For a spawned thread, use the `target_bot` returned by `handoff`; omit this parameter for `READ_MAIL`. |
| `body` | string | required for `SEND_MESSAGE` | Message content. Include findings and their basis so the recipient can understand it without the sender's conversation; omit this parameter for `READ_MAIL`. |
| `subject` | string or null | `null` | Optional one-line label shown above the body. |

Example:

```python theme={null}
mailbox_action(
    action="SEND_MESSAGE",
    to_thread_id="chat_parent123",
    to_bot_id="Adam",
    subject="Model review complete",
    body="I reviewed the generated model. Two risks remain: ...",
)
```

The tool returns `success`, `message_id`, and `to_thread_id`. A successful
message is queued for delivery; do not resend it just because the recipient
has not replied yet. A sender-recipient pair is limited to 12 messages in a
rolling 300-second window, and a single body is limited to 16,000 characters.

## `handoff_status`

Check progress for a previously started handoff. For non-terminal records,
Genesis recomputes live state from the child thread (active completion,
`blueprint_completed`, and last-activity recency) instead of trusting a stale
stored status. A plain delegation has no inferred completion from its message
transcript: it remains live until the child sends its result to the source
thread with `mailbox_action`. Blueprint handoffs complete when the blueprint
sets `blueprint_completed`; their reconcile path can resume after a server
restart. A stored `watch_expired` or legacy `timeout` therefore does not mean
the child failed while it is still running. If a follow-up turn arrives before
finalization, the handoff remains live until that turn is also answered.

If a child thread no longer exists, the live state is `child_missing` and the
handoff is retired with terminal status `abandoned`. A child that remains idle
without reporting is reminded after 30 minutes of quiet, at most once per hour
and three times total. A quiet handoff is abandoned after seven days when its
quiet duration can be established; active work is not retired based on the
handoff's age alone.

| Field | Description | |
| - | - | - |
| `status` | Live or terminal status. Non-terminal stored values include `started`, `running`, `first_response` (blueprint handoffs: first stable child response captured, mission still running), `watch_expired`, and legacy `timeout`. Live recomputation returns `running`, `completed`, `stalled`, or `child_missing`. Terminal values include `completed`, `error`, `cancelled`, `materialize_failed`, `expired_unnotified` (the child finished but no live parent waiter remained), `abandoned` (the child is gone or has remained quiet for seven days), and `undeliverable` (callback submission failed five times). | |
| `hint` | Present for live `running` or `stalled` — guidance on whether to wait or inspect the child thread. | |
| `result` | Populated when the handoff has completed. | |
| `elapsed_time` | Seconds since the handoff was created. | |
| `last_tool_call` | object or null | Last child tool call on a non-terminal record, with its name and timestamp. |
| `tool_call_count` | integer | Number of child tool calls on a non-terminal record. |
| `last_activity_at` | string or null | Last activity timestamp read from the child thread on a non-terminal record. |
| `idle_seconds` | number or null | Seconds since the child's last activity on a non-terminal record. |
| `not_notified_reason` | string or null | Present when a completed child was not delivered to its parent: `finished_<seconds>_ago`, `parent_idle_<seconds>s`, or `submit_failed`. |

For `status="stalled"`, inspect `last_tool_call` and `tool_call_count` before
starting the work again. A stalled child may have completed useful work before
it became idle; retrieve it with `handoff_results(...)` rather than assuming it
failed.

## `handoff_list`

List open delegations, oldest first. Use this to see what work is still
outstanding, identify a stalled or missing child, or check whether a job is
already in flight before dispatching more work. An empty list means no
non-terminal handoffs remain.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `limit` | integer | `50` | Maximum number of records to return. Records are ordered oldest first. Values of `0` or less return an empty list. |

Each returned record includes `handoff_id`, stored `status`, recomputed
`live_state`, `age_days`, `child_thread_id`, `child_bot_id`,
`parent_thread_id`, `blueprint_name`, and `nudges_sent`. For one known handoff,
use `handoff_status(...)`; use `handoff_results(...)` to inspect its output and
`handoff_cancel(...)` to stop tracking it.

The call reads all retained handoff records, including closed records, before
selecting the oldest open records; it then performs live-state checks only for
the records returned. Ask once rather than polling it.

## `handoff_results`

Retrieve whatever a handoff has produced, whether or not it is complete. A
terminal handoff returns its stored result. Any other status returns
`partial=true` plus the child's latest response, stored blueprint outputs,
cancellation or error details, and progress fields when available. This makes
work recoverable after cancellation, a stalled child, or an expired watch
window. Use `handoff_status(...)` for authoritative live state; do not
re-dispatch based on status alone.

The child's latest response contains its answer text, not the runtime's display
announcements such as `🧰 Using tool: ...`. If the child produced only those
announcements, the latest response is `null` rather than a successful-looking
answer.

## `handoff_send`

Queue follow-up guidance in an existing handoff thread. Queueing does not wait
for or acknowledge child consumption. A successful response includes
`status="queued"` and `queued_to_live_child`: `true` means the child was
observed processing at submission time, while `false` means the message was
queued to an idle child and may not be read. The response also includes
`child_state` and, for an idle child, the progress fields from
`handoff_status`.

If the handoff is `cancelled`, `error`, or `materialize_failed`, the message is
not submitted and the tool returns `success=false`, `status="refused"`, and
`queued_to_live_child=false`. Check `handoff_status(...)` and
`handoff_results(...)` before re-dispatching because cancellation does not
signal a child that was already running.

## `handoff_cancel`

Stop tracking an in-progress handoff. This records the handoff as `cancelled`
so it is no longer watched, reported, or reconciled; it does not send a
cancellation signal to the child. A child already mid-task can continue and
its side effects can still land. `handoff_results(...)` remains available for
partial output, so inspect it before repeating the work.

## `get_handoff_inputs`

Call from a **child** thread that was spawned by a blueprint handoff. Retrieves
structured inputs the parent thread stored (for example `migration_repo_id`,
`source_connections`, `target_connection`) so the child blueprint can start
with the correct values.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `blueprint_name` | string or null | `null` | Target blueprint name. When set, Genesis requests inputs declared in that blueprint's manifest. |
| `specific_inputs` | string\[] or null | `null` | Optional subset of input names to retrieve. When omitted, Genesis requests all declared required and optional manifest inputs. |

Returns `inputs` (keyed values), `from_parent_thread`, `missing_inputs`, and a
`hint` for next steps. When the call runs with agent context (`bot_id` present),
Genesis also persists retrieved values on the child thread as durable
`blueprint_inputs`. When there is no agent context, inputs are still returned and
held in the thread outputs cache for the current call, but the durable
`blueprint_inputs` write is skipped.

## `store_blueprint_outputs`

Call when **completing** a blueprint (typically before the final phase exit
through `@END`) to store named output values (for example `migration_repo_id`)
so `get_handoff_inputs` or `BLUEPRINT_HANDOFF` auto-extraction can supply them
to a downstream blueprint.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `outputs` | object | required | Key-value map of blueprint output names to values. |
| `blueprint_name` | string or null | `null` | Optional source blueprint name for provenance. |

Returns `success`, `stored_outputs`, `blueprint_name`, `message`, and a
contextual `hint`. The `hint` depends on how this thread was spawned:

* When `handoff_completion_mode` is `notify` (the parent used
  `on_completion="notify"`) or `handoff_is_remediation` is true (handoff
  context included `remediation_repo_id`), Genesis instructs the agent **not**
  to chain another blueprint from this thread. Stored outputs are delivered to
  the waiting parent automatically when this blueprint exits through `@END`.
* Otherwise, the hint suggests calling `handoff()` to chain to the next
  blueprint with auto-extracted inputs.

## Blueprint chain handoffs

When `handoff(...)` or `BLUEPRINT_HANDOFF` launches another blueprint, Genesis
sets `handoff_reason` to `blueprint_chain` on the child thread, inherits
`blueprint_journey_context` from the parent when present, and can create a
dedicated child Mission project for the handoff thread. Mission Center uses this
metadata to render the [blueprint chain strip](/docs/Blueprint/Blueprint-Library-And-Missions#mission-center-blueprint-chain)
and to mark journey stages as **spawned**, **expected**, or **skipped**. When
the parent or child thread stores a presenter-safe `coding_agent` blueprint
input (`ginie`, `cocoa`, or `claude_code`), the chain API and Mission Center
strip expose it as a compact coding-agent badge.

When `handoff(...)` sets `blueprint_name`, Genesis seeds blueprint kickoff
context on the spawned thread after materialization. Genesis activates
`project_manager_tools` on that thread so the delegated agent can call
`_blueprint_tool` during the blueprint. When the target agent uses `allowlist`
tool policy and its `tool_access_list` omits `project_manager_tools`, Genesis
elevates the agent's durable `tool_access_list` to include that group so the
kickoff tools survive the effective-state filter.

When a blueprint-chain child produces its first stable response during a
synchronous watch (`async_mode=false` or a bounded `timeout_seconds`), Genesis
stamps the handoff record `first_response` — not `completed` — so
`handoff_status` can keep live-recomputing while the mission runs. Parent
`on_completion="notify"` and the `[HANDOFF COMPLETE]` message fire when the
child blueprint reaches `@END`, not at first response.

## Notes

* Warnings for undeliverable handoff notifications repeat at most once per hour for the same reason, bot, and thread. A different failure condition is logged immediately; the mailbox sweep continues to log each failed delivery pass at `INFO`.
* Use `show_in_thread_list=false` for internal sub-threads and background work that should stay out of the default sidebar list. When omitted, Genesis defaults it to `true` for `visibility="visible"` and `false` for `visibility="hidden"`.
* Use `visibility="hidden"` when the spawned thread should be hidden from normal UI surfaces, not only omitted from the default sidebar list.
* For blueprint-backed spawned threads, `continuous` mode can be paused without losing the current phase. If an operator cancels continuous execution, or Genesis pauses the thread after detecting suspected replay growth, Genesis keeps the active phase on the child thread and switches it back to `manual` mode for human review.
* `handoff(...)` refuses deactivated target agents (resolved by `bot_id` or display name). It returns `success=false` and an `error` such as `Agent 'Adam' is deactivated and cannot receive handoffs. Reactivate it or choose an active agent.` When materialization is blocked by lifecycle, `status` is `materialize_failed`.
* If Genesis cannot create the child thread during the initial handoff, `handoff(...)` returns `success=false`, `status="materialize_failed"`, and an `error` instead of a `thread_link`.
* Use constrained `allowed_tools` for risky operations. The server refuses out-of-list calls, but the scope cannot grant tools the target does not already have and falls back to the target's own tool set if the child's thread state is unreadable.
* Keep `timeout_seconds` explicit for synchronous waits; long blueprints often exceed the default 300 s watch window — that stamps `watch_expired`, not failure. Poll `handoff_status` (or rely on `on_completion="notify"`) for the real outcome.
* Blueprint-chain parents that delegate with `on_completion="notify"` resume automatically when the child mission completes — no manual poll required unless you need the stored `result` payload.
