Agent Prompt Submission

On this page
  1. Agent prompt submission and final responses
    1. Authoritative admission for orchestrators
    2. Results and subscriptions
    3. Correlation safety

Agent prompt submission and final responses#

wakterm agent send TARGET MESSAGE keeps its existing behavior. It writes the prompt to the native harness pane, submits it, waits briefly for observer acknowledgement, and prints structured JSON.

For an idle Codex agent with an exact observer-backed PTY session or managed app-server session, --return-final creates a durable asynchronous return request:

wakterm agent send zola --return-final "Complete phases 2 and 3"

The command registers the exact correlation boundary, submits the prompt, and exits. Its JSON receipt contains reply_pending: true, the request ID, target incarnation, correlation source, baseline provider turn when available, and armed cursor. Observer-backed PTYs use the provider-file cursor. Managed app-server sessions use the durable Agent API event sequence. The command does not keep a CLI process or RPC socket open for the delegated turn.

Use a caller-generated UUID when another durable system owns the request:

wakterm agent send zola \
  --return-final \
  --request-id fe57dc90-994e-4e73-b09c-fac483d9f05b \
  --final-timeout-ms 3600000 \
  "Complete phases 2 and 3"

Repeating the same request ID and input returns its existing receipt without submitting the prompt again. Reusing the ID with different input is rejected. The timeout is an asynchronous request deadline. Zero, the default, disables the deadline.

Authoritative admission for orchestrators#

agent send remains the convenient interactive command. An orchestrator that must not steer an active turn uses the versioned admission API instead:

wakterm agent capabilities
wakterm agent catalog
wakterm agent admit zola \
  --incarnation PROCESS_INCARNATION \
  --request-id REQUEST_ID \
  --return-final \
  --final-timeout-ms 3600000 \
  "Complete phases 2 and 3"

An orchestrator retrying a persisted identity that may no longer appear in the current catalog uses --exact-agent-id. This bypasses display-name and catalog resolution so the server can return a structured unavailable or stale_incarnation receipt:

wakterm agent admit PERSISTED_AGENT_ID \
  --exact-agent-id \
  --incarnation PERSISTED_INCARNATION \
  --request-id REQUEST_ID \
  "Complete phases 2 and 3"

The catalog supplies the stable agent ID and opaque process incarnation. The admission call requires both, refreshes the provider observer away from the mux reactor, and rechecks the same incarnation and authoritative idle state immediately before input. Prompt text and Enter are serialized as one pane write. Observer scanning, SQLite work, and the removed 200 ms submission delay do not block the mux reactor.

The structured receipt classifies accepted, busy, unsupported, unavailable, stale_incarnation, invalid, observer_failure, internal_failure, and indeterminate. A definitive rejection always has prompt_written: false. Any write error is indeterminate because a PTY write may have been partial. Callers must not retry an indeterminate request under a new ID.

An idle observer-backed target whose observer has not produced a cursor for its completed baseline turn is a definitive observer_failure with prompt_written: false. A managed target receives the same classification when the durable Agent API event stream is unavailable. It is not busy, because no active target turn was observed, and it is not a delivery failure, because Wakterm did not attempt the pane write. A caller may choose an explicit one-way admission while return-final correlation is unavailable.

The caller owns the request ID. Repeating the same ID, process incarnation, prompt bytes, paste mode, return mode, and timeout cannot write the prompt a second time. Reusing an ID with different input is rejected. One-way admissions and return-final admissions both persist their idempotency state. Return-final admissions continue to complete on the existing durable terminal request stream described below.

Results and subscriptions#

Inspect or cancel one request:

wakterm agent request get REQUEST_ID
wakterm agent request cancel REQUEST_ID

Terminal results are appended to a durable ordered event stream. A consumer keeps the last processed terminal_event_sequence and resumes after it:

wakterm agent request watch --after 42

The command emits one JSON object per terminal request and remains attached as a single subscription. --once drains currently available events and exits. Terminal states are completed, aborted, timed_out, cancelled, delivery_failed, and indeterminate. Only completed contains final_message.

The request database lives in Wakterm's data directory, uses SQLite WAL with full synchronous commits, and survives mux and consumer restarts. Terminal event sequence numbers are stable, so consumers can make their own delivery idempotent without reading provider session files.

Correlation safety#

Every return request requires the same exact target incarnation, authoritative idle state immediately before the atomic prompt write, and one stable provider turn through completion.

Observer-backed Codex PTYs additionally require:

  • the same adopted process ID and process start time remain attached
  • the same exact observer session remains attached
  • the target was idle at submission with a completed baseline turn
  • the provider starts a new turn after the armed observer cursor
  • the first user message hash matches the submitted prompt
  • the bound provider turn ID remains stable through completion

Managed Codex app-server sessions instead require:

  • the same exact app-server thread ID and session ID remain attached
  • the durable Agent API event stream is live at admission
  • the first new provider turn starts after the armed durable event sequence
  • the same provider turn ID supplies the durable final

A mismatch becomes indeterminate. Wakterm never substitutes a later final message. During live admission, a request remains registered until prompt submission is durably confirmed; terminal watchers leave that registration unchanged. At authoritative mux startup, registrations left unfinished by the previous runtime become indeterminate, preventing a post-restart prompt from satisfying them accidentally.

Steering messages within the same bound provider turn preserve correlation. They do not replace the matched initial prompt or authorize a final from a different provider turn.

Codex session discovery first checks rollout files actually held open by the adopted process tree and verifies the adopted process start time and declared working directory. A reused pane can no longer remain attached to an older rollout merely because that file was the previous preferred observer session.

The current return mode is Codex-only because Codex rollout records and app-server notifications expose stable provider turn IDs with exact cursor boundaries. Other harnesses need equivalent evidence before they can safely support this primitive.

One PTY limitation remains: byte delivery and the durable submitted marker cannot be a single transaction. Wakterm resolves a crash in that narrow window as indeterminate instead of risking duplicate or unrelated completion. The actual pane write still runs through the existing mux input path, but it is one bounded write rather than observer work, database work, or a timed wait.

Edit this page