1pub mod backend;
21#[cfg(feature = "config-builder")]
22pub mod builder;
23pub mod middleware;
24pub mod tools;
25
26use std::sync::Arc;
27
28use synaptic_core::{ChatModel, Store, SynapticError, Tool};
29use synaptic_graph::{create_agent, AgentOptions, Checkpointer, CompiledGraph, MessageState};
30use synaptic_macros::traceable;
31use synaptic_middleware::AgentMiddleware;
32
33use backend::Backend;
34pub use middleware::subagent::SubAgentDef;
35
36#[cfg(feature = "config-builder")]
37pub use builder::build_agent_from_config;
38
39pub struct DeepAgentOptions {
41 pub backend: Arc<dyn Backend>,
43 pub system_prompt: Option<String>,
45 pub tools: Vec<Arc<dyn Tool>>,
47 pub middleware: Vec<Arc<dyn AgentMiddleware>>,
49 pub checkpointer: Option<Arc<dyn Checkpointer>>,
51 pub store: Option<Arc<dyn Store>>,
53 pub max_input_tokens: usize,
55 pub summarization_threshold: f64,
57 pub eviction_threshold: usize,
59 pub max_subagent_depth: usize,
61 pub skills_dir: Option<String>,
63 pub memory_file: Option<String>,
65 pub subagents: Vec<SubAgentDef>,
67 pub enable_subagents: bool,
69 pub enable_filesystem: bool,
71 pub enable_skills: bool,
73 pub enable_memory: bool,
75}
76
77impl DeepAgentOptions {
78 pub fn new(backend: Arc<dyn Backend>) -> Self {
80 Self {
81 backend,
82 system_prompt: None,
83 tools: Vec::new(),
84 middleware: Vec::new(),
85 checkpointer: None,
86 store: None,
87 max_input_tokens: 128_000,
88 summarization_threshold: 0.85,
89 eviction_threshold: 20_000,
90 max_subagent_depth: 3,
91 skills_dir: Some(".skills".to_string()),
92 memory_file: Some("AGENTS.md".to_string()),
93 subagents: Vec::new(),
94 enable_subagents: true,
95 enable_filesystem: true,
96 enable_skills: true,
97 enable_memory: true,
98 }
99 }
100}
101
102#[traceable(skip = "model,options")]
113pub fn create_deep_agent(
114 model: Arc<dyn ChatModel>,
115 options: DeepAgentOptions,
116) -> Result<CompiledGraph<MessageState>, SynapticError> {
117 let mut all_middleware: Vec<Arc<dyn AgentMiddleware>> = Vec::new();
118 let mut all_tools: Vec<Arc<dyn Tool>> = Vec::new();
119
120 if options.enable_memory {
122 let memory_file = options
123 .memory_file
124 .clone()
125 .unwrap_or_else(|| "AGENTS.md".to_string());
126 all_middleware.push(Arc::new(middleware::memory::DeepMemoryMiddleware::new(
127 options.backend.clone(),
128 memory_file,
129 )));
130 }
131
132 if options.enable_skills {
134 let skills_dir = options
135 .skills_dir
136 .clone()
137 .unwrap_or_else(|| ".skills".to_string());
138 all_middleware.push(Arc::new(middleware::skills::SkillsMiddleware::new(
139 options.backend.clone(),
140 skills_dir,
141 )));
142 }
143
144 if options.enable_filesystem {
146 let fs_tools = tools::create_filesystem_tools(options.backend.clone());
147 all_tools.extend(fs_tools);
148 all_middleware.push(Arc::new(middleware::filesystem::FilesystemMiddleware::new(
149 options.backend.clone(),
150 options.eviction_threshold,
151 )));
152 }
153
154 if options.enable_subagents {
156 let subagent_mw = middleware::subagent::SubAgentMiddleware::new(
157 options.backend.clone(),
158 model.clone(),
159 options.max_subagent_depth,
160 options.subagents.clone(),
161 );
162 all_tools.push(subagent_mw.create_task_tool());
163 }
164
165 all_middleware.push(Arc::new(
167 middleware::summarization::DeepSummarizationMiddleware::new(
168 options.backend.clone(),
169 model.clone(),
170 options.max_input_tokens,
171 options.summarization_threshold,
172 ),
173 ));
174
175 all_middleware.push(Arc::new(
177 middleware::patch_tool_calls::PatchToolCallsMiddleware,
178 ));
179
180 all_middleware.extend(options.middleware);
182
183 all_tools.extend(options.tools);
185
186 let agent_options = AgentOptions {
188 checkpointer: options.checkpointer,
189 interrupt_before: Vec::new(),
190 interrupt_after: Vec::new(),
191 system_prompt: options.system_prompt,
192 middleware: all_middleware,
193 store: options.store,
194 name: Some("deep_agent".to_string()),
195 pre_model_hook: None,
196 post_model_hook: None,
197 response_format: None,
198 };
199
200 create_agent(model, all_tools, agent_options)
201}