Agent Harness Lifecycle
On this page
Agent Harness Lifecycle and Supervised Backend Direction#
Status#
Wakterm supports agent harnesses as terminal processes running in PTY panes. It detects supported harnesses (Agy, Claude, Codex, Gemini, OpenCode, ZCode), observes provider session state, and automatically adopts confirmed sessions into its persistent agent registry.
Restorable Claude and Codex sessions are restored automatically across multiplexer restart and system reboot in their declared working directory, resuming the exact confirmed provider session. On Linux, confirmed Agy conversations have the same restoration guarantee. Agy and Claude resume through their native TUIs. Codex first resumes through the current shared app-server and uses an exact native fallback if that fails. If a restart interrupts an active turn, Wakterm restores the session but does not guarantee that the in-flight turn continues.
Agent API v1 provides versioned capability negotiation, catalog queries, authoritative prompt admission, durable event streams, and return request tracking. Structured supervisor backends that preserve the provider native TUI remain the long-term direction. Wakterm-rendered agent presentation is not the normal product direction. This document defines the lifecycle boundaries and guarantees.
Lifecycle states#
The lifecycle uses distinct states because each one has stronger evidence and stronger guarantees than the previous one.
| State | Meaning | Durable |
|---|---|---|
| Detected | Runtime evidence suggests that a supported harness is running in a pane | No |
| Confirmed | The process is matched to a concrete provider session reference | No |
| Adopted | Wakterm persistently associates an agent identity with the pane and confirmed harness | Yes |
| Restorable | Wakterm has a verified recipe for starting the harness and resuming that exact provider session | Yes |
| App-server TUI | The mux owns a structured provider connection while the pane renders the provider's native TUI | Yes |
| Wakterm-rendered | Wakterm owns a headless backend connection and renders its own agent presentation | Yes, but not a normal launch target |
These states are not aliases:
- Detection does not authorize persistence.
- Adoption does not prove that a session can be resumed.
- Restoration of a native TUI does not make the session structurally supervised.
- An app-server TUI is supervised without making Wakterm responsible for the provider's presentation or approval UI.
- A Wakterm-rendered backend is not a substitute for a provider's native TUI.
The public origin reports detected for unregistered discovery, adopted for
a registered PTY owned by its native process, and managed when the mux owns
the structured transport. Restorable remains a lifecycle capability rather
than an origin. App-server TUI is represented by the CodexAppServerTui
transport and therefore reports the managed origin.
Codex app-server TUI transport#
wakterm agent launch codex starts or resumes an exact Codex thread through one
mux-owned app-server on a private Unix socket. The mux keeps one initialized
protocol connection, routes lifecycle events by exact thread ID, and persists
the distinct Codex thread ID and session ID. Each pane runs codex resume
against that socket, so input, rendering, approvals, and native interaction
remain Codex TUI responsibilities.
When a managed TUI uses /resume, /fork, or another provider operation that replaces its active thread, Wakterm follows the successful transition from that exact TUI connection and rebinds the same pane and stable agent ID to the returned thread and session. Passive assistant output therefore continues under the pane's current effective-title route. The provider thread and derived incarnation remain exact provenance and change at the transition, so admission and return-final callers must use a fresh catalog incarnation.
Ephemeral provider threads used for hidden work such as title generation do not replace the pane's active thread, restoration identity, lifecycle state, or passive output source.
Turn-scoped notifications update live state only for the current running provider turn. Late items, including subagent completion attributed to a finished parent turn, remain eligible for durable event recording without reopening that turn or changing a newer turn's state. A turn/started notification for a different provider turn starts live work normally.
The native TUI receives the pane's declared working directory explicitly. Its session picker therefore starts with the same working-directory filter as a normal Codex TUI, even though multiple panes share one app-server.
When invoked inside a Wakterm pane, the command runs the native TUI in that
current pane and returns to its shell when Codex exits. --new-tab explicitly
creates a separate tab instead. Invocations outside Wakterm must use
--new-tab, because there is no current Wakterm PTY to own the TUI.
This transport intentionally keeps the native provider UI. A Codex TUI already connected to the mux-owned app-server can be promoted explicitly with wakterm agent promote-codex. Promotion requires an adopted pane and an exact thread UUID, verifies that the live process uses that thread and the current mux-owned socket, attaches the mux protocol client to the same thread, then verifies that the process did not change before persisting managed metadata. Other manually launched Codex processes remain on the observed-PTY path while they are live. A manually launched remote TUI is observed through the rollout of the thread named by its resume argument, because its app-server, not the TUI process, holds that rollout open. The shared process has one executable, version, CODEX_HOME, authentication identity, environment policy, feature set, and remote Code Mode host. Launches that need a different process-wide configuration must use a different mux or the observed-PTY path.
Wakterm binds managed metadata to the native remote TUI frontend after it starts. Suspending that process with Ctrl-Z preserves the binding and fg resumes the same frontend. Disconnecting or exiting the frontend and returning to the shell removes the managed binding. If a normal Codex TUI is then launched in the same pane, Wakterm detects and adopts its provider session through the observed-PTY path. Renaming the tab does not affect this lifecycle.
Automatic restoration is a new-process boundary. Wakterm optimistically resumes every restorable Codex thread through the current shared app-server, even when the previous process was adopted from an observed PTY or used an older Codex version. The returned thread identity must exactly match the saved thread. Saved approval and sandbox arguments are applied when the app-server first starts or resumes the thread, before the native TUI attaches. If managed resume fails, Wakterm uses the exact native resume recipe; neither path may create a replacement session.
Managed Codex restoration also recovers the newest completed-turn timestamp in the resume exchange, so LAST TURN END remains available after restart. A thread with no completed turn reports -.
Detection and confirmed adoption#
Detection may use process trees, foreground process information, terminal titles, and provider-specific observer data. Process names and terminal titles are useful discovery evidence but are too weak to persist by themselves.
Confirmed adoption requires a provider session reference discovered by the observer. Depending on the provider, that reference may currently be a session file, a database plus session ID, or another provider-owned record.
On Linux, direct Codex confirmation accepts a user-visible rollout held open by the exact foreground process incarnation or one of its descendants after verifying that the rollout declares the pane working directory. This process-owned path works across nonstandard CODEX_HOME locations without scanning those locations. Directory scanning remains a fallback within the configured Codex sessions root when exact process evidence is unavailable.
On Linux, Agy confirmation matches the exact process incarnation to its open per-conversation presence lock, then observes that conversation's persistent transcript. Wakterm does not select an Agy conversation by modification time or working directory alone.
A restorable Agy pane persists the conversation UUID confirmed by that lock.
Restoration invokes the current Agy launcher with --conversation <uuid> and
rebinds the Wakterm agent identity only after the new process incarnation owns
the presence lock for the same UUID.
Process IDs are incarnation identifiers only. When a PID is recorded, its start time must also match so PID reuse cannot attach stale metadata to an unrelated process. Neither value is a durable session identity.
A managed Codex app-server pane derives its incarnation from the stable Wakterm agent ID and exact app-server thread and session IDs. This identity is available while a restored native TUI is starting and does not depend on a temporary process ID.
Automatic adoption may promote a detected pane only after a confirmed session match. If the harness exits back to a shell, stale automatically adopted state must be cleared instead of making the shell look like a live agent.
An agent launched in an existing pane binds its process identity after the harness starts. Suspending that process preserves the registration. Exiting the harness clears its metadata and icon even when the launcher shell remains alive.
On Linux, an interactive harness may run behind a foreground supervisor. Discovery selects one outermost harness descendant in the same process group and controlling terminal; ambiguous candidates and other jobs cannot be adopted. The registration follows the harness PID and start time. Prompt admission rechecks that exact foreground target immediately before writing input. A supervisor remaining alive cannot retain a departed or replaced harness's registration.
Supervised Claude observation requires its process-owned session record and transcript to be readable by the host mux. Wakterm matches the record's PID in Claude's namespace, process start time, machine and PID namespace identity, working directory, interactive mode, and session UUID. A missing or mismatched record leaves observation pending. The existing Agent API, native TUI input, and durable output stream use the confirmed child session. Observing a sandboxed process does not grant that process host mux control authority or require access to host runtime sockets.
Claude can move a conversation to a background job run by its daemon, and a pane may then show that job: either the window that sent it there or claude attach <job>. Wakterm observes such a pane through the job's live worker and its session, and the pane keeps its agent identity. While the job runs, the pane's runtime reports background_job with a hint for moving the conversation back into the pane, because the worker runs outside the pane and a mux restart stops it. When the worker is gone, observation reports an error naming the job's saved session and the command that resumes it in the pane, rather than choosing a session from transcript timestamps.
ZCode stores sessions in OpenCode's database schema in its own database. A ZCode pane started with --resume sess_..., as every restoration is, is observed as exactly that session. Otherwise, as for OpenCode, the observer selects the most recently updated session in the pane's working directory, so two ZCode sessions in one directory can be confused until one is resumed explicitly.
Wakterm records the presence of a launch supervisor separately from the inner harness command. Automatic restoration currently retains that session intent and displays a diagnostic pane requesting an explicit supervised resume recipe. It does not execute the inner command without its supervisor. Run the offline native-TUI regression with WAKTERM_TEST_CLAUDE=/path/to/claude cargo test --locked -p mux real_sandboxed_claude_process_and_session_are_observed --lib -- --ignored --nocapture. It requires Python 3 and bubblewrap, uses private provider storage, resumes a local fixture without a model request, and checks mount, PID, IPC and UTS isolation plus absence of host control sockets.
Provider artifact observation continues after adoption. Filesystem changes are hints to refresh the exact pane and confirmed provider session through the observer worker. This keeps durable agent events current even when no client is listing agents or submitting prompts. Event reads remain side-effect free.
Unnamed tabs whose active pane contains an adopted or app-server agent use that agent's leaf folder name as an automatic display title. The title follows the active pane because one tab may contain multiple agent panes with different working directories. An explicit user title always wins and is the only title persisted as layout identity. Terminal and folder-derived titles remain automatic. The rename-tab prompt preloads only an explicit title, so an empty prompt also indicates that the visible title is automatic. Submitting an empty title clears the explicit name and returns the tab to automatic naming.
Restoration contract#
Automatic restoration must resume the intended provider session or report a visible failure. It must never silently replace an expected harness with a fresh shell or silently start a new provider session.
An exited restorable pane remains in the recoverable layout until the pane or tab is explicitly closed. Process exit updates live agent status but does not discard its restore intent.
Durable restore intent#
A restorable agent needs enough persisted intent to reconstruct an exact resume operation:
- stable Wakterm agent ID
- harness or provider kind
- stable provider session ID or an equally authoritative provider reference
- declared working directory
- launch executable and arguments
- provider-specific resume recipe version
- required workspace roots or checkout information
- safe configuration needed to recreate the session
Do not persist process IDs as recovery handles. Do not persist access tokens, temporary authentication material, or inherited environment secrets in layout or session files.
Shell aliases are not durable restore recipes. Wakterm does not invoke an interactive shell or evaluate startup files to expand them. For a supported observed harness, it derives the native restore recipe from the concrete live process argv, removes any existing provider-owned session selector, and inserts the confirmed session ID during restoration. Confirmed runtime and provider identity determine restore eligibility; the spelling of the original launch command does not.
Native restoration has one shared provider boundary: identify a restorable harness, extract its stable session ID, normalize its concrete process argv, construct its exact resume invocation, and confirm the session after launch. Agy, Claude, Codex, and ZCode implement that boundary. Provider-specific managed transports remain optional preparation paths layered on the same persisted restore intent.
The provider session identity is authoritative for recovery. File names, timestamps, titles, and command lines are supporting evidence unless a provider explicitly defines one of them as its stable identity.
Restore sequence#
For each expected harness pane, restoration should:
- Load and validate the persisted restore intent.
- Verify that the provider executable and referenced session are available.
- Construct the provider's exact resume invocation.
- Spawn the TUI in the restored pane and declared working directory.
- Observe the new process incarnation.
- Confirm that it opened the expected provider session.
- Bind the existing Wakterm agent ID to the new pane only after confirmation.
On Unix, the restored TUI runs as a foreground job of the user's interactive login shell. The harness remains the foreground process while it runs, and exiting it returns the pane to that login shell instead of closing it.
When SHELL names the native Wsh system-package path /usr/bin/wsh or /bin/wsh, restored harnesses use wsh --run --login -- PROGRAM ARG..., Wsh's exact-argument foreground interface. Wsh owns suspension and resumption and returns to the same interactive shell after the harness exits. Per-user Wsh launcher paths keep the generic shell restore path. The two system paths are reserved for the native Wsh package; manually copied legacy launchers must be migrated before using them there.
Run the real-parser and PTY regression with WAKTERM_TEST_WSH=/path/to/native/wsh cargo test -p mux restored_harness_real_wsh_preserves_argv_and_job_control --lib -- --ignored --nocapture. It uses the production restore arguments and substitutes only the executable location, checking argument bytes, Ctrl-C, Ctrl-Z, fg, foreground ownership, application exit status, and return to the shell prompt. The test needs Python 3 and an available native Wsh build.
If any step fails, keep the layout recoverable, surface the failure, and retain enough intent for an explicit retry. A failure pane or equivalent diagnostic surface is preferable to a convincing but incorrect fresh shell.
Restoration must be idempotent. Repeated reconciliation must not launch a second harness after the first one has started but before observation has finished. Persisted intent, launch attempts, and confirmed runtime bindings must remain distinguishable.
Mid-turn recovery is provider-dependent and is not guaranteed by restoring a session. The first target is confident idle-session resume after a mux-server restart.
Native TUI product boundary#
Wakterm must preserve the provider's native TUI for interactive agent panes. The provider TUI owns input, rendering, questions, approvals, and other native interaction. Wakterm may add lifecycle supervision only when a structured connection can attach to the same exact provider session without taking over those responsibilities.
The supported paths are:
existing shell or TUI
-> detect
-> confirm
-> optionally adopt
-> restore as a native TUI
Wakterm supervised start
-> mux owns a structured supervisor when the provider supports one
-> pane runs the provider's native TUI against the same exact session
-> provider TUI remains the interactive authority
An ACP agent normally expects the ACP client to render the conversation and approval UI. That topology does not qualify merely because its lifecycle events are structured. A provider protocol qualifies for a normal Wakterm launch only when the native TUI and mux supervisor can attach concurrently to the same session. Otherwise retain the observed and restorable PTY path and be honest about its weaker lifecycle evidence.
Do not automatically promote a live detected or adopted PTY into a supervised transport. Automatic restoration may select a supervised transport because it starts a new process, but it must resume the verified session and declare success only after the structured connection and native TUI confirm the same provider identity. Any future attachment to a live process must remain explicit.
Supervised backend protocol policy#
Wakterm should expose one internal supervision interface and normalized lifecycle model only when at least one additional provider passes the required same-session native-TUI tests. Protocol implementations sit behind that boundary.
The selection policy is native-TUI-first:
- Preserve the provider's native TUI as the interactive surface.
- Prefer a structured provider protocol only when it can supervise the exact session used by that TUI.
- Reject adapters that require Wakterm to render the agent interaction.
- Keep provider-specific information available behind typed extensions rather than forcing every feature into a lowest-common-denominator model.
ACP provides protocol-version negotiation, advertised optional capabilities, one reusable client implementation, and one reusable fake-agent test surface. Those properties reduce code and compatibility logic owned by Wakterm.
ACP does not guarantee whole-system robustness. An adapter adds another process, version relationship, translation state machine, and logging layer. It may also omit or approximate provider-native concepts. Wakterm must record the backend and protocol versions it actually loaded, negotiate capabilities, and fail explicitly when a required capability is absent. Provider-specific ACP metadata must not become a silent protocol contract without versioned tests.
The provider stance is:
| Provider | Starting preference | Reason |
|---|---|---|
| Agy | Native observed and restorable PTY; investigate structured supervision | The interactive TUI exposes exact conversation presence and a persistent transcript; stream JSON and state callbacks apply to managed launches rather than attachment to an existing TUI |
| Gemini | Native TUI; investigate same-session supervision | Direct ACP makes the client the UI unless Gemini supports concurrent native-TUI attachment |
| OpenCode | Native TUI; investigate same-session supervision | Direct ACP is not sufficient if it replaces the provider TUI |
| ZCode | Native observed and restorable PTY; investigate its app-server | Sessions use OpenCode's database schema, and --resume reopens an exact session; ZCode also ships a stdio app server whose attachment to the native TUI is untested |
| Claude | Native observed and restorable PTY | Remote Control preserves the TUI but exposes no supported local observer; reverse-engineered --sdk-url, SDK, and ACP paths are headless, cloud-constrained, or infer state from a PTY |
| Codex | Native app-server TUI | The mux and native TUI attach to the same exact app-server thread |
This table is a starting policy, not evidence that every provider already supports structured supervision. Attribute each lifecycle fact to the protocol, adapter, provider, or Wakterm layer before changing a transport.
Useful upstream references:
- Agy title generation
- Agy hooks
- Agy headless and stream JSON mode
- Agy exact conversation resume
- Agent Client Protocol
- Claude ACP adapter Rust evaluation
- Gemini CLI ACP mode
- OpenCode CLI ACP mode
- Claude Agent ACP adapter
- Codex ACP adapter
- Codex app-server
Supervised runtime authority#
A provider protocol is a transport, not Wakterm's persistence authority. A supervised pane needs a durable Wakterm record containing at least:
- stable Wakterm agent ID
- provider and backend kind
- provider session ID
- working directory and workspace roots
- backend executable and validated version
- negotiated capabilities
- current provider turn or request identity when available
- outstanding approval identities
- last authoritative persisted checkpoint
- recovery result after the latest backend restart
Transient notifications update this state, but the last notification alone must not define recovery behavior. Preview or delta events are display aids; provider-confirmed terminal events and persisted session state are the authoritative checkpoints.
Validation gates#
PTY adoption and restoration#
Before claiming reliable automatic restoration, cover:
- false-positive process and title detection
- PID reuse and stale process metadata
- provider session matching with multiple candidate sessions
- harness exit back to a shell
- mux restart followed by exact session resume
- missing, corrupt, and incompatible session references
- partial restore of a multi-pane layout
- repeated reconciliation without duplicate launches
- a failure that proves no fresh shell or fresh agent session was substituted
Provider-specific resume behavior needs real harness smoke tests where a small fixture cannot establish correctness. Deterministic discovery, persistence, and reconciliation logic should remain covered by unit or integration tests.
Supervised native-TUI backends#
When supervision work begins, one reusable fake backend should test the normalized state machine. Each real provider then needs a smaller compatibility suite covering:
- initialize and capability negotiation
- native TUI and supervisor attachment to the same exact session
- native ownership of input, rendering, questions, and approvals
- new session and exact-session resume
- streamed turns, commands, edits, and terminal activity
- observation of permission requests and user questions without taking ownership
- cancellation and immediate subsequent input
- supervisor disconnection while the native TUI continues
- supervisor death, restart, and same-session reattachment
- session close and resource cleanup
- mux restart and GUI reconnect
- two GUI clients observing one mux-owned supervisor
Codex app-server TUI additionally needs coverage for active-turn steering, subagent completion, nested or concurrent approvals, and provider upgrade compatibility. For another provider, a headless ACP mode is not a fallback when same-session native-TUI attachment fails.
Implementation order#
The current priority order is:
- Make detection falsifiable and observable.
- Make confirmed automatic adoption reliable.
- Persist authoritative provider session identity and explicit restore intent.
- Restore native harnesses by resuming the exact session.
- Make automatic layout restoration report partial and failed recovery honestly.
- Revisit structured supervision only when a provider can preserve its native TUI and pass the same-session attachment gate.
The supervised architecture informs today's identity and persistence choices, but it must not expand the current restoration work into premature backend implementation or a Wakterm-rendered agent UI.