agents_runtime/agent/
api.rs

1//! Public API functions that mirror the Python SDK exactly
2//!
3//! This module provides the main entry points for creating Deep Agents,
4//! matching the Python `create_deep_agent()` and `async_create_deep_agent()` functions.
5
6use super::builder::ConfigurableAgentBuilder;
7use super::config::{CreateDeepAgentParams, DeepAgentConfig};
8use super::runtime::DeepAgent;
9use crate::providers::{OpenAiChatModel, OpenAiConfig};
10use agents_core::llm::LanguageModel;
11use std::sync::Arc;
12
13/// Returns the default language model configured
14/// Uses OpenAI GPT-4o-mini for cost-effective operation.
15/// This model provides excellent performance at a fraction of the cost compared to larger models.
16///
17/// Cost comparison:
18/// - GPT-4o-mini: $0.15/1M input tokens, $0.60/1M output tokens
19/// - Claude Sonnet 4: $3.00/1M input tokens, $15.00/1M output tokens
20///
21///   = ~95% cost savings!
22pub fn get_default_model() -> anyhow::Result<Arc<dyn LanguageModel>> {
23    let config = OpenAiConfig {
24        api_key: std::env::var("OPENAI_API_KEY")
25            .map_err(|_| anyhow::anyhow!("OPENAI_API_KEY environment variable is required"))?,
26        model: "gpt-4o-mini".to_string(),
27        api_url: None,
28    };
29    let model: Arc<dyn LanguageModel> = Arc::new(OpenAiChatModel::new(config)?);
30    Ok(model)
31}
32
33/// Create a deep agent - matches Python create_deep_agent() API exactly
34///
35/// This is the main entry point that mirrors the Python SDK:
36/// ```python
37/// agent = create_deep_agent(
38///     tools=[internet_search],
39///     instructions="You are an expert researcher...",
40///     model=model,
41///     subagents=subagents,
42///     checkpointer=checkpointer,
43///     tool_configs=tool_configs
44/// )
45/// ```
46pub fn create_deep_agent(params: CreateDeepAgentParams) -> anyhow::Result<DeepAgent> {
47    let CreateDeepAgentParams {
48        tools,
49        instructions,
50        middleware,
51        model,
52        subagents,
53        context_schema,
54        checkpointer,
55        tool_configs,
56    } = params;
57
58    if context_schema.is_some() {
59        tracing::warn!(
60            "context_schema parameter for create_deep_agent is not yet supported in Rust SDK"
61        );
62    }
63
64    if !middleware.is_empty() {
65        tracing::warn!("middleware parameter for create_deep_agent is not yet supported in Rust SDK ({} entries)", middleware.len());
66    }
67
68    let mut builder = ConfigurableAgentBuilder::new(instructions);
69
70    let model = match model {
71        Some(model) => model,
72        None => get_default_model()?,
73    };
74    builder = builder.with_model(model);
75
76    if !tools.is_empty() {
77        builder = builder.with_tools(tools);
78    }
79
80    if !subagents.is_empty() {
81        builder = builder.with_subagent_config(subagents);
82    }
83
84    if let Some(checkpointer) = checkpointer {
85        builder = builder.with_checkpointer(checkpointer);
86    }
87
88    if !tool_configs.is_empty() {
89        for (tool, policy) in tool_configs {
90            builder = builder.with_tool_interrupt(tool, policy);
91        }
92    }
93
94    builder.build()
95}
96
97/// Async constructor alias to mirror the Python API surface.
98///
99/// The underlying runtime already executes every tool and planner call asynchronously,
100/// so this currently delegates to `create_deep_agent`.
101///
102/// Mirrors Python's `async_create_deep_agent()` function.
103pub fn create_async_deep_agent(params: CreateDeepAgentParams) -> anyhow::Result<DeepAgent> {
104    create_deep_agent(params)
105}
106
107/// Internal function used by the builder - creates agent from config
108pub(crate) fn create_deep_agent_from_config(config: DeepAgentConfig) -> DeepAgent {
109    super::runtime::create_deep_agent_from_config(config)
110}
111
112/// Internal async alias used by the builder
113pub(crate) fn create_async_deep_agent_from_config(config: DeepAgentConfig) -> DeepAgent {
114    super::runtime::create_deep_agent_from_config(config)
115}