Skip to content

Sub-agent tools not passed to LLM API request #1467

@bug-ops

Description

@bug-ops

Description

Sub-agents with tools.allow configuration cannot use native tool_use because tool definitions are never included in the LLM API request.

Root Cause

run_agent_loop() in crates/zeph-core/src/subagent/manager.rs (~line 246-250) calls provider.chat(&messages) which returns Result<String> — a plain text completion without tool support.

let llm_result = if let Some(ref m) = model {
    provider.chat_with_named_provider(m, &messages).await
} else {
    provider.chat(&messages).await
};

The FilteredToolExecutor is constructed correctly from the agent definition's ToolPolicy, but its tool definitions are never passed to the LLM provider. The executor is only used post-response to execute detected tool calls — but native tool calls never arrive because the LLM doesn't know tools exist.

Observed Behavior

Sub-agent with tools.allow: [shell, memory_save, memory_search] generates XML-style fake tool calls instead of native tool_use:

<function_calls>
<invoke name="bash">
<parameter name="command">echo hello</parameter>
</invoke>
</function_calls>

These fake calls are never executed. The .meta.json shows turns_used: 1 confirming tools were never actually invoked.

Expected Behavior

Sub-agent should receive tool definitions in the LLM API request and produce native tool_use blocks that FilteredToolExecutor can execute.

Steps to Reproduce

  1. Create .zeph/agents/researcher.md:
---
name: researcher
description: Research agent with shell access and memory
tools:
  allow:
    - shell
    - memory_save
    - memory_search
permissions:
  max_turns: 3
  timeout_secs: 60
memory: project
---

You are a research assistant. Use shell commands to gather information and save findings to memory.
  1. Run: /agent spawn researcher Run echo hello and save the result to memory

  2. Observe: agent generates XML fake tool calls, tools never execute, memory never written

Impact

  • All sub-agent tool functionality is broken
  • memory: project scope directory is created but never populated (memory tools don't work)
  • Any sub-agent relying on tools (shell, memory, custom) is effectively tool-less

Fix Direction

run_agent_loop() needs to use a tool-aware chat method (e.g., provider.chat_with_tools()) that includes FilteredToolExecutor's tool definitions in the API request, and then handle the tool_use/tool_result loop similar to the main agent loop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingllmzeph-llm crate (Ollama, Claude)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions