minimal_agent/
minimal_agent.rs1use a2a_agents::core::{AgentBuilder, BuildError};
7use a2a_rs::{
8 InMemoryTaskStorage,
9 domain::{A2AError, Message, Part, Role, Task, TaskState},
10 port::AsyncMessageHandler,
11};
12use async_trait::async_trait;
13use uuid::Uuid;
14
15#[derive(Clone)]
17struct EchoHandler;
18
19#[async_trait]
20impl AsyncMessageHandler for EchoHandler {
21 async fn process_message(
22 &self,
23 task_id: &str,
24 message: &Message,
25 _session_id: Option<&str>,
26 ) -> Result<Task, A2AError> {
27 let text = message
29 .parts
30 .iter()
31 .find_map(|part| match part {
32 Part::Text { text, .. } => Some(text.clone()),
33 _ => None,
34 })
35 .unwrap_or_else(|| "No text provided".to_string());
36
37 let response = Message::builder()
39 .role(Role::Agent)
40 .parts(vec![Part::text(format!("Echo: {}", text))])
41 .message_id(Uuid::new_v4().to_string())
42 .context_id(message.context_id.clone().unwrap_or_default())
43 .build();
44
45 Ok(Task::builder()
47 .id(task_id.to_string())
48 .context_id(message.context_id.clone().unwrap_or_default())
49 .status(a2a_rs::domain::TaskStatus {
50 state: TaskState::Completed,
51 message: Some(response.clone()),
52 timestamp: Some(chrono::Utc::now()),
53 })
54 .history(vec![message.clone(), response])
55 .build())
56 }
57
58 async fn validate_message(&self, message: &Message) -> Result<(), A2AError> {
59 if message.parts.is_empty() {
60 return Err(A2AError::ValidationError {
61 field: "parts".to_string(),
62 message: "Message must contain at least one part".to_string(),
63 });
64 }
65 Ok(())
66 }
67}
68
69#[tokio::main]
70async fn main() -> Result<(), BuildError> {
71 tracing_subscriber::fmt()
73 .with_env_filter(
74 tracing_subscriber::EnvFilter::from_default_env()
75 .add_directive(tracing::Level::INFO.into()),
76 )
77 .init();
78
79 println!("🚀 Starting Echo Agent with declarative configuration");
80 println!();
81
82 AgentBuilder::from_file("examples/minimal_agent.toml")?
85 .with_handler(EchoHandler)
86 .with_storage(InMemoryTaskStorage::new())
87 .build()?
88 .run()
89 .await
90 .map_err(|e| BuildError::RuntimeError(e.to_string()))?;
91
92 Ok(())
93}