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.
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 jsonThe 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 jsonThe 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
| Command | Result |
|---|---|
/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 status | Returns the newest visible snapshot. |
/goal pause | Persists pause intent, interrupts the current turn, and parks after retaining its terminal. |
/goal resume | Resumes a paused Goal or approves the active synthetic Goal gate. A terminal blocked Run is not resumable. |
/goal stop | Cancels the Goal Run and interrupts its work; keeps the terminal snapshot until Clear. |
/goal clear | Revokes 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 jsonReplacement 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 shapeCompozyOS 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:
| State | Meaning |
|---|---|
known | The provider reported a current context window size and usage ratio. |
unknown | No trustworthy report exists, or an observed compaction just completed. CompozyOS does not display or infer a percentage. |
pending | A 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:
| Action | In-flight work | Goal after settlement | Session after settlement |
|---|---|---|---|
| Pause Goal | Interrupt the exact managed turn; retain its terminal | Paused, resumable | Active and available for ordinary input |
| Resume Goal | Admit one successor after explicit control | Active | Must be active |
| Stop Goal | Cancel the Run and interrupt its exact prompt/judge leases | Terminal canceled; visible until Clear | Preserved |
| Stop session | Persist Goal pause before session termination | Paused; requires explicit Goal Resume | Stopped |
| Resume session | Restore the session runtime only | Remains paused | Active |
| Clear Goal | Cancel live work, then hide its projection | Audit retained | Preserved |
| Remove session | Cancel Goal before history deletion | Terminal canceled; Run audit retained | Removed |
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 jsonCancellation 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 jsonOptional --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 jsonThe 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_getreads the visible snapshot for the caller session and follows an active moved-binding alias.compozy__goal_controlapplies typed lifecycle operations to the caller session or an authorized descendant session.compozy__goal_reportrecordscompleteor evidencedblockedintent for the current prompt binding.compozy__loop_turnsreads 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.