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
{{ message }}
Repository navigation
[Bug]: Claude Auto mode on orchestrator v2 runs ask-rule commands without prompting #15353
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
Add an ask rule to Claude Code's user settings, for example "permissions": { "ask": ["Bash(git push:*)"] }.
Start a Claude thread on orchestrator v2 with the permission mode set to Auto.
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.
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.
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.
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:
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.
Still present on upstream main at 4b87a45 (2026-11-04). Two things I think aren't in this thread yet: what this costs when an ask guards something expensive, and the fact that, since #21806, Auto is now the less protective of the two modes for these requests.
What it cost
I use a PreToolUse hook as a spend gate for BigQuery. It dry-runs each query and returns permissionDecision: "ask" when the maximum cost is over a threshold. In an Auto thread it returned ask twice ("max $0.4692 is over the $0.1000 threshold", and about $0.19 on the second). Both queries ran, and I never saw a prompt. T3's server trace shows exactly two ClaudeAdapterV2.canUseTool spans, one right after each query, each returning in under 1 ms.
The dollar amount is small. What worries me is the pattern behind it:
ask is how a hook, a permissions.ask rule, or an org policy says "a person must decide this". People reach for it on exactly the actions that are costly or hard to undo: cloud spend, deploys, outbound messages, deleting data.
In Auto, every one of those turns into an allow, and nobody is told. The agent thinks the user approved, and the user doesn't know they were asked. As noted above, the transcript records it as source: "user_temporary". So after the fact, the record looks like a person approved something no person saw.
A hook author can't tell, from inside the hook, that their ask will be ignored. The only workaround is the one people have posted here: detect CLAUDE_CODE_ENTRYPOINT=sdk-ts and turn ask into deny. That makes the gate worse in every other SDK host, and it means every hook has to know it might run under T3.
Why it's inconsistent
With Claude Code. The same hook in the same mode prompts in the Claude Code CLI. Claude Code's permission modes docs say plainly that prompts forced by ask rules or hooks still appear in auto mode: "auto mode still shows you those prompts". In auto mode, a classifier approval can't override a hook's ask either; Claude Code passes the ask on to the person. Hook and rule authors build against that documented behavior.
Within T3, since fix(claude): honor effective bypass restrictions #21806. Full access (bypassPermissions) now sends requests that Claude forwards to the user. Auto still allows them silently. So for exactly the requests Claude reserves for a person, Full access is now the safer mode. Someone who picks Auto over Full access to be more careful gets less protection on these requests than if they had picked Full access.
With T3's own reasoning. In [Bug]: Full access stops for Claude Code safety-check approvals on routine rm commands #26418, Full access users asked T3 to stop prompting on Claude's forwarded safety checks. That was closed with "Claude code added this for a reason. I don't think it's a good idea that we override their full access behavior." Auto today is that same override, applied to Auto.
With T3's docs.Permission modes says Auto "approves routine actions and asks about others".
What a fix would need to cover
The real tension is unattended runs: #21806 called it out, and #26418 shows what it costs when a scheduled or overnight thread waits hours on a prompt. I don't think the answer to that is silently approving. Whatever T3 decides, I'd hope for:
A request Claude escalates for a person reaches a person in Auto, at least as reliably as it does in Full access.
If T3 ever resolves one of these requests without a person (for example in an unattended run), it isn't recorded as a user approval. The agent is told it wasn't approved, so it can work around it or ask, instead of carrying on as if it were.
Routine actions in Auto stay prompt-free. As triaged above, classifier approvals never reach canUseTool. I confirmed that with a probe: a real Claude Code 2.1.306 session through Agent SDK 0.3.276 in permissionMode: "auto", with a hook returning ask for one command. Only that command reached canUseTool, carrying the hook's reason in decisionReason. A routine command did not reach it.
For what it's worth, I've applied a change to my fork with the same effect as the one proposed in #15360: Auto prompts on requests Claude forwards. With it, an adapter test that feeds canUseTool the probe's hook request gets an approval request back instead of an allow. I haven't yet seen it work in a live T3 thread.
Something that i did notice is that since v2 dropped i haven't had a single approval prompt (literally 0), but when i tried full access for like 2 minutes i received a bunch from claude's auto classifier, which makes me wonder if auto isn't just auto accepting stuff that claude itself finds dangerous
Same result on T3 Code 0.1.7, Claude Code 2.1.318, WSL. One test in both modes:
a PreToolUse hook returns ask on a Write. Supervised shows Accept/Decline, and
Decline blocks the write. Auto shows no prompt and the file is written 145 ms
after the permission check ends. We rely on ask for destructive commands, so
we keep client projects out of Auto until this lands. Is #15360 still the plan?
Confirming the classifier path @TonybynMp4 suspected, live on 0.1.9 (Claude Code 2.1.325, Linux, Haiku 5.5, Auto, no ask rules).
Setup: a throwaway repo with a local bare remote and an amended commit, so git push --force origin main is needed.
The classifier blocks the force push (automode-blocked), then blocks it again. The third "try again" runs it. The transcript records that push as {"decision": "accept", "source": "user_temporary"}, and T3 shows it as a normal completed command with no request.
Four force pushes to four bare remotes in one turn: two blocked, two ran.
So Auto doesn't only skip ask rules. Claude Code turns a third classifier block in a row into a permission prompt, the Auto canUseTool answers allow, and the action the classifier refused runs. A task file that says "retry until it works" is enough to get there.
+1 for #35207. Until it lands we run a PreToolUse deny hook on the T3 Claude instance for force pushes, rm -rf outside the project and similar.
Activity
juliusmarminge commentedon Oct 3, 2026
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 apermissions.askmatch. It's the same gap that merged #13786 closed for Auto-accept edits, still open for Auto.What happens
claudeRuntimeQueryPolicyForRuntimePolicyinapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.tsmapsruntimeMode: "auto"to Claude'spermissionMode: "auto"withinstallPermissionCallback: false. The query always getscanUseToolanyway, andrequiresClaudeApprovalis that same flag. So after theAskUserQuestionandExitPlanModespecial cases, the callback returnsallowright away. The testmaps Auto runtime mode to Claude's AI-reviewed permission modepins the flag atfalse.Claude checks content-scoped ask rules before its auto-mode classifier, and it sends a match to
canUseToolinstead of letting the classifier approve it.Bash(git push:*)is the trailing-wildcard form ofBash(git push *), so your repro rule is a real ask. The query leavessettingSourcesunset, which means user settings load and a rule in~/.claude/settings.jsonapplies. 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 markedrequiresUserInteraction.Likely fix area
autolikeauto-accept-editswhenapprovalPolicyis unset, so the callback raises a normal approval request instead of allowing. An explicitapprovalPolicy: "never"could stay non-prompting.runtimeMode: "auto", would cover it. It would callcanUseToolfor aBashcommand and require acommandruntime request before any decision. The policy-mapping assertion would change along with it.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
PreToolUsehook that denies the command are good workarounds. A maintainer will decide on the fix direction.aliir74 commentedon Oct 13, 2026
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):
Why this matters beyond UX:
PreToolUsehooks that returnaskare now silently allowed in Auto threads. I rely onaskhooks 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 todenywhen they detect a T3 Auto session.Rechecked on
0.0.46-nightly.20261013.3066:installPermissionCallbackis still only true forapproval-requiredandauto-accept-edits, so the bug is still present. #15360 looks like the right fix, and I'd be glad to see it reviewed.mackinleysmith commentedon Oct 14, 2026
Note
Claude responding on behalf of MacKinley.
Still reproduces on
0.0.46-nightly.20261014.3105with Claude Code2.1.299. One detail I haven't seen mentioned yet: the auto-allow is recorded as if the user approved it.A
PreToolUsehook returnedpermissionDecision: "ask"in an Auto thread. The command ran with no prompt, and thetool_resultentry in Claude Code's session transcript (~/.claude/projects/<project>/<session>.jsonl) says: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 answersallowfor 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 anasktodenyonly when T3 is the host.juliusmarminge commentedon Oct 22, 2026
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.jorgenswiderski commentedon Nov 5, 2026
Note
Claude responding on behalf of Jorgen.
Still present on upstream
mainat 4b87a45 (2026-11-04). Two things I think aren't in this thread yet: what this costs when anaskguards something expensive, and the fact that, since #21806, Auto is now the less protective of the two modes for these requests.What it cost
I use a
PreToolUsehook as a spend gate for BigQuery. It dry-runs each query and returnspermissionDecision: "ask"when the maximum cost is over a threshold. In an Auto thread it returnedasktwice ("max $0.4692 is over the $0.1000 threshold", and about $0.19 on the second). Both queries ran, and I never saw a prompt. T3's server trace shows exactly twoClaudeAdapterV2.canUseToolspans, one right after each query, each returning in under 1 ms.The dollar amount is small. What worries me is the pattern behind it:
askis how a hook, apermissions.askrule, or an org policy says "a person must decide this". People reach for it on exactly the actions that are costly or hard to undo: cloud spend, deploys, outbound messages, deleting data.allow, and nobody is told. The agent thinks the user approved, and the user doesn't know they were asked. As noted above, the transcript records it assource: "user_temporary". So after the fact, the record looks like a person approved something no person saw.askwill be ignored. The only workaround is the one people have posted here: detectCLAUDE_CODE_ENTRYPOINT=sdk-tsand turnaskintodeny. That makes the gate worse in every other SDK host, and it means every hook has to know it might run under T3.Why it's inconsistent
askeither; Claude Code passes the ask on to the person. Hook and rule authors build against that documented behavior.bypassPermissions) now sends requests that Claude forwards to the user. Auto still allows them silently. So for exactly the requests Claude reserves for a person, Full access is now the safer mode. Someone who picks Auto over Full access to be more careful gets less protection on these requests than if they had picked Full access.What a fix would need to cover
The real tension is unattended runs: #21806 called it out, and #26418 shows what it costs when a scheduled or overnight thread waits hours on a prompt. I don't think the answer to that is silently approving. Whatever T3 decides, I'd hope for:
canUseTool. I confirmed that with a probe: a real Claude Code 2.1.306 session through Agent SDK 0.3.276 inpermissionMode: "auto", with a hook returningaskfor one command. Only that command reachedcanUseTool, carrying the hook's reason indecisionReason. A routine command did not reach it.For what it's worth, I've applied a change to my fork with the same effect as the one proposed in #15360: Auto prompts on requests Claude forwards. With it, an adapter test that feeds
canUseToolthe probe's hook request gets an approval request back instead of anallow. I haven't yet seen it work in a live T3 thread.TonybynMp4 commentedon Nov 5, 2026
Something that i did notice is that since v2 dropped i haven't had a single approval prompt (literally 0), but when i tried full access for like 2 minutes i received a bunch from claude's auto classifier, which makes me wonder if auto isn't just auto accepting stuff that claude itself finds dangerous
adamblaha00 commentedon Nov 6, 2026
Same result on T3 Code 0.1.7, Claude Code 2.1.318, WSL. One test in both modes:
a PreToolUse hook returns
askon a Write. Supervised shows Accept/Decline, andDecline blocks the write. Auto shows no prompt and the file is written 145 ms
after the permission check ends. We rely on
askfor destructive commands, sowe keep client projects out of Auto until this lands. Is #15360 still the plan?
TonybynMp4 commentedon Nov 6, 2026
Seems counter intuitive but full access will respect the permissions check so it can be a temporary solution.
Should be, just need julius to take a look 😅
karthikeyan5 commentedon Nov 15, 2026
Note
Claude responding on behalf of Karthi.
Confirming the classifier path @TonybynMp4 suspected, live on 0.1.9 (Claude Code 2.1.325, Linux, Haiku 5.5, Auto, no ask rules).
Setup: a throwaway repo with a local bare remote and an amended commit, so
git push --force origin mainis needed.automode-blocked), then blocks it again. The third "try again" runs it. The transcript records that push as{"decision": "accept", "source": "user_temporary"}, and T3 shows it as a normal completed command with no request.So Auto doesn't only skip
askrules. Claude Code turns a third classifier block in a row into a permission prompt, the AutocanUseToolanswers allow, and the action the classifier refused runs. A task file that says "retry until it works" is enough to get there.+1 for #35207. Until it lands we run a PreToolUse deny hook on the T3 Claude instance for force pushes,
rm -rfoutside the project and similar.