Skip to content

Session Orchestration

Wait for session state and coordinate governed child sessions through CLI, HTTP, UDS, and native tools.

For people running agent work11 pages in this section

CompozyOS exposes session orchestration through the CLI, matching HTTP/UDS routes, and scoped native tools. Use these surfaces to wait on state, spawn bounded children, resolve their interactions, cancel one prompt, or stop a session without polling the catalog.

Wait for state

compozy session wait returns when a session reaches any requested state:

compozy session wait sess_1234 \
  --until waiting-for-input,waiting-for-auth,stopped,failed \
  --timeout 2m \
  -o json

When --until is omitted, the target set is waiting-for-input, waiting-for-auth, idle, stopped, and failed. done satisfies idle. Explicit targets may also include done, running, hung, unhealthy, and needs-attention. Include needs-attention when an unverified stop should wake the caller for a retry.

The default timeout is 5 minutes. --unbounded keeps the CLI waiting through gapless, bounded server requests; the daemon never holds an unbounded HTTP/UDS request. Structured outcomes are state-reached, timeout, session-gone, canceled, and overflow.

Outcome or errorCLI exit
State reached0
Invalid target65
Session unavailable69
Timeout75

HTTP and UDS use POST /api/workspaces/{workspace_id}/sessions/{session_id}/wait with required timeout_ms from 1 through 1,800,000. A timeout is a normal result; a deleted or replaced session returns 410.

Cancel an active prompt

Cancel the prompt without stopping the session:

compozy session prompt-cancel sess_1234 -o json

The result is canceled with its turn_id, or nothing-in-flight. Repeating the command is safe and uses the same cancellation path as POST /api/workspaces/{workspace_id}/sessions/{session_id}/prompt/cancel and the native tool. The CLI exits 0 after a cancel and 66 when there was nothing to cancel.

Messages between sessions

Agents use compozy__session_prompt to address another session. Supply session_id, message_id, idempotency_key, and the message or attachments. Choose mode: "queue", "steer", or "interrupt" when the target is busy. Retry with the same message and idempotency IDs.

CompozyOS stamps an immutable origin from the calling agent session. Queue and event responses include kind: "session", session_id, workspace_id, hop, and optional agent_name, title_at_send, notify_on_complete, and reply_watch_id. The origin survives all delivery modes and daemon restarts. It cannot be supplied through a request body. CLI, HTTP and operator prompts remain unattributed operator input.

The receiving provider sees a one-line sender header followed by the message. The header does not become stored message text. Without a reply watch, it tells the recipient to answer by calling compozy__session_prompt with the sender's session ID. Set notify_on_complete: true to request the reply-watch flow from an agent session. Changing that flag on a retry conflicts, as does retrying another sender's message identity. A sender rename preserves the original admission.

An operator can cancel an agent-authored queued message, but cannot replace or promote its text. Those mutations return HTTP 409 input_agent_authored. Each message increases the active turn's highest accepted hop; steer also raises that value before provider delivery. A ninth hop returns message_hop_limit: ask the operator to continue in a fresh turn.

Native self-targeting returns invalid_request. To continue work in the same session, end the turn; to schedule work, use a subagent or compozy session prompt from the operator. This approved compatibility exception applies immediately. Existing v4 admission receipts still replay without origin or a new reply watch; their boundary compatibility shim is scheduled for removal in v0.5.0.

The message tool's existing cross-workspace reach is unchanged. Origin includes the sender's workspace so readers can resolve that session correctly.

Governed child feedback

compozy spawn creates a child with a required TTL, lineage, capacity limits, and permissions that cannot exceed its parent. By default, CompozyOS queues a sanitized synthetic turn on the parent when the child completes a turn, stops, fails, or enters a needs-you state. A canceled child turn sends no completed wake. The wake never interrupts an active parent prompt.

To hand one task to another agent, provider, or model from inside a turn and get the answer back without managing a child yourself, use subagents instead.

compozy spawn --agent researcher --ttl-seconds 3600
compozy spawn --agent researcher --ttl-seconds 3600 --no-notify-creator
compozy spawn --agent researcher --ttl-seconds 3600 \
  --provider codex --model gpt-5.6-sol --reasoning-effort high --speed fast

notify_creator defaults to true on HTTP, UDS, and compozy__session_spawn. Set it explicitly to false to opt out for one child. This default has no config.toml key.

Provider, model, reasoning effort, and speed are optional child-runtime overrides on the CLI, HTTP/UDS request, and native tool. Omit them to use the named agent and workspace defaults.

Native orchestration tools

Resolve each live descriptor with compozy__tool_info before calling it. All targets are restricted to the caller's workspace, and a session cannot target itself.

ToolPurpose
compozy__session_waitWait up to 30 minutes for a badge or lifecycle state.
compozy__session_spawnCreate a governed child with a required TTL and narrowed permissions.
compozy__session_stopStop another session; destructive approval policy applies.
compozy__session_approveResolve another session's pending permission request.
compozy__session_clarify_answerAnswer another session's pending clarification by choice or text.
compozy__session_prompt_cancelCancel another session's active prompt without stopping the session.

Approval and clarification resolution survive daemon restart. A successful orphaned resolution returns resolved-after-restart; a race may return already-resolved, and a full durable input queue returns queue-full without consuming the pending interaction.

Ask another session for a reply

An agent can call compozy__session_prompt with notify_on_complete: true to receive a reply from an existing session. The tool returns reply_watch: { id, state }, using its current persisted state (armed, fired, delivered, or abandoned). Retrying the same message and idempotency key after a pre-dispatch failure re-arms the same watch. The sender can then finish its turn; CompozyOS delivers one synthetic reply wake after the turn that consumed the message settles. Queued messages retain their watches across a target stop. A busy sender receives the wake after its current turn.

Waiting is long-running work, not silence. While the asked session is live, the sender's open watch counts as an awaiting_reply work signal, so inactivity supervision does not stop an orchestrator that is waiting for an answer, however long the target works. If the sender was stopped anyway (the target stopped with the message queued and the sender went quiet, a daemon restart, or an agent crash), the reply resumes the sender and delivers the wake once. A sender you stopped yourself stays stopped and receives the wake when you resume it.

compozy__session_status, the session status HTTP response, and compozy session status <id> -o json include reply_watches while they are armed or fired. Each item identifies the watch, target session, message, state, and creation time. The human CLI shows a Waiting for replies section. Delivered and abandoned watches disappear from this list.

Replies contain the last non-empty assistant message of the consuming turn, bounded to 12000 Unicode characters. Truncated replies include a pointer to compozy__session_history; empty replies use (no reply text). Outcomes are completed, failed (with an error summary), canceled, dropped (removed before execution), or unknown (delivery was uncertain; inspect the target session).

Archiving or deleting the sender abandons its outstanding watches. Canceling or clearing a reply wake from the sender's queue does not send it again. notify_on_complete belongs to the agent-facing native tool; HTTP operator prompts have no equivalent option. Operator-scoped native calls with this option return invalid_request: notify_on_complete requires an agent session. Archiving or deleting an unconsumed target settles its outstanding watches as unknown without waiting for a restart.

On this page