systemprompt-agent 0.2.1

Agent-to-Agent (A2A) protocol for systemprompt.io AI governance: streaming, JSON-RPC models, task lifecycle, .well-known discovery, and governed agent orchestration.
Documentation
use std::sync::Arc;

use anyhow::Result;
use async_trait::async_trait;
use systemprompt_identifiers::TaskId;
use systemprompt_models::AiMessage;

use super::{ExecutionContext, ExecutionResult, ExecutionStrategy};
use crate::services::ExecutionTrackingService;
use crate::services::a2a_server::processing::ai_executor::process_without_tools;
use crate::services::a2a_server::processing::message::StreamEvent;

#[derive(Debug, Clone, Copy)]
pub struct StandardExecutionStrategy;

impl StandardExecutionStrategy {
    pub const fn new() -> Self {
        Self
    }
}

impl Default for StandardExecutionStrategy {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl ExecutionStrategy for StandardExecutionStrategy {
    async fn execute(
        &self,
        context: ExecutionContext,
        messages: Vec<AiMessage>,
    ) -> Result<ExecutionResult> {
        tracing::info!("Processing without tools");

        let tracking = ExecutionTrackingService::new(Arc::clone(&context.execution_step_repo));
        let task_id = TaskId::new(context.task_id.as_str());

        if let Ok(step) = tracking.track_understanding(task_id.clone()).await {
            if context
                .tx
                .send(StreamEvent::ExecutionStepUpdate { step })
                .is_err()
            {
                tracing::debug!("Stream receiver dropped during execution");
            }
        }

        let (accumulated_text, tool_calls, tool_results) = process_without_tools(
            Arc::clone(&context.ai_service),
            &context.agent_runtime,
            messages,
            context.tx.clone(),
            context.request_ctx.clone(),
        )
        .await
        .map_err(|()| {
            anyhow::anyhow!("Standard execution failed - see stream errors for details")
        })?;

        if let Ok(step) = tracking.track_completion(task_id).await {
            if context
                .tx
                .send(StreamEvent::ExecutionStepUpdate { step })
                .is_err()
            {
                tracing::debug!("Stream receiver dropped during completion");
            }
        }

        Ok(ExecutionResult {
            accumulated_text,
            tool_calls,
            tool_results,
            tools: vec![],
            iterations: 1,
        })
    }

    fn name(&self) -> &'static str {
        "standard"
    }
}