Scheduled routines: tool calls wait for a permission prompt nobody can answer, and the run still reports success (follow-up to #83166)
Follow-up to #83166, which the stale bot closed on 2026-09-07 ("inactive for too long, open a new issue if this is still relevant"). It is still relevant for us, so here is the same problem with a month of extra data.
What we reported on 2026-08-07 (comment 5215676428 on #83166)
A one-shot scheduled routine fired on time and produced nothing. The transcript held five tool_use blocks with null results, the session metadata said "permissionMode":"default", and the Bash calls were waiting for an interactive approval that nobody can give in an unattended run. The session then ended without an error and the trigger reported run_once_fired. Listing the tools in allowed_tools in the routine's job_config did not act as a standing grant.
The part that hurts is not the stall but the silence: the routine says it fired, nothing is queued, nothing times out, and the only trace is a transcript full of null tool results. For a scheduled server check that means you believe the check ran.
Since then
No reply on the issue in 32 days. Our own watcher polls the thread four times a day and only ever saw the bot's closing comment.
The CLI side works, and has all along. On CLI 2.1.263, claude -p --permission-mode <mode>, allow/deny rules in settings.json and a PreToolUse hook give a headless session a workable standing policy. Scheduled routines expose no equivalent, so the one place without a human is the one place where you cannot express a non-interactive permission policy.
We moved every scheduled check that touches a tool to systemd timers on our own server. Since 2026-09-06 we also run an unattended on-call agent there: claude -p --permission-mode auto with a settings.json allow/deny list and a hook that blocks a fixed list of commands. That is exactly the standing grant a routine cannot express, and it only works because we control the machine.
What would fix it
- A
permission_modefield on a scheduled routine (job_config), with the same meaning asclaude -p --permission-mode. That alone would do it. - If a tool call blocks on a permission prompt in a session with no interactive client attached, end the run with an explicit error and show it in the routine result, instead of returning
run_once_firedfor a session that died with null tool results. - Document that
allowed_toolsinjob_configis not a standing grant. It reads like one, and that is what cost us the run.
Environment: Ubuntu Server 26.04, Claude Code CLI 2.1.263, unattended runs as a dedicated user driven by systemd timers and a queue. Original report: #83166, comment 5215676428 (2026-08-07).
Happy to provide the transcript excerpt with the null tool results if that helps.