Skip to main content

systemprompt_agent/services/a2a_server/processing/strategies/
tool_executor.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use serde_json::Value;
4use systemprompt_identifiers::AiToolCallId;
5use systemprompt_models::{McpTool, RequestContext, ToolCall};
6
7use super::plan_executor::ToolExecutorTrait;
8use super::ExecutionContext;
9
10#[derive(Debug)]
11pub struct ContextToolExecutor {
12    pub context: ExecutionContext,
13}
14
15#[async_trait]
16impl ToolExecutorTrait for ContextToolExecutor {
17    async fn execute_tool(
18        &self,
19        tool_name: &str,
20        arguments: Value,
21        tools: &[McpTool],
22        ctx: &RequestContext,
23    ) -> Result<Value> {
24        let tool_call = ToolCall {
25            ai_tool_call_id: AiToolCallId::new(format!("call_{}", tool_name)),
26            name: tool_name.to_string(),
27            arguments,
28        };
29
30        let (_, results) = self
31            .context
32            .ai_service
33            .execute_tools(
34                vec![tool_call],
35                tools,
36                ctx,
37                Some(&self.context.agent_runtime.tool_model_overrides),
38            )
39            .await;
40
41        let result = results
42            .into_iter()
43            .next()
44            .ok_or_else(|| anyhow::anyhow!("Tool {} returned no result", tool_name))?;
45
46        if result.is_error.unwrap_or(false) {
47            let error_msg = result
48                .content
49                .into_iter()
50                .next()
51                .and_then(|c| {
52                    if let rmcp::model::RawContent::Text(text_content) = c.raw {
53                        Some(text_content.text)
54                    } else {
55                        None
56                    }
57                })
58                .unwrap_or_else(|| "Unknown error".to_string());
59            return Err(anyhow::anyhow!("Tool {} failed: {}", tool_name, error_msg));
60        }
61
62        result
63            .structured_content
64            .ok_or_else(|| anyhow::anyhow!("Tool {} returned no structured_content", tool_name))
65    }
66}