Skip to main content

autoagents_protocol/
protocol.rs

1use crate::StreamChunk;
2use crate::task::Task;
3use crate::tool::ToolCallResult;
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        sub_id: SubmissionId,
69        actor_id: ActorID,
70        id: String,
71        tool_name: String,
72        arguments: String,
73    },
74
75    /// Tool call completed (with ID and result)
76    ToolCallCompleted {
77        sub_id: SubmissionId,
78        actor_id: ActorID,
79        id: String,
80        tool_name: String,
81        result: serde_json::Value,
82    },
83
84    /// Tool call has failed
85    ToolCallFailed {
86        sub_id: SubmissionId,
87        actor_id: ActorID,
88        id: String,
89        tool_name: String,
90        error: String,
91    },
92
93    /// Sandbox code execution has started
94    CodeExecutionStarted {
95        sub_id: SubmissionId,
96        actor_id: ActorID,
97        execution_id: String,
98        language: String,
99        source: String,
100    },
101
102    /// Console output produced during sandbox code execution
103    CodeExecutionConsole {
104        sub_id: SubmissionId,
105        actor_id: ActorID,
106        execution_id: String,
107        message: String,
108    },
109
110    /// Sandbox code execution completed successfully
111    CodeExecutionCompleted {
112        sub_id: SubmissionId,
113        actor_id: ActorID,
114        execution_id: String,
115        result: serde_json::Value,
116        duration_ms: u64,
117    },
118
119    /// Sandbox code execution failed
120    CodeExecutionFailed {
121        sub_id: SubmissionId,
122        actor_id: ActorID,
123        execution_id: String,
124        error: String,
125        duration_ms: u64,
126    },
127
128    /// A turn has started
129    TurnStarted {
130        sub_id: SubmissionId,
131        actor_id: ActorID,
132        turn_number: usize,
133        max_turns: usize,
134    },
135
136    /// A turn has completed
137    TurnCompleted {
138        sub_id: SubmissionId,
139        actor_id: ActorID,
140        turn_number: usize,
141        final_turn: bool,
142    },
143
144    /// Streaming chunk from agent
145    StreamChunk {
146        sub_id: SubmissionId,
147        chunk: StreamChunk,
148    },
149
150    /// Streaming tool call chunk
151    StreamToolCall {
152        sub_id: SubmissionId,
153        tool_call: serde_json::Value,
154    },
155
156    /// Streaming completed
157    StreamComplete {
158        sub_id: SubmissionId,
159    },
160}
161
162/// Internal events that are processed within the runtime
163#[derive(Debug)]
164pub enum InternalEvent {
165    /// Process a protocol event
166    ProtocolEvent(Box<Event>),
167    /// Shutdown signal
168    Shutdown,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub enum StreamingTurnResult {
173    Complete(String),
174    ToolCallsProcessed(Vec<ToolCallResult>),
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use serde_json::json;
181
182    #[test]
183    fn test_event_serialization_new_task() {
184        let _ = Uuid::new_v4();
185        let event = Event::NewTask {
186            actor_id: Default::default(),
187            task: Task::new(String::from("test")),
188        };
189
190        //Check if serialization and deserilization works properly
191        let serialized = serde_json::to_string(&event).unwrap();
192        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
193
194        match deserialized {
195            Event::NewTask { task, .. } => {
196                assert_eq!(task.prompt, "test");
197            }
198            _ => panic!("Expected NewTask variant"),
199        }
200    }
201
202    #[test]
203    fn test_event_serialization_task_started() {
204        let event = Event::TaskStarted {
205            sub_id: Uuid::new_v4(),
206            actor_id: Default::default(),
207            actor_name: String::from("test"),
208            task_description: "Started task".to_string(),
209        };
210
211        let serialized = serde_json::to_string(&event).unwrap();
212        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
213
214        match deserialized {
215            Event::TaskStarted {
216                task_description, ..
217            } => {
218                assert_eq!(task_description, "Started task");
219            }
220            _ => panic!("Expected TaskStarted variant"),
221        }
222    }
223
224    #[test]
225    fn test_event_serialization_tool_calls() {
226        let tool_call_requested = Event::ToolCallRequested {
227            sub_id: Uuid::new_v4(),
228            actor_id: Uuid::new_v4(),
229            id: "call_123".to_string(),
230            tool_name: "test_tool".to_string(),
231            arguments: "{\"param\": \"value\"}".to_string(),
232        };
233
234        let serialized = serde_json::to_string(&tool_call_requested).unwrap();
235        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
236
237        match deserialized {
238            Event::ToolCallRequested {
239                id,
240                tool_name,
241                arguments,
242                ..
243            } => {
244                assert_eq!(id, "call_123");
245                assert_eq!(tool_name, "test_tool");
246                assert_eq!(arguments, "{\"param\": \"value\"}");
247            }
248            _ => panic!("Expected ToolCallRequested variant"),
249        }
250    }
251
252    #[test]
253    fn test_event_serialization_tool_call_completed() {
254        let result = json!({"output": "tool result"});
255        let event = Event::ToolCallCompleted {
256            sub_id: Uuid::new_v4(),
257            actor_id: Uuid::new_v4(),
258            id: "call_456".to_string(),
259            tool_name: "completed_tool".to_string(),
260            result: result.clone(),
261        };
262
263        let serialized = serde_json::to_string(&event).unwrap();
264        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
265
266        match deserialized {
267            Event::ToolCallCompleted {
268                id,
269                tool_name,
270                result: res,
271                ..
272            } => {
273                assert_eq!(id, "call_456");
274                assert_eq!(tool_name, "completed_tool");
275                assert_eq!(res, result);
276            }
277            _ => panic!("Expected ToolCallCompleted variant"),
278        }
279    }
280
281    #[test]
282    fn test_event_serialization_tool_call_failed() {
283        let event = Event::ToolCallFailed {
284            sub_id: Uuid::new_v4(),
285            actor_id: Uuid::new_v4(),
286            id: "call_789".to_string(),
287            tool_name: "failed_tool".to_string(),
288            error: "Tool execution failed".to_string(),
289        };
290
291        let serialized = serde_json::to_string(&event).unwrap();
292        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
293
294        match deserialized {
295            Event::ToolCallFailed {
296                id,
297                tool_name,
298                error,
299                ..
300            } => {
301                assert_eq!(id, "call_789");
302                assert_eq!(tool_name, "failed_tool");
303                assert_eq!(error, "Tool execution failed");
304            }
305            _ => panic!("Expected ToolCallFailed variant"),
306        }
307    }
308
309    #[test]
310    fn test_event_serialization_code_execution_started() {
311        let event = Event::CodeExecutionStarted {
312            sub_id: Uuid::new_v4(),
313            actor_id: Uuid::new_v4(),
314            execution_id: "exec_123".to_string(),
315            language: "typescript".to_string(),
316            source: "return 42;".to_string(),
317        };
318
319        let serialized = serde_json::to_string(&event).unwrap();
320        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
321
322        match deserialized {
323            Event::CodeExecutionStarted {
324                execution_id,
325                language,
326                source,
327                ..
328            } => {
329                assert_eq!(execution_id, "exec_123");
330                assert_eq!(language, "typescript");
331                assert_eq!(source, "return 42;");
332            }
333            _ => panic!("Expected CodeExecutionStarted variant"),
334        }
335    }
336
337    #[test]
338    fn test_event_serialization_code_execution_completed() {
339        let result = json!({"value": 42});
340        let event = Event::CodeExecutionCompleted {
341            sub_id: Uuid::new_v4(),
342            actor_id: Uuid::new_v4(),
343            execution_id: "exec_456".to_string(),
344            result: result.clone(),
345            duration_ms: 17,
346        };
347
348        let serialized = serde_json::to_string(&event).unwrap();
349        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
350
351        match deserialized {
352            Event::CodeExecutionCompleted {
353                execution_id,
354                result: actual,
355                duration_ms,
356                ..
357            } => {
358                assert_eq!(execution_id, "exec_456");
359                assert_eq!(actual, result);
360                assert_eq!(duration_ms, 17);
361            }
362            _ => panic!("Expected CodeExecutionCompleted variant"),
363        }
364    }
365
366    #[test]
367    fn test_event_serialization_turn_events() {
368        let turn_started = Event::TurnStarted {
369            sub_id: Uuid::new_v4(),
370            actor_id: Uuid::new_v4(),
371            turn_number: 1,
372            max_turns: 10,
373        };
374
375        let serialized = serde_json::to_string(&turn_started).unwrap();
376        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
377
378        match deserialized {
379            Event::TurnStarted {
380                turn_number,
381                max_turns,
382                ..
383            } => {
384                assert_eq!(turn_number, 1);
385                assert_eq!(max_turns, 10);
386            }
387            _ => panic!("Expected TurnStarted variant"),
388        }
389
390        let turn_completed = Event::TurnCompleted {
391            sub_id: Uuid::new_v4(),
392            actor_id: Uuid::new_v4(),
393            turn_number: 1,
394            final_turn: false,
395        };
396
397        let serialized = serde_json::to_string(&turn_completed).unwrap();
398        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
399
400        match deserialized {
401            Event::TurnCompleted {
402                turn_number,
403                final_turn,
404                ..
405            } => {
406                assert_eq!(turn_number, 1);
407                assert!(!final_turn);
408            }
409            _ => panic!("Expected TurnCompleted variant"),
410        }
411    }
412
413    #[test]
414    fn test_uuid_types() {
415        let submission_id: SubmissionId = Uuid::new_v4();
416        let agent_id: ActorID = Uuid::new_v4();
417        let runtime_id: RuntimeID = Uuid::new_v4();
418        let event_id: EventId = Uuid::new_v4();
419
420        // Test that all UUID types can be used interchangeably
421        assert_ne!(submission_id, agent_id);
422        assert_ne!(runtime_id, event_id);
423    }
424}