atomr_agents_tool/
handoff.rs1use async_trait::async_trait;
8use atomr_agents_core::{InvokeCtx, Result, ToolId, Value};
9
10use crate::descriptor::{ToolDescriptor, ToolSchema};
11use crate::tool_return::{RichTool, ToolControl, ToolReturn};
12
13pub struct HandoffTool {
14 pub default_target: String,
15 descriptor: ToolDescriptor,
16}
17
18impl HandoffTool {
19 pub fn new(default_target: impl Into<String>) -> Self {
20 let target = default_target.into();
21 Self {
22 descriptor: ToolDescriptor {
23 id: ToolId::from(format!("handoff_{target}")),
24 name: format!("handoff_to_{target}"),
25 description: format!("Hand off control to the {target} agent."),
26 schema: ToolSchema(serde_json::json!({
27 "type": "object",
28 "properties": {
29 "target": {"type": "string"},
30 "payload": {},
31 }
32 })),
33 },
34 default_target: target,
35 }
36 }
37}
38
39#[async_trait]
40impl RichTool for HandoffTool {
41 fn descriptor(&self) -> &ToolDescriptor {
42 &self.descriptor
43 }
44 async fn invoke_rich(&self, args: Value, _ctx: &InvokeCtx) -> Result<ToolReturn> {
45 let target = args
46 .get("target")
47 .and_then(|v| v.as_str())
48 .map(|s| s.to_string())
49 .unwrap_or_else(|| self.default_target.clone());
50 let payload = args.get("payload").cloned().unwrap_or(Value::Null);
51 Ok(ToolReturn::Command(ToolControl::Handoff { target, payload }))
52 }
53}