Repository navigation
feat(core): give every tool call a deadline and make a wedged tool interruptible [K-05] - #8
Merged
Merged
Conversation
…terruptible [K-05]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every tool call in the conversation loop now runs on a polled daemon worker with a per-call deadline, so a tool that never returns can no longer block the turn forever, and
interrupt()(which only setsAgent._cancel) can actually break a wedged tool.Why
Koza executed each sequential tool inline (
self._execute_tool(name, args)atcore.py:1436pre-change) and only checkedself._cancelbetween calls. A tool that hangs — a subprocess with no timeout, a socket read that never returns — held the loop indefinitely, and/stopdid nothing until it returned. The parallel branch had the mirror-image bug:with ThreadPoolExecutor(...) as executor:joins its workers on exit, so one hung call froze the whole batch even after the cancel poll broke out of the wait loop.Measured on
mainwith a probe driving one turn whose only tool call blocks forever (scratch script, not committed):What changed
core.py:38— new module constants_SEQUENTIAL_INTERRUPT_POLL_SECONDS = 0.1,_DEFAULT_TOOL_TIMEOUT_SECONDS = 600.0,_TOOL_DEADLINE_EXEMPT_TOOLS(delegate_task,spawn_subagent,start_coding_session,start_tracked_coding_task,browser_task— they supervise their own liveness) and helpers_resolve_tool_timeout(),_tool_timeout_message(),_tool_interrupt_message().core.py:1702—Agent._run_tool_with_deadline(): runs one call on a daemon worker, polls in 0.1 s slices, returns(result, elapsed, outcome)with outcomedone | timeout | interrupted. A disabled deadline still polls — that poll is what makes a non-cooperative tool interruptible.core.py:1498— sequential branch: the inline call is replaced by the helper; aninterruptedoutcome stops the turn and marks any remaining callsProcess interrupted by user.core.py:1352— parallel branch: the executor is replaced by one daemon worker per call reporting through a queue; the collect loop honours interruption and the per-call deadline and abandons overrunning calls.config.py:98— newtool_timeout_seconds: 600(0disables the deadline).tests/test_tool_deadline.py(new, force-added —tests/is gitignored): 9 tests (unit + end-to-end throughput the loop).Provenance
Mechanism ported from
hermes:agent/tool_executor.py:834-841, 865-892, 957-971(_SEQUENTIAL_INTERRUPT_POLL_SECONDS,_poll_sequential_future,_resolve_sequential_tool_timeout,_SEQUENTIAL_DEADLINE_EXEMPT_TOOLS), re-implemented with koza names, config key and logging. Upstream exemptsdelegate_task/manage_connections; koza's equivalents are the four above plusbrowser_task.Verification
Test-power check (scratch probe, not committed — same turn,
main'score.pyvs the fix):Risk / rollback
tool_timeout_seconds(default 600 s) is now abandoned with a timeout result instead of running to completion — raise the config value, or add the tool to_TOOL_DEADLINE_EXEMPT_TOOLS.Roadmap: K-05