Goal pause state exists, but agent tool contract can make agents report pause is unavailable
Summary
Goal pause appears to be supported by the local goal model and runtime events, but the agent-visible contract can lead the agent to tell the user that pause is unavailable.
In one Codex Desktop thread, the user explicitly asked to pause the goal while keeping an automation/heartbeat running. The agent answered that the goal tool did not expose a pause status and said the goal would remain active. Shortly after that, the runtime emitted thread_goal_updated with status: "paused", and a later get_goal returned the same goal as paused.
This creates a confusing state where pause exists and is applied, but the agent can misreport it as unsupported.
Environment
Observed on 2026-06-29:
- Codex Desktop macOS app:
26.623.70822 - App bundle version:
4559 - Parent session metadata reported:
cli_version: 0.142.4 - Local shell
codex --versionreports:codex-cli 0.142.1 - Repository issue filed from macOS / Codex Desktop
Local evidence
The local goal DB schema explicitly permits paused:
CREATE TABLE thread_goals (
thread_id TEXT PRIMARY KEY NOT NULL,
goal_id TEXT NOT NULL,
objective TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN (
'active',
'paused',
'blocked',
'usage_limited',
'budget_limited',
'complete'
)),
token_budget INTEGER,
tokens_used INTEGER NOT NULL DEFAULT 0,
time_used_seconds INTEGER NOT NULL DEFAULT 0,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL
);
The same local DB had multiple paused goals, including the active thread under investigation.
Relevant rollout sequence from the affected thread, redacted to avoid private content:
get_goalreturned the current goal withstatus: "active".- The user said:
you may pause the goal but keep the heartbeat! - The agent responded:
Paused here. The goal tool does not expose a `pause` status, so I did not mark it complete or blocked; it remains active in the tool state...
- No visible
update_goalorset_goalcall appears in the transcript around that turn. The only visible goal calls in the thread werecreate_goaland repeatedget_goalcalls. - The runtime then emitted:
{
"type": "thread_goal_updated",
"threadId": "<same-thread-id>",
"goal": {
"status": "paused"
}
}
- A later
get_goalreturned:
{
"goal": {
"threadId": "<same-thread-id>",
"status": "paused"
}
}
In the follow-up side conversation, deferred tool discovery for goal pause/update did not expose an agent-facing pause/update goal tool either; it returned unrelated tools.
Expected behavior
When a user asks the agent to pause a goal:
- The agent should have an explicit, documented way to pause the goal, for example
update_goal({"status":"paused"}), or - If pausing is intentionally handled by the runtime rather than the model, the agent should be told that this will happen and should not claim pause is unsupported.
The model-visible goal contract should match the runtime and storage model. If paused is a valid persisted/runtime state, the tool schema and instructions should not lead agents to say only complete/blocked are possible.
Actual behavior
- Local storage supports
paused. - Runtime emits
thread_goal_updatedwithstatus: "paused". get_goallater confirmsstatus: "paused".- The agent can still tell the user that pause is not exposed and that the goal remains active.
- No explicit agent-visible pause/update call is present in the transcript around the transition.
Why this matters
For long-running Goal mode work, users need reliable lifecycle semantics: active, paused, blocked, and complete are meaningfully different. If the agent incorrectly says a goal cannot be paused, users lose trust in manager/heartbeat workflows and may think the goal is still consuming active attention even after the platform has paused it.
This is especially confusing for workflows where the goal should pause but an external monitor/automation should continue running.
Suggested fix direction
One of these would make the behavior coherent:
- Expose
pausedin the agent-facingupdate_goalschema when goal update tools are available. - If pause is runtime-owned, inject an explicit event/instruction visible to the agent before final response generation, so the agent can say the runtime has paused the goal.
- Ensure
get_goal/goal lifecycle guidance clearly documents all supported statuses, includingpaused,usage_limited, andbudget_limitedif they can appear. - Add a regression test for: user asks to pause a goal -> final agent answer must not claim pause is unavailable -> subsequent
get_goaland emitted goal event agree onpaused.
Related issues
This is adjacent to, but narrower than:
- #24094: goal tools not exposed at all
- #24978: completed goals cannot be cleared / update lifecycle is incomplete
- #28430: completed-goal lifecycle differs between slash command and agent tool
- #29813: goal event replay/thread-id inconsistencies
This report is specifically about the paused lifecycle state existing in storage/runtime while the agent-visible contract can still cause a false "pause is unavailable" answer.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗