You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The agent that asks, plans, and pursues. OpenClaw runs on the Codex runtime, but OpenClaw users don't get the three interactive primitives Codex-native users take for granted: the agent can't ask a structured question, can't enter a reviewable plan mode, and can't be handed a long-running goal it pursues on its own. This issue is the master hub for the series that closes that gap: the architecture, the PR, exactly how to try and test each feature, and the follow-up roadmap.
The full flow — plan mode, the live plan pane, inline approval, and an inline agent question. A 30s narrated walkthrough covers goal mode too.
The gap, precisely (verified against both codebases)
Codex sessions: degraded to plain text; native sessions: nothing
Native ask_user_question + one question pipeline for both lanes, rendered on every surface, answerable cross-surface
Plan checklist
update_plan → live turn/plan/updated
Tool merged but experimental-flagged; events rendered as a bare text line
Promoted default-on + a live plan panel
Plan mode
ModeKind::Plan collaboration mode + /plan
Nothing
Read-only mode enforced at the tool choke point + approve-to-execute + plan artifact
Goal mode
goal tools + an idle-continuation loop + "Pursuing goal" UI
Goal state tools + /goal start|resume merged; no driver, no UI
A gated, debounced continuation driver + goal chip + full lifecycle
The pattern worth noticing: the primitives were already merged (update_plan, goal state, a codex user-input bridge, stream:plan events, approval UIs, channel buttons) — this series is the completion layer. Every feature rides an existing choke point rather than inventing a parallel system: the question manager mirrors the exec-approval manager; the plan gate lives in the one before-tool-call hook every tool execution funnels through; the goal driver fires through the cron system-event path. That's why the diff stays small for what it delivers.
The mental model: one interaction pipeline, two producers
Native tools (all models) — ask_user_question, plan-mode lifecycle tools, the goal driver: first-class OpenClaw features that work on Anthropic/Google/any model.
Codex pass-through (codex-runtime sessions) — the runtime's own request_user_input converges onto the same question pipeline (a structured answer and the legacy free-text path race; the loser is cancelled). Plan/goal wire bridges are documented follow-up seams.
One rendering surface, Codex-Desktop-shaped — in the Control UI, questions and plan-approval render as inline cards in the chat composer (not page-locking modals), the active plan docks in the right sidebar (always viewable, full checklist), a mode selector by the gear toggles plan/goal (mutually exclusive), and the goal editor is a focused modal. Telegram inline keyboards, Slack Block Kit, and numbered-text + /answer/plan/goal on every other channel. Ask on one surface, answer from another: resolution is global with scope/turn-source visibility, exactly like exec approvals today.
flowchart LR
subgraph Producers["Two producers, one dialect"]
N["🤖 Native tools (all models)<br/>ask_user_question · update_plan · plan mode · goal driver"]
X["⚙️ Codex runtime pass-through<br/>item/tool/requestUserInput · turn/plan/updated"]
end
N --> GW["Gateway<br/>global QuestionManager (cross-surface resolve)<br/>plan state · goal state + goal.updated"]
X --> GW
GW --> UI["🖥️ Control UI<br/>inline composer cards · right-sidebar plan · mode selector · goal modal · Pursuing-goal pill"]
GW --> TG["Telegram<br/>inline keyboards"]
GW --> SL["Slack<br/>Block Kit buttons"]
GW --> TXT["Every channel<br/>numbered text · /answer · /plan · /goal"]
Loading
Why the goal driver is safe to leave running
sequenceDiagram
participant T as Turn completes
participant D as Goal driver (debounced)
participant G as 4 gates
participant S as System-event turn
T->>D: arm (debounce + jitter) — the ONLY thing that arms it
D->>G: on wake: goal active? · no active run? · queue empty? · ceiling not hit?
G-->>D: any gate fails → re-arm silently (no fire)
G->>S: all pass → enqueue steering prompt + heartbeat wake
S->>T: turn runs with NORMAL privileges — exec approvals still block (tested)
Note over D: after a FIRE the driver never self-re-arms —<br/>only the next turn-completion arms it. No tight loop, by construction.
Loading
Layered brakes: debounce+jitter · the four gates · a durable no-progress ceiling (auto-pause, default 3) · budget limits (budget_limited disarms mid-wait) · an experimental flag (default off) · host-only pause/stop (the model can only mark complete|blocked, mirroring Codex).
🔍 Try it (per-feature test map)
Feature
Do this
Observe
Questions
Ask something ambiguous, or have the agent call ask_user_question
Inline card in the composer (not a modal); buttons pushed to Telegram/Slack; first option "(Recommended)"; "Other" free text; answer from a different surface than you asked
Modes
Click the mode selector by the gear → Plan or Goal
Mutually exclusive (can't have both); reflects /plan & /goal commands; switching while active confirms
Cross-surface
Ask via a Telegram session, answer in the Control UI (or /answer 2 from anywhere)
The parked tool resolves; the agent's next turn uses your answer
Restart safety
Restart the gateway with a question pending
question.expired fires; nothing hangs; the agent isn't stranded
Codex lane
Trigger request_user_input in a codex-runtime session
The same structured card (was: plain text); legacy free-text answering still works
Plan mode
Mode selector → Plan (or /plan) → ask for a refactor plan
Mutating tools refused with guidance; checklist ticks live in the right-sidebar plan pane; exit_plan_mode → inline approval card in the composer; reject-with-feedback → revised plan; approve → executes
Plan artifact
After approval
~/.openclaw/agents/<id>/plans/plan-<date>-<slug>.md; /plan show renders in-channel
Gate hardness
In plan mode, try exec / an MCP tool / a plugin tool / spawning a subagent
All vetoed at the single choke point (adversarial suite in-PR)
Goal mode
/goal set "<objective>" --budget <n> (flag on) and walk away
Follow-ups (filed as the post-merge roadmap; deliberately out of the first PR)
Codex plan-collaboration bridge — map OpenClaw plan mode onto ModeKind::Plan via thread settings (no plumbing exists in the codex extension today; documented seam).
Plan-mode power-ups — archetype prompting, escalating retry, plan-tier model routing (proven in a 156-case-parity-hardened plugin implementation; ported only if maintainers want them in core).
Question multi-select + secret inputs (isSecret is already in the shared schema).
Research-subagent allowance in plan mode (currently vetoed for gate hardness; relaxable by policy).
How this stays lean
No new dependencies anywhere in the series. Every human-in-the-loop interaction (questions, exit-plan approval, goal edit) is ONE pipeline — the same global-manager + scope-visibility pattern exec approvals already use. Features cluster in additive dirs; the tool gate is one policy at one choke point; the driver is one scheduler wired to two existing seams.
The full flow — plan mode, the live plan pane, inline approval, and an inline agent question. A 30s narrated walkthrough covers goal mode too.
The gap, precisely (verified against both codebases)
request_user_input— options + "(Recommended)" + free-text "Other"; the turn waitsask_user_question+ one question pipeline for both lanes, rendered on every surface, answerable cross-surfaceupdate_plan→ liveturn/plan/updatedModeKind::Plancollaboration mode +/plan/goal start|resumemerged; no driver, no UIThe pattern worth noticing: the primitives were already merged (update_plan, goal state, a codex user-input bridge,
stream:planevents, approval UIs, channel buttons) — this series is the completion layer. Every feature rides an existing choke point rather than inventing a parallel system: the question manager mirrors the exec-approval manager; the plan gate lives in the one before-tool-call hook every tool execution funnels through; the goal driver fires through the cron system-event path. That's why the diff stays small for what it delivers.The mental model: one interaction pipeline, two producers
ask_user_question, plan-mode lifecycle tools, the goal driver: first-class OpenClaw features that work on Anthropic/Google/any model.request_user_inputconverges onto the same question pipeline (a structured answer and the legacy free-text path race; the loser is cancelled). Plan/goal wire bridges are documented follow-up seams./answer/plan/goalon every other channel. Ask on one surface, answer from another: resolution is global with scope/turn-source visibility, exactly like exec approvals today.flowchart LR subgraph Producers["Two producers, one dialect"] N["🤖 Native tools (all models)<br/>ask_user_question · update_plan · plan mode · goal driver"] X["⚙️ Codex runtime pass-through<br/>item/tool/requestUserInput · turn/plan/updated"] end N --> GW["Gateway<br/>global QuestionManager (cross-surface resolve)<br/>plan state · goal state + goal.updated"] X --> GW GW --> UI["🖥️ Control UI<br/>inline composer cards · right-sidebar plan · mode selector · goal modal · Pursuing-goal pill"] GW --> TG["Telegram<br/>inline keyboards"] GW --> SL["Slack<br/>Block Kit buttons"] GW --> TXT["Every channel<br/>numbered text · /answer · /plan · /goal"]Why the goal driver is safe to leave running
Layered brakes: debounce+jitter · the four gates · a durable no-progress ceiling (auto-pause, default 3) · budget limits (
budget_limiteddisarms mid-wait) · an experimental flag (default off) · host-only pause/stop (the model can only markcomplete|blocked, mirroring Codex).🔍 Try it (per-feature test map)
ask_user_question/plan&/goalcommands; switching while active confirms/answer 2from anywhere)question.expiredfires; nothing hangs; the agent isn't strandedrequest_user_inputin a codex-runtime session/plan) → ask for a refactor planexit_plan_mode→ inline approval card in the composer; reject-with-feedback → revised plan; approve → executes~/.openclaw/agents/<id>/plans/plan-<date>-<slug>.md;/plan showrenders in-channel/goal set "<objective>" --budget <n>(flag on) and walk awayThe PR
Follow-ups (filed as the post-merge roadmap; deliberately out of the first PR)
ModeKind::Planvia thread settings (no plumbing exists in the codex extension today; documented seam).thread/goal/set|get|clear+thread/goal/updated↔ session goal (same: seam documented, zero plumbing today).isSecretis already in the shared schema).How this stays lean
No new dependencies anywhere in the series. Every human-in-the-loop interaction (questions, exit-plan approval, goal edit) is ONE pipeline — the same global-manager + scope-visibility pattern exec approvals already use. Features cluster in additive dirs; the tool gate is one policy at one choke point; the driver is one scheduler wired to two existing seams.