Skip to content

fix(subagent): pass tool definitions to LLM API in sub-agent loop#1492

Merged
bug-ops merged 2 commits intomainfrom
subagent-tools-llm
Mar 9, 2026
Merged

fix(subagent): pass tool definitions to LLM API in sub-agent loop#1492
bug-ops merged 2 commits intomainfrom
subagent-tools-llm

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

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

Summary

  • Sub-agents with tools.allow config were calling provider.chat() (plain string, no tools), causing the LLM to generate XML-style fake tool calls instead of native tool_use blocks
  • Rewrote run_agent_loop in subagent/manager.rs to use chat_with_tools with FilteredToolExecutor definitions
  • Added handle_tool_step for ChatResponse::ToolUse/Text branching with proper multi-part message construction
  • Added chat_with_named_provider_and_tools / chat_for_named_with_tools for named provider routing
  • Exposed tool_execution module and tool_def_to_definition as pub(crate) for reuse
  • 2 regression tests added: tools passed to provider, native tool call executed

Test plan

  • cargo nextest run --config-file .github/nextest.toml --workspace --features full --lib --bins — 4933 passed
  • cargo clippy --workspace --features full -- -D warnings — clean
  • cargo +nightly fmt --check — clean
  • Regression: run_agent_loop_passes_tools_to_provider verifies chat_with_tools is called
  • Regression: run_agent_loop_executes_native_tool_call verifies execute_tool_call_erased invoked

Closes #1467

Sub-agents with `tools.allow` configuration were calling `provider.chat()`
which returns a plain string with no tool support. The `FilteredToolExecutor`
was constructed correctly but its definitions never reached the LLM, causing
it to generate XML-style fake tool calls instead of native tool_use blocks.

- Rewrite `run_agent_loop` in `subagent/manager.rs` to use `chat_with_tools`
  with tool definitions collected from `FilteredToolExecutor`
- Add `handle_tool_step` to handle `ChatResponse::ToolUse` / `Text` branching
  and execute tool calls via `execute_tool_call_erased`, building proper
  ToolUse/ToolResult message parts for the next turn
- Add `chat_with_named_provider_and_tools` to `AnyProvider` and
  `chat_for_named_with_tools` to `Orchestrator` for named provider routing
- Expose `tool_execution` module and `tool_def_to_definition` as `pub(crate)`
  so subagent module can reuse the conversion helper
- Add 2 regression tests: tools passed to provider, native tool call executed

Fixes #1467
@github-actions github-actions Bot added bug Something isn't working size/L Large PR (201-500 lines) llm zeph-llm crate (Ollama, Claude) rust Rust code changes core zeph-core crate and removed 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 21:19
@github-actions github-actions Bot added bug Something isn't working size/L Large PR (201-500 lines) labels Mar 9, 2026
@bug-ops bug-ops merged commit f1d5f06 into main Mar 9, 2026
18 checks passed
@bug-ops bug-ops deleted the subagent-tools-llm branch March 9, 2026 21:32
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 llm zeph-llm crate (Ollama, Claude) 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 tools not passed to LLM API request

1 participant