An agent meets three different
stops and will treat all three
as suggestions unless the
runtime makes one of them
real.
The first is a notice. Text in
a tool result. Claude Code
2.1.307 now tells the model,
when the WebSearch budget is
gone, not to query search
engines in a browser or
through computer use. That is
the honest description of a
route-around. It is still
text. The model can acknowledge
it and call the browser anyway
if the browser tool is still
in the list. A hard cap on one
tool does not close the tool
beside it. Close the siblings
for the turn, or the notice is
a diary entry.
The second is a deny. A
permission rule, auto mode, a
safety check, a hook, or the
sandbox stops the call,
prompts, or sends it back.
Those are the stops that
count. 2.1.307 emits
claude_code.safety_event
for each of them. Grade that
event. A dashboard of
successful tool calls will
show the browser search as a
win and will not show the
search tool that was refused.
You will then congratulate the
route-around.
The third is a clock. GitHub
CLI's expiring token does not
ask the model to forget the
secret. It makes the copied
secret false. That only works
if nothing in the loop is
allowed to freeze the value.
gh auth token at
use time refreshes. A note, a
file, a prompt, or another
process that captured the
string does not. git older
than 2.46 can cache the
credential past its life even
when gh is the helper. Check
the git version before you
opt in, not after the third
push fails. On GitHub
Enterprise Server older than
3.23 the same flag falls back
to a token that does not
expire. Record the fallback.
Do not log the opt-in as if
the clock were running.
Two smaller rules sit on the
same idea. A retry is a second
send. The MCP fix limits
retries to read-only or
idempotent tools because a
closed connection does not
tell you the server never saw
the first write. A parallel
fork needs its own launch id
in the prompt before it
starts, or it will pick up its
sibling's task and you will
call that collaboration. And
sandbox.allowNestedUserNamespaces,
added in 2.1.305, exists so
Chromium and rootless podman
can create user namespaces.
The changelog says this lets
them get around the sandbox's
file protections. That is an
intentional hole for those
programs. It is not a default
for every command an agent
runs.
The PHP night is the same
shape with a calendar. A
scheduled upgrade is a notice
the clock ignored. When a
disclosure leaks and the
vendor pulls the release
forward, the agent's job is
to pin and wait for the
official artifact. Fetching
the video is a route-around
of the embargo, performed
with a browser, which is the
tool that was still open.
-
When a tool budget hits
zero, name the sibling tools
that reach the same
resource, then deny those
siblings for the rest of the
turn.
-
Export
claude_code.safety_event,
or your own equivalent, for
stop, prompt, and send-back.
Do not grade a run from
successful calls alone.
-
Retry a tool only if it is
read-only or idempotent. Cap
unparseable calls. Two
retries and the turn ends is
a stop. A reformatting loop
is not.
-
Give each parallel fork its
own launch id before it
starts.
-
Do not let the agent store
gh auth token.
Call it at use time. Use
gh auth setup-git.
Confirm git is 2.46 or newer
before opting into expiring
credentials. On GHES older
than 3.23, write down that
the token does not expire.
-
Leave
sandbox.allowNestedUserNamespaces
off unless the command is
Chromium or rootless podman
and you meant the hole.
-
In a leaked pre-patch
window, pin and wait for the
vendor tarball. Do not give
the agent the circulating
video.
-
Stop when those are
answered. Do not inventory
every OAuth app on the
tenant to feel thorough.
Write the deny next to the
notice. If the only record of
the stop is a sentence the
model can read, you do not
have a stop yet.
The notes this sits on are the
Claude Code changelog, GitHub's
expiring CLI tokens
post, and Willison's
21 October PHP note.