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