Models sometimes request very large wait timeouts (hours or more).
The raw value went straight into the inner asyncio.wait_for, so the
SDK's tool-call ceiling fired first and aborted the call instead of
returning the clean timeout payload that tells the agent to keep
working or finish. Clamp the requested value into [1s, 300s], wait on
the clamped value, and echo it back.
* add a generic MCP client and a config for connecting MCP servers
* Add MCP docs and CLI polish: docs page, startup connect summary, --mcp-config flag, compact tool output
* Add MCP connection notes and per-run selection; clean up on cancel and dedupe names
* Show errored MCP tool calls as failed in the TUI
* Sanitize namespaced tool names so model APIs accept them
* Show MCP tool calls distinctly in the terminal and the run viewer
* Say what MCP servers are worth connecting for
* Correct the notes docstring to match how notes reach the agent
* keep the mcp tests from reading your shell's STRIX_MCP_* vars
* add extra-files plumbing so orchestrators can drop single files into the sandbox workspace
* reject extra-file paths that collide with a local source tree
* add --workspace-file so CLI users can place files in the sandbox workspace
* reject repeated and control-character workspace paths
* revalidate persisted workspace files when resuming a run
* drop the workspace-file size limit
* let an agent wait on what it already said
An agent that answers in plain text is nudged to call a tool, and the only tool
that hands control back takes a required message. So it says the same thing
twice: once as text the user has already read, once as the argument it had to
supply to stop. Seen on a run whose whole instruction was "hi" - a greeting, then
the same greeting again through respond_to_user.
message is optional now. The nudge arms the tool with the text that was
delivered and says not to repeat it, so an agent that has said its piece can park
on it with an empty call. Anything it does want to add it passes normally.
Parking still cannot leave the user on silence: an empty call is refused unless
something was actually said, and the arming is single use - execution clears it
as soon as a turn ends any other way.
The interactive prompt now also says to answer and stop in one respond_to_user
call, which is what avoids the nudge in the first place.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* drop the worked example from the interactive prompt
"the user greeted you, asked something you can answer outright, or you need a
decision" was the run I had been reading, written into a rule that holds
whatever the reason. The rule is that replying and stopping is one call; listing
occasions only invites the model to check whether this is one of them.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* drop the arming flag; an empty message just waits
Passing the delivered text from execution into the tool, and refusing an empty
call without it, was machinery guarding against an agent parking having said
nothing. That leaves the user looking at "waiting for your reply" with a cursor
in front of them - they type. It does not need a mechanism.
What is left is the default on message, and the nudge saying the text already
landed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* only offer waiting on words that were written
The nudge told every agent its text had already been delivered, but it fires
whenever a turn leaves the agent running, and a turn can end with no tool call
and no text at all - _final_output_preview has carried <none> and <empty>
branches all along. An agent that said nothing was being invited to wait on an
answer the user never received, leaving them at a bare prompt.
It now reads the turn: waiting on what was said is offered only when something
was, and otherwise the agent is told plainly that the user has read nothing and
to send its message.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* leave the continuation nudge alone
Rewording it meant asserting from the outside whether the agent had spoken, and
the nudge fires whenever a turn leaves the agent running - text or no text. The
agent knows which it did without being told, so the guidance belongs in its
prompt, where the condition is its own to read.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* say it in the nudge, where the agent is reading
An agent stranded by the nudge reasons off the nudge. Told only to call
respond_to_user, it supplies a message, and since it has just answered in plain
text that message is the same answer again. The system prompt saying otherwise
sits thousands of tokens earlier and loses.
The clause goes on the line the agent acts on: call respond_to_user, with no
message if it has already said it. That reads true whatever the turn did,
including one that produced no text, because the agent is the one who knows
which — nothing here has to work it out from the outside.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* make the working-directory prompt answer the mouse
Its Confirm and Cancel were drawn as buttons and did nothing when clicked: the
modal mouse handler had a case for every dialog except this one, so a click fell
through and the scan sat waiting on an answer the user believed they had given.
Only the keyboard could answer it.
The prompt is docked in a corner rather than centered, so it also needs its own
bounds; the centered ones every other dialog uses would have put the buttons in
the wrong place. Those bounds now come from the same placement cornerOverlay
draws with.
Two returns that hand back the model alongside a call that mutates it are now
sequenced explicitly. They work, but only because the compiler happens to
evaluate the call first, and one of them is what puts the prompt back in the
composer when the mount is declined.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* skip the mount instead of abandoning the scan
Declining the working-directory prompt threw the whole launch away and dropped
back to the start screen, which is a lot to lose for answering one question
about one directory. The two answers are now about the directory alone: mount it,
or run without it. The prompt is the whole of the input either way.
The buttons say which is which - Mount and Skip rather than Confirm and Cancel -
and the prompt says what skipping costs.
A run with neither target nor directory is a real run, so two things follow it.
It can be resumed: its instruction is what drives it, and that is in the run
record. And it tells the agent plainly that it has neither, because an agent
given no scope goes looking for the one it assumes it was meant to have.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(agents): collapse repeated waits queued inside one model turn
* fix(agents): state that one wait is enough in every prompt variant
---------
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>