Skip to content

fix(subagent): only block fenced-block calls with matching tool tags#1464

Merged
bug-ops merged 2 commits intomainfrom
subagent-fenced-block-filter
Mar 9, 2026
Merged

fix(subagent): only block fenced-block calls with matching tool tags#1464
bug-ops merged 2 commits intomainfrom
subagent-fenced-block-filter

Conversation

@bug-ops
Copy link
Owner

@bug-ops bug-ops commented Mar 9, 2026

Summary

  • FilteredToolExecutor::execute_erased() was unconditionally returning Err(ToolError::Blocked) for every LLM response, regardless of whether it contained an actual tool invocation
  • Each false-positive block counted as a turn, exhausting max_turns without producing a response
  • Fixed by collecting registered fenced-block language tags at construction time and checking for actual matching blocks before blocking

Changes

  • crates/zeph-core/src/subagent/filter.rs: added fenced_tags field (cached at construction), has_fenced_tool_invocation() helper, updated execute_erased() and execute_confirmed_erased() to return Ok(None) for non-tool responses
  • CHANGELOG.md: updated [Unreleased] section
  • 8 new unit tests covering: matching tag blocked, non-matching fence passes, plain text passes, unclosed fence passes, multiple fences with one match

Test plan

  • cargo nextest run --config-file .github/nextest.toml --workspace --features full --lib --bins — 4892 tests pass
  • cargo +nightly fmt --check — clean
  • cargo clippy --workspace --features full -- -D warnings — clean
  • Verify sub-agent spawned with /agent spawn answers questions instead of exhausting turns on false-positive blocks

Fixes #1432

FilteredToolExecutor::execute_erased() was unconditionally returning
Err(ToolError::Blocked) for every LLM response, including plain text
replies with no tool invocations. This caused sub-agents to exhaust
their max_turns limit on false-positive blocks without ever producing
a response (issue #1432).

Fix: collect registered fenced-block language tags at construction time
and check whether the response actually contains a fenced block matching
one of those tags before blocking. Plain text and non-tool code fences
now return Ok(None), allowing the agent loop to break cleanly.
@github-actions github-actions bot added documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate bug Something isn't working size/L Large PR (201-500 lines) labels Mar 9, 2026
@bug-ops bug-ops enabled auto-merge (squash) March 9, 2026 16:49
@bug-ops bug-ops merged commit 83b4ecc into main Mar 9, 2026
18 checks passed
@bug-ops bug-ops deleted the subagent-fenced-block-filter branch March 9, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working core zeph-core crate documentation Improvements or additions to documentation rust Rust code changes size/L Large PR (201-500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sub-agent fenced-block filter consumes all turns without producing a response

1 participant