feat: default agent permission mode to Bypass Permissions - #2225
Conversation
When no agent profile, project agent override, or user agent setting picks a permission mode, agent sessions now start in bypassPermissions instead of the agent's always-ask "default" mode. Since the ACP permission bridge (#2202) routes permission prompts to chat, "default" stopped behaving like the old auto-approve path and left agents waiting on the human. - shared: DEFAULT_AGENT_PERMISSION_MODE = 'bypassPermissions'; relabel the 'default' mode "Manual" (Claude Code's name) so it is not mistaken for SAM's default - api: the VM agent's /agent-settings callback falls back to the platform default (project override > user setting > default); explicit choices, including Manual, are unchanged - web/acp-client: Settings -> Agents and the workspace chat settings panel preselect the platform default when nothing is saved - MCP profile/skill tool text and the agents guide document the default - tests: behavioral route test on real SQLite (replaces source-text check), card and chat panel unit tests, Playwright audits at 375px and 1280px Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 1 minute. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (17)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
AGENT_PERMISSION_MODE_DESCRIPTIONS had no consumers. Rename a test local that now points at the Bypass Permissions radio. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
@coderabbitai review |
|



Summary
Raphaël asked: "The default mode for all agents should be bypass permissions."
When no agent profile, project agent override, or user agent setting picks a permission mode, agent sessions now start in Bypass Permissions instead of the agent's always-ask
defaultmode.Why it matters now: before #2202 (Sep 30) the VM agent auto-approved every ACP permission request whatever the mode. Since #2202,
default-mode requests go to the human in chat (or are cancelled whenACP_INTERACTIONS_ENABLEDis off), so unconfigured agents started stopping to ask.DEFAULT_AGENT_PERMISSION_MODE = 'bypassPermissions'. Thedefaultmode ID is relabelled Manual (Claude Code's own name for it), so "Default" is no longer a non-default option.POST /api/workspaces/:id/agent-settingscallback resolves project override → user setting → platform default (was→ null). Every runtime (VM and Instant) fetches its settings here at session start, so this applies to already-running nodes once the API deploys; no VM-agent rollout is needed. A profile's own mode still overrides it (applyProfileOverridesin the VM agent). Explicit choices are unchanged, including Manual.defaultPermissionModeprop onChatSettingsPanel/AgentPanel).permissionModefield text and the public agents guide document the default.Per-agent effect:
bypassPermissionsvia ACPSetSessionMode. The adapter allows this for non-root users, which covers Instant containers (USER node) and normal devcontainers. Even in Bypass, Claude still asks about a few "bypass-immune" safety checks; those still show in chat.approval_policy: never+danger-full-access.acp-amp0.1.3) stores the ID but only auto-approves for its ownbypassID, so it keeps asking. None of these change from today's explicit-Bypass behavior.Production check (read-only): every saved per-user
agent_settingsrow is alreadybypassPermissions. The old built-in profiles (implementer/default→ Accept Edits,planner/reviewer→ Plan, in ~12 projects) are explicit choices and are not migrated by this PR.Validation
pnpm lint(viapnpm check:fast: format ratchet, oxlint, eslint, type-boundary ratchet)pnpm typecheck(shared, acp-client, api, web)pnpm test: shared 773/773, acp-client 557/557, web 3977/3977 (330 files), targeted api suites 67/67 (incl. the new route test); full api suite runs in CI083cd5969(UI review nits): removedAGENT_PERMISSION_MODE_DESCRIPTIONS, which had no consumers, and renamed a test local; typecheck and card tests re-run greenDiscrimination checks (each guard reverted once, then restored):
?? null: exactly the 4 default-path tests inworkspace-agent-settings-callback.test.tswent red; the explicit user-mode, explicit Manual and project-precedence controls stayed green.AgentSettingsCardfallback reverted to'default': exactly the 3 new default tests plus the updatedagent-cardsave test went red; the saved-Manual control stayed green.AgentPanelpass-through removed: the new AgentPanel default test went red.Staging Verification (REQUIRED for all code changes — merge-blocking)
fb53ed0ea;083cd5969only removes an unused export and renames a test localapp.sammy.partyStaging Verification Evidence
A/B on staging with one Claude Code Instant profile with no mode (
Claude Code Chat, projecthono, which has no Agent Overrides). The prompt and runtime were identical; only the smoke user's saved Claude Code permission mode changed:mkdir -p /tmp/staging-check && date … > /tmp/staging-check/ts.txt && echo STAGING_CHECK_DONE …with no prompt and repliedSTAGING_CHECK_DONE 20261004T120553(sessionb4fd4654…). The VM agent recordedACP session mode applied {"mode":"bypassPermissions"}(staging observability, workspace01M43CVV746APNB4TYWT3660JS). Before this PR that combination sent noSetSessionModeat all. A first run (fec49518…) showed the same.df75c896…). No session-mode event, as expected. Staging hasACP_INTERACTIONS_ENABLED=false, so Manual-mode requests are denied rather than shown in chat.Cleanup: all 4 test sessions are
cancelledwith workspaces/nodesstopped. The smoke user's Claude Code setting was restored to its original row (bypassPermissions, provider modesam).Unrelated pre-existing staging issues seen (not caused by this PR; added to existing ideas):
POST …/sessions/:id/stopreturned 500Managed node teardown remains unconfirmedfor every Instant stop, in both modes (23+ staging occurrences since 2026-09-11; idea01M3KYP55W91YQHV2FN1A2NVBT).Snapshot wip artifact is missing(HTTP 400) from the vm-agent on one stop; it did not recur.get_instructionsnote in Instant sessions as a possible prompt injection (idea01KX4HFF2Y66RW1V7TVV1ZTP7X).UI Compliance Checklist (Required for UI changes)
aria-checked/toBeCheckedasserted in Playwright)assertNoOverflow(includes clipped-overflow walk) on every captureUI Screenshot Evidence
All screenshots below were taken with Playwright from local mock-data audits (
apps/web/tests/playwright/agent-settings-audit.spec.ts,apps/web/tests/playwright/chat-settings-permission-default-audit.spec.ts) at 375x667 and 1280x800.Surface: Settings → Agents permission mode (AgentSettingsCard)
Surface: Workspace chat Agent Settings panel (ChatSettingsPanel)
End-to-End Verification (Required for multi-component changes)
runtimeRoutes+ real SQLite for the resolution step; staging session for the runtime step)Data Flow Trace
packages/vm-agent/internal/acp/session_host_selection.go:loadAgentSettings→session_host_reporting.go:fetchAgentSettings→POST /api/workspaces/:id/agent-settings(same code in VM and Instant runtimes).apps/api/src/routes/workspaces/runtime.tsagent-settings callback:resolveProjectAgentDefault(project.agentDefaults)→ useragent_settingsrow (scoped byuser_id+agent_type) →DEFAULT_AGENT_PERMISSION_MODE.applyProfileOverrides(a profile's explicit mode wins) →session_host_settings.go:applySessionSettings→ ACPSetSessionMode(bypassPermissions)for non-Codex agents.session-mode.jsswitches the session tobypassPermissions(permissions/modes.js: allowed for non-root users or withIS_SANDBOX).Untested Gaps
bypassPermissionsmode ID (Amp calls itbypass, Geminiyolo). Mapping SAM's mode to their native equivalents is out of scope here; those agents keep their own default.Post-Mortem (Required for bug fix PRs)
N/A: not a bug fix (product default change requested by the owner).
Specialist Review Evidence (Required for agent-authored PRs)
needs-human-reviewlabel added and merge deferred to human (N/A: both completed)bypassPermissionswas unverified. I checkedacp-amp0.1.3server.py:set_session_modestores the ID, and only the literalbypassenablesallow_all, sobypassPermissionsleaves Amp in its normal asking mode (no escalation; Amp not bypassed, which is noted as a known gap). LOW: saving another field persists the preselected mode explicitly. This is the existing pattern (it persisteddefaultbefore) and was accepted.083cd5969(unusedAGENT_PERMISSION_MODE_DESCRIPTIONSremoved; test local renamed). Pre-existing, unchanged by this PR: chat-panel warning lacksrole="alert"; chat-panel radios lack roving tabindex.CodeRabbit Review Evidence (Required for agent-authored PRs)
CodeRabbit Notes
Requested 2026-10-04T12:13:26Z by adding the
coderabbit-reviewlabel (thecoderabbit-bot-review.ymlrun succeeded) after local review, staging and green CI. I watched until 12:29:48Z (about 16 minutes). CodeRabbit posted only a rate-limit notice ("Review limit reached — You've used all free OSS reviews for now"; run81fe0860-d673-4f08-9279-33c5f33c5685) and no review. Under.claude/rules/25-review-merge-gate.mdthat counts as no review: I recorded it and did not re-trigger.Exceptions (If any)
Agent Preflight (Required)
Classification
External References
@agentclientprotocol/claude-agent-acp0.81.2 (installed package source):dist/session-mode.js(mode catalog,parseMode),dist/permissions/modes.js(ALLOW_BYPASS: non-root orIS_SANDBOX),dist/acp-agent.js(bypass-immune permission requests still reach the client).packages/opencode/src/acp/service.ts(setSessionModerejects modes not inavailableModes).packages/cli/src/acp/acpSession.ts(setModethrows "Invalid or unavailable mode").vibe/acp/agent.py(set_session_modeignores non-primary modes).Codebase Impact Analysis
packages/shared(constant + labels),apps/api(routes/workspaces/runtime.tsagent-settings callback; MCP field text),apps/web(AgentSettingsCard,ChatSession),packages/acp-client(ChatSettingsPanel,AgentPanel).packages/vm-agentis intentionally unchanged. Request I/O for the callback is unchanged (2 D1 reads).Documentation & Specs
apps/www/src/content/docs/docs/guides/agents.md: new "Permission mode" section.Constitution & Risk Check
Principle XI: the default is one shared constant (
DEFAULT_AGENT_PERMISSION_MODE), not a URL, timeout, limit or identifier. Users can still choose any mode per agent, project or profile. Risk: agents now run without permission prompts by default. That is the requested behavior; explicit restrictive choices still win, and an unreadable config falls back to the always-ask mode.🤖 Generated with Claude Code