1pub mod backend;
21#[cfg(feature = "config-builder")]
22pub mod builder;
23pub mod middleware;
24pub mod skill;
25pub mod tools;
26
27use std::sync::Arc;
28
29use synaptic_core::{ChatModel, Store, SynapticError, Tool};
30use synaptic_graph::{create_agent, AgentOptions, Checkpointer, CompiledGraph, MessageState};
31use synaptic_macros::traceable;
32use synaptic_middleware::AgentMiddleware;
33
34use backend::Backend;
35pub use middleware::subagent::SubAgentDef;
36
37#[cfg(feature = "config-builder")]
38pub use builder::build_agent_from_config;
39
40pub struct DeepAgentOptions {
42 pub backend: Arc<dyn Backend>,
44 pub system_prompt: Option<String>,
46 pub tools: Vec<Arc<dyn Tool>>,
48 pub middleware: Vec<Arc<dyn AgentMiddleware>>,
50 pub checkpointer: Option<Arc<dyn Checkpointer>>,
52 pub store: Option<Arc<dyn Store>>,
54 pub max_input_tokens: usize,
56 pub summarization_threshold: f64,
58 pub eviction_threshold: usize,
60 pub max_subagent_depth: usize,
62 pub skills_dir: Option<String>,
64 pub memory_file: Option<String>,
66 pub subagents: Vec<SubAgentDef>,
68 pub enable_subagents: bool,
70 pub enable_filesystem: bool,
72 pub enable_skills: bool,
74 pub enable_memory: bool,
76 pub parallel_tools: bool,
78}
79
80impl DeepAgentOptions {
81 pub fn new(backend: Arc<dyn Backend>) -> Self {
83 Self {
84 backend,
85 system_prompt: None,
86 tools: Vec::new(),
87 middleware: Vec::new(),
88 checkpointer: None,
89 store: None,
90 max_input_tokens: 128_000,
91 summarization_threshold: 0.85,
92 eviction_threshold: 20_000,
93 max_subagent_depth: 3,
94 skills_dir: Some(".skills".to_string()),
95 memory_file: Some("AGENTS.md".to_string()),
96 subagents: Vec::new(),
97 enable_subagents: true,
98 enable_filesystem: true,
99 enable_skills: true,
100 enable_memory: true,
101 parallel_tools: false,
102 }
103 }
104}
105
106#[traceable(skip = "model,options")]
117pub fn create_deep_agent(
118 model: Arc<dyn ChatModel>,
119 options: DeepAgentOptions,
120) -> Result<CompiledGraph<MessageState>, SynapticError> {
121 let mut all_middleware: Vec<Arc<dyn AgentMiddleware>> = Vec::new();
122 let mut all_tools: Vec<Arc<dyn Tool>> = Vec::new();
123
124 if options.enable_memory {
126 let memory_file = options
127 .memory_file
128 .clone()
129 .unwrap_or_else(|| "AGENTS.md".to_string());
130 all_middleware.push(Arc::new(middleware::memory::DeepMemoryMiddleware::new(
131 options.backend.clone(),
132 memory_file,
133 )));
134 }
135
136 if options.enable_skills {
138 let skills_dir = options
139 .skills_dir
140 .clone()
141 .unwrap_or_else(|| ".skills".to_string());
142 all_middleware.push(Arc::new(middleware::skills::SkillsMiddleware::new(
143 options.backend.clone(),
144 skills_dir,
145 )));
146 }
147
148 if options.enable_filesystem {
150 let fs_tools = tools::create_filesystem_tools(options.backend.clone());
151 all_tools.extend(fs_tools);
152 all_middleware.push(Arc::new(middleware::filesystem::FilesystemMiddleware::new(
153 options.backend.clone(),
154 options.eviction_threshold,
155 )));
156 }
157
158 if options.enable_subagents {
160 let subagent_mw = middleware::subagent::SubAgentMiddleware::new(
161 options.backend.clone(),
162 model.clone(),
163 options.max_subagent_depth,
164 options.subagents.clone(),
165 );
166 all_tools.push(subagent_mw.create_task_tool());
167 }
168
169 all_middleware.push(Arc::new(
171 middleware::summarization::DeepSummarizationMiddleware::new(
172 options.backend.clone(),
173 model.clone(),
174 options.max_input_tokens,
175 options.summarization_threshold,
176 ),
177 ));
178
179 all_middleware.push(Arc::new(
181 middleware::patch_tool_calls::PatchToolCallsMiddleware,
182 ));
183
184 all_middleware.extend(options.middleware);
186
187 all_tools.extend(options.tools);
189
190 let agent_options = AgentOptions {
192 checkpointer: options.checkpointer,
193 interrupt_before: Vec::new(),
194 interrupt_after: Vec::new(),
195 system_prompt: options.system_prompt,
196 middleware: all_middleware,
197 store: options.store,
198 name: Some("deep_agent".to_string()),
199 pre_model_hook: None,
200 post_model_hook: None,
201 response_format: None,
202 parallel_tools: options.parallel_tools,
203 };
204
205 create_agent(model, all_tools, agent_options)
206}