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
- 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.
-
Run: /agent spawn researcher Run echo hello and save the result to memory
-
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.
Description
Sub-agents with
tools.allowconfiguration cannot use native tool_use because tool definitions are never included in the LLM API request.Root Cause
run_agent_loop()incrates/zeph-core/src/subagent/manager.rs(~line 246-250) callsprovider.chat(&messages)which returnsResult<String>— a plain text completion without tool support.The
FilteredToolExecutoris constructed correctly from the agent definition'sToolPolicy, 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 nativetool_use:These fake calls are never executed. The
.meta.jsonshowsturns_used: 1confirming tools were never actually invoked.Expected Behavior
Sub-agent should receive tool definitions in the LLM API request and produce native
tool_useblocks thatFilteredToolExecutorcan execute.Steps to Reproduce
.zeph/agents/researcher.md:Run:
/agent spawn researcher Run echo hello and save the result to memoryObserve: agent generates XML fake tool calls, tools never execute, memory never written
Impact
memory: projectscope directory is created but never populated (memory tools don't work)Fix Direction
run_agent_loop()needs to use a tool-aware chat method (e.g.,provider.chat_with_tools()) that includesFilteredToolExecutor's tool definitions in the API request, and then handle the tool_use/tool_result loop similar to the main agent loop.