1use std::sync::Arc;
2
3use crate::guardrails::{InputGuardrail, OutputGuardrail};
4use crate::handoffs::Handoff;
5use crate::model::ModelRef;
6use crate::model_settings::ModelSettings;
7use crate::runtime::RuntimeHook;
8use crate::tools::{AgentToolBuilder, BackgroundAgentTaskBuilder};
9use crate::tools::{Tool, ToolPolicy};
10use crate::types::Metadata;
11
12#[derive(Clone)]
13pub struct Agent {
14 name: String,
15 instructions: String,
16 model: Option<ModelRef>,
17 model_settings: ModelSettings,
18 tools: Vec<Arc<dyn Tool>>,
19 handoffs: Vec<Handoff>,
20 input_guardrails: Vec<Arc<dyn InputGuardrail>>,
21 output_guardrails: Vec<Arc<dyn OutputGuardrail>>,
22 hooks: Vec<Arc<dyn RuntimeHook>>,
23 max_cycles: Option<u32>,
24 tool_use_behavior: ToolUseBehavior,
25 tool_policy: ToolPolicy,
26 metadata: Metadata,
27}
28
29impl Agent {
30 pub fn builder(name: impl Into<String>) -> AgentBuilder {
31 AgentBuilder {
32 agent: Self {
33 name: name.into(),
34 instructions: String::new(),
35 model: None,
36 model_settings: ModelSettings::default(),
37 tools: Vec::new(),
38 handoffs: Vec::new(),
39 input_guardrails: Vec::new(),
40 output_guardrails: Vec::new(),
41 hooks: Vec::new(),
42 max_cycles: None,
43 tool_use_behavior: ToolUseBehavior::default(),
44 tool_policy: ToolPolicy::default(),
45 metadata: Metadata::new(),
46 },
47 }
48 }
49
50 pub fn name(&self) -> &str {
51 &self.name
52 }
53
54 pub fn instructions(&self) -> &str {
55 &self.instructions
56 }
57
58 pub fn model(&self) -> Option<&ModelRef> {
59 self.model.as_ref()
60 }
61
62 pub fn model_settings(&self) -> &ModelSettings {
63 &self.model_settings
64 }
65
66 pub fn tools(&self) -> &[Arc<dyn Tool>] {
67 &self.tools
68 }
69
70 pub fn handoffs(&self) -> &[Handoff] {
71 &self.handoffs
72 }
73
74 pub(crate) fn input_guardrails(&self) -> &[Arc<dyn InputGuardrail>] {
75 &self.input_guardrails
76 }
77
78 pub(crate) fn output_guardrails(&self) -> &[Arc<dyn OutputGuardrail>] {
79 &self.output_guardrails
80 }
81
82 pub fn hooks(&self) -> &[Arc<dyn RuntimeHook>] {
83 &self.hooks
84 }
85
86 pub fn max_cycles(&self) -> Option<u32> {
87 self.max_cycles
88 }
89
90 pub fn tool_use_behavior(&self) -> &ToolUseBehavior {
91 &self.tool_use_behavior
92 }
93
94 pub fn tool_policy(&self) -> &ToolPolicy {
95 &self.tool_policy
96 }
97
98 pub fn metadata(&self) -> &Metadata {
99 &self.metadata
100 }
101
102 pub fn as_tool(&self) -> AgentToolBuilder {
103 AgentToolBuilder::new(self.clone())
104 }
105
106 pub fn as_background_task(&self) -> BackgroundAgentTaskBuilder {
107 BackgroundAgentTaskBuilder::new(self.clone())
108 }
109}
110
111pub struct AgentBuilder {
112 agent: Agent,
113}
114
115impl AgentBuilder {
116 pub fn instructions(mut self, instructions: impl Into<String>) -> Self {
117 self.agent.instructions = instructions.into();
118 self
119 }
120
121 pub fn model(mut self, model: ModelRef) -> Self {
122 self.agent.model = Some(model);
123 self
124 }
125
126 pub fn model_settings(mut self, settings: ModelSettings) -> Self {
127 self.agent.model_settings = settings;
128 self
129 }
130
131 pub fn tool(mut self, tool: impl Tool + 'static) -> Self {
132 self.agent.tools.push(Arc::new(tool));
133 self
134 }
135
136 pub fn tool_arc(mut self, tool: Arc<dyn Tool>) -> Self {
137 self.agent.tools.push(tool);
138 self
139 }
140
141 pub fn handoff(mut self, handoff: impl Into<Handoff>) -> Self {
142 self.agent.handoffs.push(handoff.into());
143 self
144 }
145
146 pub fn input_guardrail(mut self, guardrail: Arc<dyn InputGuardrail>) -> Self {
147 self.agent.input_guardrails.push(guardrail);
148 self
149 }
150
151 pub fn output_guardrail(mut self, guardrail: Arc<dyn OutputGuardrail>) -> Self {
152 self.agent.output_guardrails.push(guardrail);
153 self
154 }
155
156 pub fn hook(mut self, hook: Arc<dyn RuntimeHook>) -> Self {
157 self.agent.hooks.push(hook);
158 self
159 }
160
161 pub fn max_cycles(mut self, max_cycles: u32) -> Self {
162 self.agent.max_cycles = Some(max_cycles);
163 self
164 }
165
166 pub fn tool_use_behavior(mut self, behavior: ToolUseBehavior) -> Self {
167 self.agent.tool_use_behavior = behavior;
168 self
169 }
170
171 pub fn tool_policy(mut self, tool_policy: ToolPolicy) -> Self {
172 self.agent.tool_policy = tool_policy;
173 self
174 }
175
176 pub fn metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
177 self.agent.metadata.insert(key.into(), value);
178 self
179 }
180
181 pub fn build(self) -> Result<Agent, String> {
182 if self.agent.name.trim().is_empty() {
183 return Err("agent name cannot be empty".to_string());
184 }
185 if self.agent.instructions.trim().is_empty() {
186 return Err("agent instructions cannot be empty".to_string());
187 }
188 Ok(self.agent)
189 }
190}
191
192#[derive(Clone, Default)]
193pub enum ToolUseBehavior {
194 #[default]
195 RunLlmAgain,
196 StopOnFirstTool,
197 StopAtTools(Vec<String>),
198}