Skip to main content

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

1use crate::services::shared::{AgentServiceError, Result};
2use async_trait::async_trait;
3use serde_json::Value;
4use systemprompt_identifiers::AiToolCallId;
5use systemprompt_models::{McpTool, RequestContext, ToolCall};
6
7use super::ExecutionContext;
8use super::plan_executor::ToolExecutorTrait;
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_owned(),
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.into_iter().next().ok_or_else(|| {
42            AgentServiceError::Internal(format!("Tool {} returned no result", tool_name))
43        })?;
44
45        if result.is_error.unwrap_or(false) {
46            let error_msg = result
47                .content
48                .into_iter()
49                .next()
50                .and_then(|c| {
51                    if let rmcp::model::RawContent::Text(text_content) = c.raw {
52                        Some(text_content.text)
53                    } else {
54                        None
55                    }
56                })
57                .unwrap_or_else(|| "Unknown error".to_owned());
58            return Err(AgentServiceError::Internal(format!(
59                "Tool {tool_name} failed: {error_msg}"
60            )));
61        }
62
63        result.structured_content.ok_or_else(|| {
64            AgentServiceError::Internal(format!("Tool {tool_name} returned no structured_content"))
65        })
66    }
67}