Reframed (2026-08-22) after review: invocation mode is surfaced as read-only transparency, not a user-selectable control. "Structured vs raw" is codebase plumbing that a real user (a developer using the coding agent) cannot meaningfully choose by name — and the consequences they do care about are already stated by the continuity / metering / attribution notes. So this issue ships the visibility of what's happening, and keeps the override out of the UI.
Depends on #728 (adapter seam) and #729 (so Codex has a structured path to show) for the "structured" state to be real; the fallback-warning half can ship independently.
What ships
-
Per-engine mode status chip in the CLI engines panel (agents/coder/web/src/EnginesModal.tsx): a small read-only chip showing which path will actually run — structured or raw — with a tooltip explaining the consequence in plain words: "Structured: the agent's real messages, spend metered, conversation remembered. Raw: unprocessed stdout, spend not visible, each turn starts cold." No picker.
-
Silent-downgrade warning. When the runner runs a path different from what the engine is capable of (e.g. a structured-capable Codex running raw because the machine's codex-cli lacks --json, or the runner predates the adapter), surface a named warning in the engine report — "running raw — structured not available on this machine's CLI" — mirroring the existing engineAuthWarning asked-vs-got pattern. This is the genuinely useful transparency and it requires no new user choice.
What does NOT ship (deliberately)
- No
mode dropdown / user override. Keep an internal mode capability in the data model only if an implementation needs it, but do not surface it as a control. Rationale: it adds a 4th interacting dimension (command × sign-in × mode × default) whose combinations users can't reason about, restates facts three existing notes already convey, and — once visible — becomes permanent UI debt. If a concrete user scenario later demands a raw override (e.g. debugging a broken structured adapter), file it separately behind an "Advanced" disclosure; today the escape hatch is editing the command to drop --json.
- Because there's no persisted user choice, this avoids adding a
resolved_mode column to coding_sessions (the chip derives the mode live from the resolved command + runner capability, like the auth report does). If an implementation still wants to persist it, that's a D1 migration and must be named explicitly — but the transparency-only design is specifically chosen to not need one.
Acceptance
Refs: #728, #729, #556, #732 (sign-in is the sibling per-engine dimension).
Reframed (2026-08-22) after review: invocation mode is surfaced as read-only transparency, not a user-selectable control. "Structured vs raw" is codebase plumbing that a real user (a developer using the coding agent) cannot meaningfully choose by name — and the consequences they do care about are already stated by the continuity / metering / attribution notes. So this issue ships the visibility of what's happening, and keeps the override out of the UI.
Depends on #728 (adapter seam) and #729 (so Codex has a structured path to show) for the "structured" state to be real; the fallback-warning half can ship independently.
What ships
Per-engine mode status chip in the CLI engines panel (
agents/coder/web/src/EnginesModal.tsx): a small read-only chip showing which path will actually run —structuredorraw— with a tooltip explaining the consequence in plain words: "Structured: the agent's real messages, spend metered, conversation remembered. Raw: unprocessed stdout, spend not visible, each turn starts cold." No picker.Silent-downgrade warning. When the runner runs a path different from what the engine is capable of (e.g. a structured-capable Codex running raw because the machine's codex-cli lacks
--json, or the runner predates the adapter), surface a named warning in the engine report — "running raw — structured not available on this machine's CLI" — mirroring the existingengineAuthWarningasked-vs-got pattern. This is the genuinely useful transparency and it requires no new user choice.What does NOT ship (deliberately)
modedropdown / user override. Keep an internalmodecapability in the data model only if an implementation needs it, but do not surface it as a control. Rationale: it adds a 4th interacting dimension (command × sign-in × mode × default) whose combinations users can't reason about, restates facts three existing notes already convey, and — once visible — becomes permanent UI debt. If a concrete user scenario later demands a raw override (e.g. debugging a broken structured adapter), file it separately behind an "Advanced" disclosure; today the escape hatch is editing the command to drop--json.resolved_modecolumn tocoding_sessions(the chip derives the mode live from the resolved command + runner capability, like the auth report does). If an implementation still wants to persist it, that's a D1 migration and must be named explicitly — but the transparency-only design is specifically chosen to not need one.Acceptance
rawwith no warning (it's a legitimate state, not a fault) — same "state it, don't imply it" bar as Coding sessions no longer use tmux, but the names, diagnostics, kill-tmux control and docs all still say they do #247/Show which credential a coding session actually used (subscription vs per-token API key) and what the engine really is #248.Refs: #728, #729, #556, #732 (sign-in is the sibling per-engine dimension).