claude_agent/agent/
executor.rs1use std::sync::Arc;
4
5use tokio::sync::RwLock;
6
7use super::config::AgentConfig;
8use crate::Client;
9use crate::budget::{BudgetTracker, TenantBudget};
10use crate::context::PromptOrchestrator;
11use crate::hooks::HookManager;
12use crate::tools::{ToolRegistry, ToolRegistryBuilder};
13use crate::types::Message;
14
15pub struct Agent {
16 pub(crate) client: Client,
17 pub(crate) config: AgentConfig,
18 pub(crate) tools: Arc<ToolRegistry>,
19 pub(crate) hooks: HookManager,
20 pub(crate) session_id: String,
21 pub(crate) orchestrator: Option<Arc<RwLock<PromptOrchestrator>>>,
22 pub(crate) initial_messages: Option<Vec<Message>>,
23 pub(crate) budget_tracker: BudgetTracker,
24 pub(crate) tenant_budget: Option<Arc<TenantBudget>>,
25 pub(crate) mcp_manager: Option<Arc<crate::mcp::McpManager>>,
26}
27
28impl Agent {
29 pub fn new(client: Client, config: AgentConfig) -> Self {
30 let tools = ToolRegistry::default_tools(
31 &config.security.tool_access,
32 config.working_dir.clone(),
33 Some(config.security.permission_policy.clone()),
34 );
35 Self::from_parts(client, config, Arc::new(tools), HookManager::new(), None)
36 }
37
38 pub fn with_skills(
39 client: Client,
40 config: AgentConfig,
41 skill_executor: crate::skills::SkillExecutor,
42 ) -> Self {
43 let mut builder = ToolRegistryBuilder::new()
44 .access(&config.security.tool_access)
45 .skill_executor(skill_executor)
46 .policy(config.security.permission_policy.clone());
47
48 if let Some(dir) = config.working_dir.clone() {
49 builder = builder.working_dir(dir);
50 }
51
52 let tools = builder.build();
53 Self::from_parts(client, config, Arc::new(tools), HookManager::new(), None)
54 }
55
56 pub fn with_components(
57 client: Client,
58 config: AgentConfig,
59 tools: ToolRegistry,
60 hooks: HookManager,
61 ) -> Self {
62 Self::from_parts(client, config, Arc::new(tools), hooks, None)
63 }
64
65 pub fn with_orchestrator(
66 client: Client,
67 config: AgentConfig,
68 tools: Arc<ToolRegistry>,
69 hooks: HookManager,
70 orchestrator: PromptOrchestrator,
71 ) -> Self {
72 Self::from_parts(
73 client,
74 config,
75 tools,
76 hooks,
77 Some(Arc::new(RwLock::new(orchestrator))),
78 )
79 }
80
81 pub fn with_shared_tools(
82 client: Client,
83 config: AgentConfig,
84 tools: Arc<ToolRegistry>,
85 hooks: HookManager,
86 ) -> Self {
87 Self::from_parts(client, config, tools, hooks, None)
88 }
89
90 fn from_parts(
91 client: Client,
92 config: AgentConfig,
93 tools: Arc<ToolRegistry>,
94 hooks: HookManager,
95 orchestrator: Option<Arc<RwLock<PromptOrchestrator>>>,
96 ) -> Self {
97 let budget_tracker = match config.budget.max_cost_usd {
98 Some(max) => BudgetTracker::new(max),
99 None => BudgetTracker::unlimited(),
100 };
101
102 Self {
103 client,
104 config,
105 tools,
106 hooks,
107 session_id: uuid::Uuid::new_v4().to_string(),
108 orchestrator,
109 initial_messages: None,
110 budget_tracker,
111 tenant_budget: None,
112 mcp_manager: None,
113 }
114 }
115
116 pub fn with_tenant_budget(mut self, budget: Arc<TenantBudget>) -> Self {
117 self.tenant_budget = Some(budget);
118 self
119 }
120
121 pub fn with_mcp_manager(mut self, manager: Arc<crate::mcp::McpManager>) -> Self {
122 self.mcp_manager = Some(manager);
123 self
124 }
125
126 pub fn mcp_manager(&self) -> Option<&Arc<crate::mcp::McpManager>> {
127 self.mcp_manager.as_ref()
128 }
129
130 pub fn with_initial_messages(mut self, messages: Vec<Message>) -> Self {
131 self.initial_messages = Some(messages);
132 self
133 }
134
135 pub fn with_session_id(mut self, id: impl Into<String>) -> Self {
136 self.session_id = id.into();
137 self
138 }
139
140 #[must_use]
141 pub fn builder() -> super::AgentBuilder {
142 super::AgentBuilder::new()
143 }
144
145 pub fn with_model(model: impl Into<String>) -> super::AgentBuilder {
146 super::AgentBuilder::new().model(model)
147 }
148
149 pub async fn default_agent() -> crate::Result<Self> {
150 Self::builder().build().await
151 }
152
153 #[must_use]
154 pub fn hooks(&self) -> &HookManager {
155 &self.hooks
156 }
157
158 #[must_use]
159 pub fn session_id(&self) -> &str {
160 &self.session_id
161 }
162
163 pub fn orchestrator(&self) -> Option<&Arc<RwLock<PromptOrchestrator>>> {
164 self.orchestrator.as_ref()
165 }
166
167 #[must_use]
168 pub fn config(&self) -> &AgentConfig {
169 &self.config
170 }
171
172 #[must_use]
173 pub fn tools(&self) -> &Arc<ToolRegistry> {
174 &self.tools
175 }
176}