autoagents_core/
protocol.rs

1use crate::agent::task::Task;
2use crate::tool::ToolCallResult;
3use autoagents_llm::chat::StreamChoice;
4use serde::{Deserialize, Serialize};
5use std::any::{Any, TypeId};
6use std::fmt::Debug;
7use std::sync::Arc;
8use uuid::Uuid;
9
10/// Submission IDs are used to track actor tasks
11pub type SubmissionId = Uuid;
12
13/// Agent IDs are used to identify actors
14pub type ActorID = Uuid;
15
16/// Session IDs are used to identify sessions
17pub type RuntimeID = Uuid;
18
19/// Event IDs are used to correlate events with their responses
20pub type EventId = Uuid;
21
22/// Protocol events represent the various events that can occur during actor execution
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub enum Event {
25    // /// A new task has been submitted to an agent
26    NewTask {
27        actor_id: ActorID,
28        task: Task,
29    },
30
31    /// A task has started execution
32    TaskStarted {
33        sub_id: SubmissionId,
34        actor_id: ActorID,
35        actor_name: String,
36        task_description: String,
37    },
38
39    /// A task has been completed
40    TaskComplete {
41        sub_id: SubmissionId,
42        actor_id: ActorID,
43        actor_name: String,
44        result: String,
45    },
46
47    /// A task encountered an error
48    TaskError {
49        sub_id: SubmissionId,
50        actor_id: ActorID,
51        error: String,
52    },
53
54    #[serde(skip)]
55    PublishMessage {
56        topic_name: String,
57        topic_type: TypeId,
58        message: Arc<dyn Any + Send + Sync>,
59    },
60
61    SendMessage {
62        message: String,
63        actor_id: ActorID,
64    },
65
66    /// Tool call requested (with ID)
67    ToolCallRequested {
68        id: String,
69        tool_name: String,
70        arguments: String,
71    },
72
73    /// Tool call completed (with ID and result)
74    ToolCallCompleted {
75        id: String,
76        tool_name: String,
77        result: serde_json::Value,
78    },
79
80    /// Tool call has failed
81    ToolCallFailed {
82        id: String,
83        tool_name: String,
84        error: String,
85    },
86
87    /// A turn has started
88    TurnStarted {
89        turn_number: usize,
90        max_turns: usize,
91    },
92
93    /// A turn has completed
94    TurnCompleted {
95        turn_number: usize,
96        final_turn: bool,
97    },
98
99    /// Streaming chunk from agent
100    StreamChunk {
101        sub_id: SubmissionId,
102        chunk: StreamChoice,
103    },
104
105    /// Streaming tool call chunk
106    StreamToolCall {
107        sub_id: SubmissionId,
108        tool_call: serde_json::Value,
109    },
110
111    /// Streaming completed
112    StreamComplete {
113        sub_id: SubmissionId,
114    },
115}
116
117/// Internal events that are processed within the runtime
118#[derive(Debug)]
119pub enum InternalEvent {
120    /// Process a protocol event
121    ProtocolEvent(Event),
122    /// Shutdown signal
123    Shutdown,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub enum StreamingTurnResult {
128    Complete(String),
129    ToolCallsProcessed(Vec<ToolCallResult>),
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135    use serde_json::json;
136
137    #[test]
138    fn test_event_serialization_new_task() {
139        let _ = Uuid::new_v4();
140        let event = Event::NewTask {
141            actor_id: Default::default(),
142            task: Task::new(String::from("test")),
143        };
144
145        //Check if serialization and deserilization works properly
146        let serialized = serde_json::to_string(&event).unwrap();
147        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
148
149        match deserialized {
150            Event::NewTask { task, .. } => {
151                assert_eq!(task.prompt, "test");
152            }
153            _ => panic!("Expected NewTask variant"),
154        }
155    }
156
157    #[test]
158    fn test_event_serialization_task_started() {
159        let event = Event::TaskStarted {
160            sub_id: Uuid::new_v4(),
161            actor_id: Default::default(),
162            actor_name: String::from("test"),
163            task_description: "Started task".to_string(),
164        };
165
166        let serialized = serde_json::to_string(&event).unwrap();
167        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
168
169        match deserialized {
170            Event::TaskStarted {
171                task_description, ..
172            } => {
173                assert_eq!(task_description, "Started task");
174            }
175            _ => panic!("Expected TaskStarted variant"),
176        }
177    }
178
179    #[test]
180    fn test_event_serialization_tool_calls() {
181        let tool_call_requested = Event::ToolCallRequested {
182            id: "call_123".to_string(),
183            tool_name: "test_tool".to_string(),
184            arguments: "{\"param\": \"value\"}".to_string(),
185        };
186
187        let serialized = serde_json::to_string(&tool_call_requested).unwrap();
188        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
189
190        match deserialized {
191            Event::ToolCallRequested {
192                id,
193                tool_name,
194                arguments,
195            } => {
196                assert_eq!(id, "call_123");
197                assert_eq!(tool_name, "test_tool");
198                assert_eq!(arguments, "{\"param\": \"value\"}");
199            }
200            _ => panic!("Expected ToolCallRequested variant"),
201        }
202    }
203
204    #[test]
205    fn test_event_serialization_tool_call_completed() {
206        let result = json!({"output": "tool result"});
207        let event = Event::ToolCallCompleted {
208            id: "call_456".to_string(),
209            tool_name: "completed_tool".to_string(),
210            result: result.clone(),
211        };
212
213        let serialized = serde_json::to_string(&event).unwrap();
214        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
215
216        match deserialized {
217            Event::ToolCallCompleted {
218                id,
219                tool_name,
220                result: res,
221            } => {
222                assert_eq!(id, "call_456");
223                assert_eq!(tool_name, "completed_tool");
224                assert_eq!(res, result);
225            }
226            _ => panic!("Expected ToolCallCompleted variant"),
227        }
228    }
229
230    #[test]
231    fn test_event_serialization_tool_call_failed() {
232        let event = Event::ToolCallFailed {
233            id: "call_789".to_string(),
234            tool_name: "failed_tool".to_string(),
235            error: "Tool execution failed".to_string(),
236        };
237
238        let serialized = serde_json::to_string(&event).unwrap();
239        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
240
241        match deserialized {
242            Event::ToolCallFailed {
243                id,
244                tool_name,
245                error,
246            } => {
247                assert_eq!(id, "call_789");
248                assert_eq!(tool_name, "failed_tool");
249                assert_eq!(error, "Tool execution failed");
250            }
251            _ => panic!("Expected ToolCallFailed variant"),
252        }
253    }
254
255    #[test]
256    fn test_event_serialization_turn_events() {
257        let turn_started = Event::TurnStarted {
258            turn_number: 1,
259            max_turns: 10,
260        };
261
262        let serialized = serde_json::to_string(&turn_started).unwrap();
263        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
264
265        match deserialized {
266            Event::TurnStarted {
267                turn_number,
268                max_turns,
269            } => {
270                assert_eq!(turn_number, 1);
271                assert_eq!(max_turns, 10);
272            }
273            _ => panic!("Expected TurnStarted variant"),
274        }
275
276        let turn_completed = Event::TurnCompleted {
277            turn_number: 1,
278            final_turn: false,
279        };
280
281        let serialized = serde_json::to_string(&turn_completed).unwrap();
282        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
283
284        match deserialized {
285            Event::TurnCompleted {
286                turn_number,
287                final_turn,
288            } => {
289                assert_eq!(turn_number, 1);
290                assert!(!final_turn);
291            }
292            _ => panic!("Expected TurnCompleted variant"),
293        }
294    }
295
296    #[test]
297    fn test_uuid_types() {
298        let submission_id: SubmissionId = Uuid::new_v4();
299        let agent_id: ActorID = Uuid::new_v4();
300        let runtime_id: RuntimeID = Uuid::new_v4();
301        let event_id: EventId = Uuid::new_v4();
302
303        // Test that all UUID types can be used interchangeably
304        assert_ne!(submission_id, agent_id);
305        assert_ne!(runtime_id, event_id);
306    }
307}