Skip to content

fix: make concurrent tool batching path-aware for file mutations#1914

Merged
teknium1 merged 2 commits intomainfrom
hermes/hermes-562a3784
Mar 18, 2026
Merged

fix: make concurrent tool batching path-aware for file mutations#1914
teknium1 merged 2 commits intomainfrom
hermes/hermes-562a3784

Conversation

@teknium1
Copy link
Copy Markdown
Contributor

Salvage of PR #1873 by @kshitijk4poor (cherry-picked with authorship preserved, 2 commits). Fixes #1872.

Summary

The tool batching gate was too coarse — any multi-call batch without clarify went concurrent, which meant overlapping file mutations like write_file("src/a.py") + patch("src/a.py") could race each other with nondeterministic results.

This makes the parallelization decision path-aware:

  • Read-only tools (web_search, read_file, search_files, etc.) → always safe to parallelize
  • File-scoped tools (read_file, write_file, patch) → parallel only when targeting different paths
  • Stateful/unknown tools (terminal, etc.) → forced sequential
  • Any ambiguity (malformed args, non-dict args) → falls back to sequential

Disjoint file operations keep their latency benefit while overlapping mutations stay ordered.

Changes

  • run_agent.py: New _should_parallelize_tool_batch() function with _PARALLEL_SAFE_TOOLS, _PATH_SCOPED_TOOLS allowlists, path overlap detection
  • tests/test_run_agent.py: 8 new test methods covering overlapping/disjoint writes, terminal batches, malformed args, plus unit tests for _paths_overlap

Test plan

  • pytest tests/test_run_agent.py -n0 -q — 190 passed
  • Full suite — 5373 passed (7 pre-existing failures)
- Log malformed/non-dict tool arguments at debug level before
  falling back to sequential, instead of silently swallowing
  the error into an empty dict
- Guard empty paths in _paths_overlap (unreachable in practice
  due to upstream filtering, but makes the invariant explicit)
- Add tests: malformed JSON args, non-dict args, _paths_overlap
  unit tests including empty path edge cases
- web_crawl is not a registered tool (only web_search/web_extract
  are); no addition needed to _PARALLEL_SAFE_TOOLS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants