fix(channel): use native tool calling to preserve conversation context

AnthropicProvider declared supports_native_tools() = true but did not
override chat_with_tools(). The default trait implementation drops all
conversation history (sends only system + last user message), breaking
multi-turn conversations on Telegram and other channels.

Changes:
- Override chat_with_tools() in AnthropicProvider: converts OpenAI-format
  tool JSON to ToolSpec and delegates to chat() which preserves full
  message history
- Skip build_tool_instructions() XML protocol when provider supports
  native tools (saves ~12k chars in system prompt)
- Remove duplicate Tool Use Protocol section from build_system_prompt()
  for native-tool providers
- Update Your Task section to encourage conversational follow-ups
  instead of XML tool_call tags when using native tools
- Add tracing::warn for malformed tool definitions in chat_with_tools
This commit is contained in:
xj 2026-02-18 05:42:14 -08:00 committed by Chummy
parent 8c826e581c
commit 2d6205ee58
3 changed files with 264 additions and 13 deletions

View file

@ -1458,17 +1458,21 @@ pub async fn run(
} else {
None
};
let mut system_prompt = crate::channels::build_system_prompt(
let native_tools = provider.supports_native_tools();
let mut system_prompt = crate::channels::build_system_prompt_with_mode(
&config.workspace_dir,
model_name,
&tool_descs,
&skills,
Some(&config.identity),
bootstrap_max_chars,
native_tools,
);
// Append structured tool-use instructions with schemas
system_prompt.push_str(&build_tool_instructions(&tools_registry));
// Append structured tool-use instructions with schemas (only for non-native providers)
if !native_tools {
system_prompt.push_str(&build_tool_instructions(&tools_registry));
}
// ── Approval manager (supervised mode) ───────────────────────
let approval_manager = ApprovalManager::from_config(&config.autonomy);
@ -1823,15 +1827,19 @@ pub async fn process_message(config: Config, message: &str) -> Result<String> {
} else {
None
};
let mut system_prompt = crate::channels::build_system_prompt(
let native_tools = provider.supports_native_tools();
let mut system_prompt = crate::channels::build_system_prompt_with_mode(
&config.workspace_dir,
&model_name,
&tool_descs,
&skills,
Some(&config.identity),
bootstrap_max_chars,
native_tools,
);
system_prompt.push_str(&build_tool_instructions(&tools_registry));
if !native_tools {
system_prompt.push_str(&build_tool_instructions(&tools_registry));
}
let mem_context = build_context(mem.as_ref(), message, config.memory.min_relevance_score).await;
let rag_limit = if config.agent.compact_context { 2 } else { 5 };