Problem description
Provenance & confidence (please read first)
Produced with an AI-assisted investigation. Partly reproduced: the production error text and the
zero-side-effect outcome are quoted from our journal and confirmed locally; but note the local direct call
raises unexpected keyword argument 'message_title' rather than the production missing 1 required positional argument: 'title', because ToolkitMessageIntegration pops the injected keys before invoking
the function (message_integration.py:101). Both are argument-binding failures that happen before the
function body runs — that equivalence is code reading, please confirm it in your dispatch path.
The claim that the Run is failed with outcome_unknown is taken directly from our tool_calls row and
runs.terminal_detail, not inferred.
FileToolkit.write_to_file is re-wrapped in Eigent with a positional, defaultless title:
backend/app/agent/toolkit/file_write_toolkit.py:141
lambda _, title, content, filename, encoding=None, use_latex=False: (At the same time, ToolkitMessageIntegration injects message_title / message_description into the
same advertised parameter list, documented as an optional status-message title
(camel/toolkits/message_integration.py:157, :535).
The two names are near-synonyms, one required and one optional. A model that fills the injected cosmetic field and omits the real one produces:
Error: FileToolkit.<lambda>() missing 1 required positional argument: 'title'Observed request (our journal, tool_calls.request_json, abridged):
{"content": "…", "filename": "write-test/probe.csv", "encoding": "utf-8",
"message_title": "Fixing CSV format", "message_description": "…", "use_latex": false}
# no "title"Two consequences worth separating:
- The failure itself is a plain argument-binding error: no tool code executed, no file was created
(verified: target path absent,
git statusempty). - The classification is wrong in proportion. Because the exception surfaces after dispatch has begun
and the tool is
unsafe_write,run_runtime/tool_checkpoint.py:940-951recordsstatus = "outcome_unknown"andexternal_effect_may_have_occurred = true, which fails the entire Run (terminal_detail = "execution_backend_failure: tool 'write_to_file' may have produced an external side effect") — 0.8 s after dispatch, withtimeout_reason = NULL.
So the cheapest, provably side-effect-free error is punished with the heaviest outcome, while a genuine
write failure (e.g. RepositoryStateChangedError) only costs one call.
Steps to reproduce
- Git-enabled Space, single-agent.
- Ask the agent to write a file, and have the call omit
title(or send onlymessage_title). - Observe: the tool raises a Python binding error; the tool call is journalled
outcome_unknown; the Run is markedfailedwith an "external side effect" reason; no file exists.
Additional context
Suggested fixes, any one of which removes the trap:
- Give
titlea default in the wrapper and fall back to the injectedmessage_title(or better, remove the near-synonym collision: rename the injected field, or suppress it for tools that already have a requiredtitle). - Classify argument-binding failures distinctly from post-effect ambiguity. Python raises
TypeError: … missing 1 required positional argument/unexpected keyword argumentbefore the function body runs, so absence of external effect is provable. A fail-closed boundary is right, but it should not treat "proven not to have happened" the same as "cannot prove whether it happened". - Related family we hit the same day (same root shape — model-produced argument structure vs a schema
that permits near-synonyms):
shell_view(id='t6', block='false')whereblockbelongs toshell_exec; a call to a non-existent tool namewrite_file; andfile_pathsarriving as a stringified JSON array, whichmarkitdownthen treats as one literal path (File not found: <HOME>/workbench/["write-test/probe.txt", …). A stricter server-side argument validation step — rejecting unknown/missing required keys with a clean, retryable tool error rather than an ambiguous one — would turn all four of these into ordinary recoverable failures.
Activity
0No activity yet.