autumn_plugin_agent/
delegate.rs1use std::future::Future;
10use std::pin::Pin;
11
12use crate::agent::{Agent, AgentOutcome};
13use crate::error::{AgentError, ErrorKind};
14use crate::tools::{Tool, ToolContext, ToolEffect};
15
16#[derive(Debug, Clone)]
38pub struct AgentTool {
39 name: String,
40 description: String,
41 agent: Agent,
42 effect: ToolEffect,
43}
44
45impl AgentTool {
46 #[must_use]
48 pub fn new(name: impl Into<String>, description: impl Into<String>, agent: Agent) -> Self {
49 Self {
50 name: name.into(),
51 description: description.into(),
52 agent,
53 effect: ToolEffect::Write,
54 }
55 }
56
57 #[must_use]
60 pub const fn effect(mut self, effect: ToolEffect) -> Self {
61 self.effect = effect;
62 self
63 }
64}
65
66impl Tool for AgentTool {
67 fn name(&self) -> &str {
68 &self.name
69 }
70
71 fn description(&self) -> &str {
72 &self.description
73 }
74
75 fn input_schema(&self) -> serde_json::Value {
76 serde_json::json!({
77 "type": "object",
78 "properties": {
79 "task": {
80 "type": "string",
81 "description": "The task, with every detail the helper needs: it cannot see this conversation.",
82 }
83 },
84 "required": ["task"]
85 })
86 }
87
88 fn effect(&self) -> ToolEffect {
89 self.effect
90 }
91
92 fn execute<'a>(
93 &'a self,
94 input: serde_json::Value,
95 _ctx: &'a ToolContext,
96 ) -> Pin<Box<dyn Future<Output = Result<serde_json::Value, AgentError>> + Send + 'a>> {
97 Box::pin(async move {
98 let task = input
99 .get("task")
100 .and_then(serde_json::Value::as_str)
101 .map(str::trim)
102 .filter(|task| !task.is_empty())
103 .ok_or_else(|| AgentError::new(ErrorKind::Tool, "give the `task` to delegate"))?;
104 let outcome = self.agent.run(task).await?;
105 let usage = outcome.usage();
106 let tokens = usage.total();
107 Ok(match outcome {
108 AgentOutcome::Completed { text, .. } => {
109 serde_json::json!({"answer": text, "tokens": tokens})
110 }
111 AgentOutcome::AwaitingApproval { .. } => serde_json::json!({
112 "error": "the helper needs a person to approve an action; do it another way",
113 }),
114 other => serde_json::json!({
115 "error": "the helper stopped before it finished",
116 "outcome": other,
117 }),
118 })
119 })
120 }
121}
122
123#[cfg(test)]
124mod tests;