Skip to content

Operate a Goal from a session

Start, inspect, replace, pause, resume, draft, and audit a durable Goal through session commands, native tools, and Run history.

For people running agent work17 pages in this section

A conversational Goal attaches a durable, judged convergence Run to one existing session. Start it through the session prompt surface, keep working in the same thread, and inspect the same Run through Web, CLI, HTTP/UDS, or native tools. The daemon remains the source of truth; closing a browser or disconnecting the prompt response does not cancel a committed Goal.

/goal is parsed only at authenticated operator prompt ingress: Web, HTTP, UDS, and compozy session prompt. Internal, automation, extension, and synthetic prompts treat the same text as an ordinary message.

Start and inspect

Send a free-form objective to an active session:

compozy session prompt sess_123 '/goal Ship the requested change and keep make verify green.' -o json

The command returns a structured result. A successful start has outcome: started, the canonical snapshot, message_id, and idempotency_key. HTTP and UDS return the same Goal result inside the prompt envelope, which also reports replayed. Retrying the exact request with both original identities returns the stored result and preserves its original HTTP status without running the Goal command again. If the session already owns a visible Goal, CompozyOS returns goal_replace_required with the current snapshot instead of overwriting it. See Session events and safe retries.

Read the current Goal through any of these public surfaces:

  • Web session header — status, turn meter, context state, Run link, active binding link, and valid controls.
  • compozy session prompt <id> '/goal status' -o json — structured session command result.
  • compozy__goal_get — session-scoped native read, including terminal state until clear.
  • GET /api/workspaces/{workspace_id}/sessions/{session_id}/goal — canonical snapshot or { "goal": null }.

An authenticated agent can manage a child Goal with the typed control surface instead of sending slash-command text. Use compozy__goal_control with session_id and one operation (set, replace, status, pause, resume, stop, or clear), or use the equivalent compozy session goal ... CLI and POST /api/workspaces/{workspace_id}/sessions/{session_id}/goal HTTP/UDS route. The caller may target its own session or a descendant in the same workspace; an unrelated session is rejected with goal_caller_unauthorized. set and replace may include a typed provider/model/reasoning/speed runtime for the Goal worker. The Goal keeps its immutable creation identity, while the selected worker runtime is scoped to that run. Results are structured and include stable reason codes for stale replacement, invalid runtime, and failed binding evidence.

The snapshot includes run_id, node_id, objective, origin and bound session IDs, Goal and Run status, cause, turn counts, contract summary, latest nullable verdict, and context telemetry. A terminal newest Goal remains visible after restart until it is explicitly cleared. Clear returns the session projection to { "goal": null }; it does not delete the Run or expose an older Goal.

Audit verification sessions

Daemon-owned verdict-only system sessions, including agent judges, stay out of the default session list, attention badges and notifications. Expand the Goal header and choose Verification sessions to open a judge transcript. This audit lists system sessions attributed to the bound Goal session; the Run history retains the per-turn verdicts and evidence.

For CLI or HTTP/UDS audits, explicitly select the system type:

compozy session list --all --type system --parent <bound-session-id> -o json

The equivalent catalog filter is type=system&parent=<bound-session-id>. Older judges without parent lineage remain available with --type system alone. Existing transcripts and verdicts are preserved; no archive, deletion or data migration is needed. Other system sessions, including automation and task workers that may need operator action, remain visible. Completed idle judges close their provider process with verified exit rather than raising a false cancellation-timeout warning.

Queued messages during a Goal

At an idle turn boundary, CompozyOS drains a finite batch of eligible queued operator prompts, agent messages, and synthetic wakes (including session replies) before dispatching a prepared Goal prompt, even when that Goal prompt was prepared earlier. The first public-input claim freezes the batch's admission boundary durably. Inputs admitted later wait until after that Goal prompt; they cannot keep extending the batch. Interrupt replacements retain precedence. Within the batch, existing priority and FIFO ordering remain in force; unresolved steers retain their eligibility rules. Queue reads and positions show public inputs and exclude internal Goal prompts.

Queued inputs run as their own turns and do not increment the Goal's work-turn count. Its binding, control epochs, turn limit, and existing budget guards remain intact. The saved batch boundary survives restart. Queue mode never preempts the currently running turn: a long turn can delay after_turn delivery until it ends. Use fenced steering or interrupt when guidance must arrive during that turn.

Command grammar

CommandResult
/goal <objective>Starts one session-origin Goal. Returns goal_replace_required when a visible Goal already exists.
/goal replace <expected-run-id> <objective>Replaces exactly the Run the operator reviewed. A stale ID returns goal_replace_stale and preserves the current Goal.
/goal statusReturns the newest visible snapshot.
/goal pausePersists pause intent, interrupts the current turn, and parks after retaining its terminal.
/goal resumeResumes a paused Goal or approves the active synthetic Goal gate. A terminal blocked Run is not resumable.
/goal stopCancels the Goal Run and interrupts its work; keeps the terminal snapshot until Clear.
/goal clearRevokes live Goal work when needed, then hides the newest live or terminal projection without deleting its audit.
/goal draft <rough text>Runs one ordinary streamed agent turn that expands the draft; it does not activate a Goal. The composer prefills the result.

Reserved verbs accept only the arguments shown. Objectives are limited to 4,000 Unicode code points. Unknown text after /goal is the objective for the start form, not a command registry.

Replace safely

Use the run_id from the current snapshot as the expected ID:

compozy session prompt sess_123 \
  '/goal replace run_current Ship the narrower objective and keep make verify green.' \
  -o json

Replacement prepares the candidate before it stops the old Run. Invalid candidate configuration leaves the old Goal live. Concurrent valid replacements have one compare-and-swap winner; other callers receive goal_replace_stale with the newer snapshot.

Draft before activation

compozy session prompt sess_123 '/goal draft fix the flaky checks without broad rewrites'

Draft is the only /goal form that stays on the ordinary streaming response path. It is admitted only while the session prompt slot is idle. A busy or race-busy session returns goal_draft_requires_idle before stream headers and does not queue, steer, interrupt, or count a Goal turn. Review the generated objective and optional clauses, then submit the prefilled /goal command yourself.

Verification and constraints

The start and replace objectives accept line-oriented lowercase clauses:

/goal Ship the parser cleanup without changing unrelated packages.
verify: make verify remains green
verify: generated OpenAPI has no drift
constraints: preserve the public CLI shape

CompozyOS stores the non-clause lines as the objective. Each verify: and constraints: line must contain text. The synthetic Goal always uses one canonical agent-judge criterion. Verification text is added to that judge rubric; it is never executed as a shell command. To author an actual command criterion, use a goal node in a compozy.loop/v1 definition.

Context and recovery

The context gauge reports evidence from the active Goal checkpoint:

StateMeaning
knownThe provider reported a current context window size and usage ratio.
unknownNo trustworthy report exists, or an observed compaction just completed. CompozyOS does not display or infer a percentage.
pendingA compaction turn ended without the agent reporting a compaction lifecycle, and CompozyOS still needs a strictly newer usage report to judge it.

[goals].context_nudge_ratio is pinned when the Run starts. When known usage reaches that threshold, CompozyOS asks the agent to compact its own context by sending the command the agent advertises, /compact or else /compress, as an operational prompt in maintenance mode on the managed Goal path. It is not a user-authored human message and not a Goal work turn. The compaction succeeds when the newest status CompozyOS observed for it is completed; failed or cancelled does not. The outcome follows the current status, so a correction before the turn ends (completed to failed, or failed to completed) changes it. After an observed completed update the gauge reads unknown until a later usage report carries both used and a positive window size; a used-only or counter-only report does not make it known. When the agent reports no compaction lifecycle at all, a normal turn end counts as success and the gauge is pending: the next strictly newer usage report must show used below the value measured before the compaction, otherwise the Goal takes the reseed path. An agent that advertises neither command goes straight to the reseed path below. This turn is experimental, because it follows an unstable upstream agent contract. See Session compaction.

CompozyOS does not replay an ACP prompt after its durable start. A restart with exact terminal evidence reconciles that terminal result. Missing proof becomes an ambiguous turn and a typed approval boundary. A max_tokens recovery starts a new continuation turn that inspects current state; it is not a retry of the previous prompt.

Run-owned Goals may reseed automatically when compaction cannot recover the binding. A session-origin Goal requires explicit approval before it moves away from the user's conversation. After approval, origin_session_id remains the owner and bound_session_id points to the active successor session. Use the active-session link for ordinary messages; /goal controls remain on the origin session.

Pause and approval re-entry enqueue one successor segment under a new control epoch. Repeated resume/approve calls do not create multiple successors. A terminal blocked Run stays terminal; change the objective with expected-Run replacement or clear the projection instead of resuming it.

Stop, remove, or recover a Goal

The Goal and session state machines compose as follows:

ActionIn-flight workGoal after settlementSession after settlement
Pause GoalInterrupt the exact managed turn; retain its terminalPaused, resumableActive and available for ordinary input
Resume GoalAdmit one successor after explicit controlActiveMust be active
Stop GoalCancel the Run and interrupt its exact prompt/judge leasesTerminal canceled; visible until ClearPreserved
Stop sessionPersist Goal pause before session terminationPaused; requires explicit Goal ResumeStopped
Resume sessionRestore the session runtime onlyRemains pausedActive
Clear GoalCancel live work, then hide its projectionAudit retainedPreserved
Remove sessionCancel Goal before history deletionTerminal canceled; Run audit retainedRemoved

pause_requested: true means the pause is committed but work is still settling. The Web strip shows Pausing… until the effective state arrives and keeps Stop available. Repeated Pause, Resume, or Stop requests are idempotent within the same Goal. A terminal Goal cannot be resumed. Resume is available after Paused. An API or command request during Pausing… returns goal_control_stale (HTTP 409) and preserves the pause; refresh status and retry once it settles. If Clear wins while Pause, Resume, or Stop is finishing, the control returns cleared without a stale snapshot. Stop's cancellation step runs independently of client disconnect within a bounded deadline; after a lost response, read Goal status to confirm the result.

User controls fence further prompt claims before interrupting work. A late provider terminal may attach its exact event range to the original token-authenticated receipt after revocation, but cannot advance its checkpoint, resurrect the Run, or create a second turn terminal. The control outcome remains authoritative. Trailing usage/command telemetry does not invalidate a completed turn; a second terminal or result-bearing output after the terminal still fails validation.

Context usage is supplementary: an event-read failure yields context.state: unknown and context.diagnostic: goal_context_unavailable, while durable state and controls remain available. The Web preserves the last snapshot during a failed refresh, surfaces the error, and offers Retry.

Stopping the origin or current bound session pauses its session Goal before stopping the runtime. The Goal remains resumable, and resuming the session alone never resumes the Goal. Resume the session, then explicitly resume the Goal. Removing the session cancels its Goal before deleting history. If lifecycle settlement fails, the durable stop receipt remains pending; retrying Stop or restarting the daemon retries the settlement. Deletion cannot bypass a pending settlement. The Run, turns, and task audit stay inspectable. Closing only a window, disconnecting a stream, or restarting the daemon does not cancel a committed Goal. Informational origins of catalog Loops retain their separate lifecycle.

A canceled Goal shows a terminal run_status: canceled, live: false, and Goal status paused, including when it stopped before the first work turn. Resume is unavailable. A quarantined Goal shows blocked with node_quarantined; inspect its Run and requeue the node after repairing the cause, or cancel it. Previous failed attempts remain in the audit.

If an older Goal outlived a session that was already removed, use its Run controls:

compozy loop runs --origin session --origin-session sess_123 -o json
compozy loop cancel --run-id run_123 -o json
compozy loop status --run-id run_123 -o json

Cancellation is idempotent and does not require the missing session. A missing-session error on session controls and a connection refusal from an unavailable daemon are different failures; reconnect to the owning daemon before operating on its Run.

Active task leases keep ongoing Goal work fresh even before its first completed coordinator pass. Status reads do not extend those leases or wait deadlines. Real expired work, quarantine, approval, and intervention still surface Needs attention, including while the agent produces other progress.

Audit turns

Every durably started work prompt consumes one monotonic Goal turn. Compaction does not. Read the run-wide total order with:

compozy loop turns --run run_123 --after-seq 42 --limit 50 -o json

Optional --node and --item filters narrow one Goal instance. result_status, reason, stop reason, verdict, evidence, token usage, and ended_at are nullable until the corresponding evidence exists. Settled turns also retain bounded criteria[] and aggregate warnings[]. Each criterion records its outcome and, when applicable, exit code, standard output, standard error, blockers, and warnings. The Web Run page shows the same diagnostics, so a continuation can act on the failed check instead of repeating completed work. The response returns next_after_seq for the next page. See the generated compozy loop turns reference.

List only conversational Goal Runs, or one origin session:

compozy loop runs --origin session --origin-session sess_123 -o json

The Web Run page merges persisted pages with the three Goal Run events without duplicating turns. Session discovery remains separate: persisted goal_snapshot_changed frames announce start, replace, status, clear, and reseed changes on the always-on transcript stream, including changes made through another public surface.

Prompt metadata and native reports

Persisted transcript events tag engine-owned prompts as goal-work, goal-continuation, or goal-compaction, with Run, node, generation, item, prompt attempt, prompt ID, and nullable turn. The tags survive reload; clients do not infer them from prompt prose.

Agents operating inside the active binding have three dedicated tools:

  • compozy__goal_get reads the visible snapshot for the caller session and follows an active moved-binding alias.
  • compozy__goal_control applies typed lifecycle operations to the caller session or an authorized descendant session.
  • compozy__goal_report records complete or evidenced blocked intent for the current prompt binding.
  • compozy__loop_turns reads the workspace-authorized Run audit with cursor and node/item filters, even after the binding is terminal.

compozy__goal_report is a durable boundary intent, not immediate completion or proof of provider-side effect uniqueness. It is available to the current bound Goal prompt whether the Run started from a session, the catalog, HTTP, or a native tool. The daemon revalidates workspace, Run, prompt, control, and binding epochs when invoked. Evidence is limited to 16 KiB; blocked requires evidence. Retries with the same payload deduplicate, while conflicting or revoked reports fail with stable reason codes. Resolve each live descriptor with compozy__tool_info before calling it.

Configure defaults

New conversational and authored Goals consume the resolved [goals] defaults where the public start path applies them. Active Runs keep their pinned values. See the [goals] config reference for precedence, mutable paths, bounds, and restart lifecycle.

A stopped session reopens when you send an ordinary message. Control-only /goal commands do not reopen it. The Goal stays paused until an explicit Resume after the session is active.

On this page