autoagents_core/agent/
runnable.rs1use super::base::{AgentDeriveT, BaseAgent};
2use super::error::RunnableAgentError;
3use crate::error::Error;
4use crate::memory::MemoryProvider;
5use crate::protocol::{Event, TaskResult};
6use crate::runtime::Task;
7use crate::tool::ToolCallResult;
8use async_trait::async_trait;
9use serde_json::Value;
10use std::fmt::Debug;
11use std::sync::Arc;
12use tokio::sync::{mpsc, RwLock};
13use tokio::task::JoinHandle;
14use uuid::Uuid;
15
16#[derive(Debug, Default, Clone)]
18pub struct AgentState {
19 pub tool_calls: Vec<ToolCallResult>,
21 pub task_history: Vec<Task>,
23}
24
25impl AgentState {
26 pub fn new() -> Self {
27 Self::default()
28 }
29
30 pub fn record_tool_call(&mut self, tool_call: ToolCallResult) {
31 self.tool_calls.push(tool_call);
32 }
33
34 pub fn record_task(&mut self, task: Task) {
35 self.task_history.push(task);
36 }
37}
38
39#[async_trait]
41pub trait RunnableAgent: Send + Sync + 'static + Debug {
42 fn name(&self) -> &'static str;
43 fn description(&self) -> &'static str;
44 fn id(&self) -> Uuid;
45
46 async fn run(self: Arc<Self>, task: Task, tx_event: mpsc::Sender<Event>) -> Result<(), Error>;
47
48 fn memory(&self) -> Option<Arc<RwLock<Box<dyn MemoryProvider>>>>;
49
50 fn spawn_task(
51 self: Arc<Self>,
52 task: Task,
53 tx_event: mpsc::Sender<Event>,
54 ) -> JoinHandle<Result<(), Error>> {
55 tokio::spawn(async move { self.run(task, tx_event).await })
56 }
57}
58
59#[derive(Debug)]
61pub struct RunnableAgentImpl<T: AgentDeriveT> {
62 agent: BaseAgent<T>,
63 state: Arc<RwLock<AgentState>>,
64}
65
66impl<T: AgentDeriveT> RunnableAgentImpl<T> {
67 pub fn new(agent: BaseAgent<T>) -> Self {
68 Self {
69 agent,
70 state: Arc::new(RwLock::new(AgentState::new())),
71 }
72 }
73
74 #[allow(dead_code)]
75 pub fn state(&self) -> Arc<RwLock<AgentState>> {
76 self.state.clone()
77 }
78}
79
80#[async_trait]
81impl<T> RunnableAgent for RunnableAgentImpl<T>
82where
83 T: AgentDeriveT,
84{
85 fn name(&self) -> &'static str {
86 self.agent.name()
87 }
88
89 fn description(&self) -> &'static str {
90 self.agent.description()
91 }
92
93 fn id(&self) -> Uuid {
94 self.agent.id
95 }
96
97 fn memory(&self) -> Option<Arc<RwLock<Box<dyn MemoryProvider>>>> {
98 self.agent.memory()
99 }
100
101 async fn run(self: Arc<Self>, task: Task, tx_event: mpsc::Sender<Event>) -> Result<(), Error> {
102 match self
104 .agent
105 .inner()
106 .execute(
107 self.agent.llm(),
108 self.agent.memory(),
109 self.agent.tools(),
110 &self.agent.agent_config(),
111 task.clone(),
112 self.state.clone(),
113 tx_event.clone(),
114 )
115 .await
116 {
117 Ok(output) => {
118 let value: Value = output.into();
120
121 let _ = tx_event
123 .send(Event::TaskComplete {
124 sub_id: task.submission_id,
125 result: TaskResult::Value(value),
126 })
127 .await
128 .map_err(RunnableAgentError::event_send_error)?;
129
130 Ok(())
131 }
132 Err(e) => {
133 let error_msg = e.to_string();
135 let _ = tx_event
136 .send(Event::TaskComplete {
137 sub_id: task.submission_id,
138 result: TaskResult::Failure(error_msg.clone()),
139 })
140 .await;
141
142 Err(RunnableAgentError::ExecutorError(error_msg).into())
143 }
144 }
145 }
146}
147
148pub trait IntoRunnable<T: AgentDeriveT> {
150 fn into_runnable(self) -> Arc<dyn RunnableAgent>;
151}
152
153impl<T: AgentDeriveT> IntoRunnable<T> for BaseAgent<T> {
154 fn into_runnable(self) -> Arc<dyn RunnableAgent> {
155 Arc::new(RunnableAgentImpl::new(self))
156 }
157}