Persistent Goals in the Agent Harness
Persistent completion contracts with independent judging, bounded continuation, restart recovery, and operational events.
Agent Orchestrator sessions support /goal for work that must continue until a verifiable result exists. A goal is session-bound durable control state, not a stronger wording of one prompt. Ordinary turns without a goal retain their existing behavior.
Commands
| Command | Result |
|---|---|
/goal <objective> | Replaces the stored goal and starts its first work loop. |
/goal status | Shows objective, state, current/max iteration, active-time limit, last judge result, timestamp, and next action. |
/goal pause | Persistently prevents another automatic work loop. An already-running turn is not forcefully interrupted. |
/goal resume | Reactivates paused or blocked work and dispatches the stored judge delta. A completed goal is immutable; set a new goal instead. |
/goal clear | Removes goal state without deleting the session or its event history. |
Lifecycle and completion contract
After every goal-dispatched work turn, ClapilotAICore atomically claims that turn for judging. Ordinary messages sent while a goal exists remain ordinary single turns. A separate ephemeral completion routed through the configured provider/model receives the original objective, iteration/limit state, the worker's final output, and locally observed evidence: current Git status, diff statistics, the current commit, and persisted tool-result events for that turn. The judge must return structured JSON with complete, continue, or blocked, a reason, missing work, and cited evidence. A Codex plain-completion fallback remains available for older deployments that do not inject the native provider router.
complete requires evidence that the stated acceptance criteria are met. The worker's own claim is insufficient. continue produces a new user-role work turn containing the original goal and the smallest concrete judge delta. Each continuation is detached from the originating HTTP or channel request and occupies the session FIFO only for its own worker turn. blocked is reserved for an external dependency or an exhausted hard limit. A malformed or unavailable judge may retry twice; the third consecutive judge failure blocks the goal instead of spending the full worker budget.
Defaults are 20 judged iterations and four hours of active goal time. Operators can set CLAPILOT_GOAL_MAX_ITERATIONS and CLAPILOT_GOAL_MAX_DURATION_SECONDS. Paused time is excluded. Reaching either limit deterministically persists blocked and schedules no further run; explicitly resuming a limit-blocked goal grants another bounded iteration or active-time window while retaining its history.
Persistence and concurrency
Goal state is stored inside the existing agent_external_sessions.metadata.goal JSONB document. It includes a stable goal ID, text, status, iterations, limits, accumulated active time, timestamps, last judge result, processed turn ID, in-flight judge claim, and next step. This deliberately needs no migration: agent_external_sessions is already the durable session system of record and survives runtime restarts.
The existing per-session FIFO prevents parallel work turns. Resume refuses to dispatch while any turn is queued or running. In addition, goal control writes and judge transitions use conditional PostgreSQL updates against the goal ID, status, and version timestamp. The final judge write is another compare-and-swap, so concurrent pause, clear, and judgement writes cannot restore stale state. Duplicate completion callbacks therefore cannot both judge or dispatch the same continuation, including across processes. The claim carries a five-minute lease timestamp: an interrupted runtime can reclaim abandoned judging after restart without allowing immediate duplicate callbacks.
Events and operations
Events are persisted with the normal orchestrator event stream using orchestrator_session.goal.* names: set, run_started, judged, continued, completed, blocked, paused, resumed, and cleared. Judge errors are visible in the judged event and do not silently mark a goal complete.
The design follows the bounded, independently judged continuation concept described by the Hermes Persistent Goals reference, while keeping durable state, queues, model routing, and observability inside ClapilotAICore.
Reviewer verification
Run the focused goal tests and the existing orchestrator suite. For a manual check, create an Agent Orchestrator session, set an intentionally two-step objective, confirm at least one continued event, then inspect /goal status. Pause and restart ClapilotAICore, confirm status remains paused, resume, and verify a completed goal dispatches no further turn. Send the same completion callback twice in an integration harness and confirm only one conditional claim succeeds.
