Skip to content

feat: add ask-every-time session mode - #557

Open
karki011 wants to merge 1 commit into
agentclientprotocol:mainfrom
karki011:feat/ask-always-mode
Open

karki011 wants to merge 1 commit into
agentclientprotocol:mainfrom
karki011:feat/ask-always-mode

Conversation

@karki011

Copy link
Copy Markdown

Closes #555

Summary

Adds a fifth access preset, Ask every time (ask-always). It uses the same sandbox as workspace-write (workspace writable, no network), but sends approvalPolicy: "untrusted" with the user as reviewer. Every command and every file change then reaches session/request_permission, including reads such as ls or cat .env, which every other mode runs unasked.

Motivation

Clients that mediate every agent action through their own policy (audit trails, allow lists, secret-file rules) need a mode in which nothing runs unasked. #480 made the presets honest about what they allow; this adds the strict end of the range without changing the existing four modes or the default.

untrusted is the app-server's AskForApproval value for Codex's untrusted-project policy ("Commands require approval unless an explicit exec policy rule allows them"). Codex retired it as a config.toml or CLI setting in 0.149 (openai/codex#39630), but it is still part of the app-server v2 protocol in 0.157, and turn/start accepts it.

Evidence from a raw ACP client (fresh session per action, requests answered allow_once):

Action 1.13.1 / Codex 0.156.1, on-request 1.13.1 / Codex 0.156.1, untrusted this branch / Codex 0.157.0, workspace-write this branch / Codex 0.157.0, ask-always
ls ran, no request request ran, no request request
cat README.md ran, no request request not rerun request
cat .env ran, no request request ran, no request request
apply_patch in the workspace written, no request request written, no request request, written after allow_once
echo hi > shell.txt written, no request request not rerun request, written after allow_once

The untrusted column was also reconfirmed on 1.13.2-preview.5 / Codex 0.157.1. The issue has the full table.

The change

  • src/AgentMode.ts: new AgentMode.AskAlways ("ask-always", "Ask every time", kind standard, approval policy untrusted, reviewer user, a workspaceWrite sandbox identical to WorkspaceWrite, sandbox mode workspace-write). AgentMode.all() lists it last, after AgentFullAccess, so existing mode positions don't change.
  • Additional session roots are widened as for workspace-write, through the existing addAdditionalDirectoriesToSandboxPolicy.
  • README.md and readme-dev.md: INITIAL_AGENT_MODE lists ask-always.
  • No change to DEFAULT_AGENT_MODE, to CodexAcpClient.sendPrompt (it already sends the mode's policies on every turn/start), or to /status, which prints Approval: untrusted.

Tests

  • session-config-options.test.ts: ask-always added to the expected mode config options and availableModes, and seven rows added to the applies $modeId permissions after $selection from $initialMode matrix (selection through INITIAL_AGENT_MODE, session/set_mode and session/set_config_option, into and out of ask-always). The new snapshot data/ask-always-mode-policy.json pins the outgoing turn/start policies: untrusted, user, and workspaceWrite with the extra root writable and no network.
  • E2E (RUN_E2E_TESTS=true), new ask-always suites:
    • shell: a cat of a workspace file requests permission; an in-workspace write requests permission and is applied after allow_once; a cancelled request leaves the file unwritten.
    • file: an in-workspace edit requests permission and is applied after allow_once; a cancelled request leaves the file unwritten.

Local results:

  • npm run typecheck
  • CI=true npm test: 60 files passed, 786 tests passed, 37 skipped (the e2e suites)
  • npm run build
  • npm run bundle:all: not run locally (no bun installed); the change adds no dependencies or build inputs
  • npm run test:e2e: not run (needs an OpenAI API key); the manual probe above covers the same cases

Compatibility

  • Additive: a new mode id. Clients that list modes from availableModes or the mode config option show it automatically; clients that hard-code the four ids are unaffected. It is appended at the end of the list, so clients that pick modes by index are unaffected.
  • Codex dependency: this relies on the app-server continuing to accept approvalPolicy: "untrusted" on turn/start. If a later Codex removes it, turn/start would fail in this mode only, and the snapshot plus the e2e cases would flag it on the next codex-update PR. The issue discusses the alternative (not marking session roots trusted).
  • Known limitation (Codex behavior, the same in every mode): an approved command that Codex runs with escalated permissions leaves the sandbox, and the approval request doesn't say whether a command is escalated.
  • Under untrusted, Codex offers cancel as the only reject option, so rejecting ends the turn. The PR for Rejecting a command or file edit can only end the turn when Codex doesn't offer decline #556 adds an opt-in continue-on-reject option. The two PRs are independent and merge cleanly in either order.

🤖 Generated with Claude Code

Add an `ask-always` access preset ("Ask every time") that sends
`approvalPolicy: "untrusted"` with the user as reviewer and the same
workspace-write sandbox as `workspace-write` (no network). Every command
and every file change, including plain reads, then reaches
`session/request_permission`.

The mode is not the default and the existing presets are unchanged.
@karki011
karki011 marked this pull request as ready for review September 27, 2026 15:15

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No mode asks before every command and file edit (an untrusted-style preset)

1 participant