[Bug]: Claude Auto mode on orchestrator v2 runs ask-rule commands without prompting#15353

opened21d agobyTTonybynMp4

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Add an ask rule to Claude Code's user settings, for example "permissions": { "ask": ["Bash(git push:*)"] }.
  2. Start a Claude thread on orchestrator v2 with the permission mode set to Auto.
  3. Ask the agent to run git push (or any command matching the ask rule).

Expected behavior

T3 Code shows an approval request, the same way Claude Code does in its own auto mode. The permission modes guide says Auto "uses the provider's automatic review to approve routine actions and ask about others".

Actual behavior

The command runs with no prompt, the same as Full access.

Claude's auto mode sends anything it wants a human to decide (an ask rule match, a protected path, a classifier escalation) to the SDK canUseTool callback. In ClaudeAdapterV2, that callback answers allow whenever requiresClaudeApproval is false, and installPermissionCallback is false for auto. So every request Claude escalates gets approved without the user seeing it.

The V1 adapter skipped the prompt only for full-access and asked in Auto. #13786 fixed the same problem for Auto-accept edits and left Auto unchanged.

Impact

Major degradation or frequent failure

Version or commit

main @ 65731f986b

Environment

Linux, Claude Code provider, orchestrator v2

Workaround

Use Supervised, or add a PreToolUse hook that blocks the command.

Note

Grok responding on behalf of Julius.

Triage

Thanks for the precise report, @TonybynMp4! This reproduces on current main. A Claude thread in Auto auto-approves the tool calls Claude has already decided to ask about, including a permissions.ask match. It's the same gap that merged #13786 closed for Auto-accept edits, still open for Auto.

What happens

claudeRuntimeQueryPolicyForRuntimePolicy in apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts maps runtimeMode: "auto" to Claude's permissionMode: "auto" with installPermissionCallback: false. The query always gets canUseTool anyway, and requiresClaudeApproval is that same flag. So after the AskUserQuestion and ExitPlanMode special cases, the callback returns allow right away. The test maps Auto runtime mode to Claude's AI-reviewed permission mode pins the flag at false.

Claude checks content-scoped ask rules before its auto-mode classifier, and it sends a match to canUseTool instead of letting the classifier approve it. Bash(git push:*) is the trailing-wildcard form of Bash(git push *), so your repro rule is a real ask. The query leaves settingSources unset, which means user settings load and a rule in ~/.claude/settings.json applies. The permission modes guide says Auto approves routine actions and asks about others, but today those asks never reach the thread.

Routine classifier approvals never call canUseTool, so routing asks to the user wouldn't turn Auto into Supervised. A one-off classifier block isn't a prompt either and stays inside Claude. The callback does see the later fallback, when repeated blocks make Claude start prompting again. It also sees anything else Claude routes as an ask, such as org connector tools set to ask or MCP tools marked requiresUserInteraction.

Likely fix area

  • One option is to treat auto like auto-accept-edits when approvalPolicy is unset, so the callback raises a normal approval request instead of allowing. An explicit approvalPolicy: "never" could stay non-prompting.
  • A test like the Auto-accept edits one, repeated for runtimeMode: "auto", would cover it. It would call canUseTool for a Bash command and require a command runtime request before any decision. The policy-mapping assertion would change along with it.
  • Full access (bypassPermissions) has the same auto-allow, and Claude would still send ask rules to the callback there. The guide says that mode doesn't prompt, so whether it should honor ask rules is a separate question.

Until then, Supervised or a PreToolUse hook that denies the command are good workarounds. A maintainer will decide on the fix direction.

Synced from GitHub

Note

Claude responding on behalf of Ali.

Adding real-world data in support of this, and of #15360.

From my local T3 state database (macOS, Nightly channel):

  • 2026-09-13 to 2026-10-03 (V1 adapter): 305 Claude approval prompts were shown. 274 of them came from threads that are in Auto mode now.
  • 2026-10-04 onward (orchestrator v2): 0 approval prompts. All 70 runtime requests were question cards.

Why this matters beyond UX: PreToolUse hooks that return ask are now silently allowed in Auto threads. I rely on ask hooks to confirm outbound and write actions, and in Auto threads they pass with no prompt. As a workaround I had to change the critical ones to deny when they detect a T3 Auto session.

Rechecked on 0.0.46-nightly.20261013.3066: installPermissionCallback is still only true for approval-required and auto-accept-edits, so the bug is still present. #15360 looks like the right fix, and I'd be glad to see it reviewed.

Synced from GitHub

Note

Claude responding on behalf of MacKinley.

Still reproduces on 0.0.46-nightly.20261014.3105 with Claude Code 2.1.299. One detail I haven't seen mentioned yet: the auto-allow is recorded as if the user approved it.

A PreToolUse hook returned permissionDecision: "ask" in an Auto thread. The command ran with no prompt, and the tool_result entry in Claude Code's session transcript (~/.claude/projects/<project>/<session>.jsonl) says:

json
1"permissionDecision": {"decision": "accept", "source": "user_temporary"}

That is the same record a human clicking "allow once" produces. For comparison, commands the Auto classifier approves on its own are recorded as {"decision": "accept", "source": "config", "reasonType": "classifier"}. So when the callback answers allow for an escalated request, the transcript attributes the approval to the user. That makes the audit trail misleading even after the fact: you can't tell from the record that nobody saw the request.

It would be worth checking that #15360 also fixes the attribution. If Auto is ever meant to approve an escalation without a prompt, it would be better recorded as something other than a user decision.

For anyone writing a hook workaround in the meantime: hooks run under T3 Code see CLAUDE_CODE_ENTRYPOINT=sdk-ts, which is one way to switch an ask to deny only when T3 is the host.

Rechecked current main at defb7e6e6b. An adapter regression test reproduces the Auto escalation bug: the command ran without asking: expected decision to equal request. Auto-accept edits passes as the control. Applying only the Auto callback-policy hunk from #15360 makes both cases pass; all 208 current-main Claude adapter tests pass, with no scoped lint errors.

The real-app attempt used an isolated Linux web dev server, a fresh Git project with no remote, Claude Sonnet 5.5, Auto, and Bash(git push:*). The command could not be submitted: the backend logged an 84.8-second event-loop stall and repeated disconnects, and the browser readiness wait timed out after 60 seconds. This does not verify the real-provider approval round trip.

The existing fix remains #15360, now labeled bugfix; no competing PR was opened. The issue remains open until that fix lands.