serdes_ai/lib.rs
1//! # SerdesAI - Type-Safe AI Agent Framework for Rust
2//!
3//! SerdesAI is a comprehensive Rust library for building AI agents that interact with
4//! large language models (LLMs). It is a complete port of [pydantic-ai](https://github.com/pydantic/pydantic-ai)
5//! to Rust, providing type-safe, ergonomic APIs for creating intelligent agents.
6//!
7//! ## Quick Start
8//!
9//! ```ignore
10//! use serdes_ai::prelude::*;
11//!
12//! #[tokio::main]
13//! async fn main() -> anyhow::Result<()> {
14//! let agent = Agent::builder()
15//! .model("openai:gpt-4o")
16//! .system_prompt("You are a helpful assistant.")
17//! .build()?;
18//!
19//! let result = agent.run("What is the capital of France?", ()).await?;
20//! println!("{}", result.output());
21//! Ok(())
22//! }
23//! ```
24//!
25//! ## Key Features
26//!
27//! - **Type-safe agents** with generic dependencies and output types
28//! - **Multiple LLM providers** (OpenAI, Anthropic, Google, Groq, Mistral, Ollama, Bedrock)
29//! - **Tool/function calling** with automatic JSON schema generation
30//! - **Streaming responses** with real-time text updates
31//! - **Structured outputs** with JSON Schema validation
32//! - **MCP protocol support** for Model Context Protocol servers
33//! - **Embeddings** for semantic search and RAG applications
34//! - **Graph-based workflows** for complex multi-step tasks
35//! - **Evaluation framework** for testing and benchmarking agents
36//! - **Retry strategies** with exponential backoff
37//! - **OpenTelemetry integration** for observability
38//!
39//! ## Feature Flags
40//!
41//! | Feature | Description | Default |
42//! |---------|-------------|--------|
43//! | `openai` | OpenAI GPT models | ✅ |
44//! | `anthropic` | Anthropic Claude models | ✅ |
45//! | `gemini` | Google Gemini models | ❌ |
46//! | `groq` | Groq fast inference | ❌ |
47//! | `mistral` | Mistral AI models | ❌ |
48//! | `ollama` | Local Ollama models | ❌ |
49//! | `bedrock` | AWS Bedrock | ❌ |
50//! | `mcp` | MCP protocol support | ❌ |
51//! | `embeddings` | Embedding models | ❌ |
52//! | `graph` | Graph execution engine | ❌ |
53//! | `evals` | Evaluation framework | ❌ |
54//! | `macros` | Proc macros | ✅ |
55//! | `otel` | OpenTelemetry | ❌ |
56//! | `full` | All features | ❌ |
57//!
58//! ## Architecture
59//!
60//! SerdesAI is organized as a workspace of focused crates:
61//!
62//! - [`serdes_ai_core`] - Core types, messages, and errors
63//! - [`serdes_ai_agent`] - Agent implementation and builder
64//! - [`serdes_ai_models`] - Model trait and implementations
65//! - [`serdes_ai_tools`] - Tool system and schema generation
66//! - [`serdes_ai_toolsets`] - Toolset abstractions
67//! - [`serdes_ai_output`] - Output schema validation
68//! - [`serdes_ai_streaming`] - Streaming support
69//! - [`serdes_ai_retries`] - Retry strategies
70//! - [`serdes_ai_mcp`] - MCP protocol (optional)
71//! - [`serdes_ai_embeddings`] - Embeddings (optional)
72//! - [`serdes_ai_graph`] - Graph execution (optional)
73//! - [`serdes_ai_evals`] - Evaluation framework (optional)
74//! - [`serdes_ai_macros`] - Procedural macros
75//!
76//! ## Examples
77//!
78//! ### Simple Chat
79//!
80//! ```ignore
81//! use serdes_ai::prelude::*;
82//!
83//! let agent = Agent::builder()
84//! .model("openai:gpt-4o")
85//! .system_prompt("You are helpful.")
86//! .build()?;
87//!
88//! let result = agent.run("Hello!", ()).await?;
89//! ```
90//!
91//! ### With Tools
92//!
93//! ```ignore
94//! use serdes_ai::prelude::*;
95//!
96//! #[tool(description = "Get weather for a city")]
97//! async fn get_weather(ctx: &RunContext<()>, city: String) -> ToolResult<String> {
98//! Ok(format!("Weather in {}: 22°C, sunny", city))
99//! }
100//!
101//! let agent = Agent::builder()
102//! .model("openai:gpt-4o")
103//! .tool(get_weather)
104//! .build()?;
105//! ```
106//!
107//! ### Structured Output
108//!
109//! ```ignore
110//! use serdes_ai::prelude::*;
111//! use serde::Deserialize;
112//!
113//! #[derive(Deserialize, OutputSchema)]
114//! struct Person {
115//! name: String,
116//! age: u32,
117//! }
118//!
119//! let agent = Agent::builder()
120//! .model("openai:gpt-4o")
121//! .output_type::<Person>()
122//! .build()?;
123//!
124//! let result: Person = agent.run("Extract: John is 30 years old", ()).await?.into_output();
125//! ```
126//!
127//! ### Streaming
128//!
129//! ```ignore
130//! use serdes_ai::prelude::*;
131//! use futures::StreamExt;
132//!
133//! let mut stream = agent.run_stream("Tell me a story", ()).await?;
134//!
135//! while let Some(event) = stream.next().await {
136//! if let AgentStreamEvent::Text { delta } = event? {
137//! print!("{}", delta);
138//! }
139//! }
140//! ```
141
142#![warn(missing_docs)]
143#![warn(rustdoc::missing_crate_level_docs)]
144#![deny(unsafe_code)]
145#![cfg_attr(docsrs, feature(doc_cfg))]
146
147// ============================================================================
148// Direct Model Access
149// ============================================================================
150
151/// Direct model request functions for imperative API access.
152///
153/// Use this module when you want to make simple, direct requests to models
154/// without the full agent infrastructure.
155///
156/// # Example
157///
158/// ```rust,ignore
159/// use serdes_ai::direct::model_request;
160/// use serdes_ai_core::ModelRequest;
161///
162/// let response = model_request(
163/// "openai:gpt-4o",
164/// &[ModelRequest::user("Hello!")],
165/// None,
166/// None,
167/// ).await?;
168/// ```
169pub mod direct;
170
171// ============================================================================
172// Core Crate Re-exports
173// ============================================================================
174
175/// Core types, messages, and error handling.
176pub use serdes_ai_core as core;
177
178/// Agent implementation and builder.
179pub use serdes_ai_agent as agent;
180
181/// Model traits and implementations.
182pub use serdes_ai_models as models;
183
184/// Provider abstractions.
185pub use serdes_ai_providers as providers;
186
187/// Tool system.
188pub use serdes_ai_tools as tools;
189
190/// Toolset abstractions.
191pub use serdes_ai_toolsets as toolsets;
192
193/// Output schema validation.
194pub use serdes_ai_output as output;
195
196/// Streaming support.
197pub use serdes_ai_streaming as streaming;
198
199/// Retry strategies.
200pub use serdes_ai_retries as retries;
201
202// ============================================================================
203// Optional Crate Re-exports
204// ============================================================================
205
206/// Model Context Protocol support.
207#[cfg(feature = "mcp")]
208#[cfg_attr(docsrs, doc(cfg(feature = "mcp")))]
209pub use serdes_ai_mcp as mcp;
210
211/// Embedding models.
212#[cfg(feature = "embeddings")]
213#[cfg_attr(docsrs, doc(cfg(feature = "embeddings")))]
214pub use serdes_ai_embeddings as embeddings;
215
216/// Graph-based execution engine.
217#[cfg(feature = "graph")]
218#[cfg_attr(docsrs, doc(cfg(feature = "graph")))]
219pub use serdes_ai_graph as graph;
220
221/// Evaluation framework.
222#[cfg(feature = "evals")]
223#[cfg_attr(docsrs, doc(cfg(feature = "evals")))]
224pub use serdes_ai_evals as evals;
225
226// ============================================================================
227// Macro Re-exports
228// ============================================================================
229
230/// Derive macro for tools.
231#[cfg(feature = "macros")]
232#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
233pub use serdes_ai_macros::Tool;
234
235/// Derive macro for output schemas.
236#[cfg(feature = "macros")]
237#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
238pub use serdes_ai_macros::OutputSchema;
239
240/// Attribute macro for tool functions.
241#[cfg(feature = "macros")]
242#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
243pub use serdes_ai_macros::tool;
244
245/// Attribute macro for agent definitions.
246#[cfg(feature = "macros")]
247#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
248pub use serdes_ai_macros::agent as agent_macro;
249
250// ============================================================================
251// Core Type Re-exports (Flat)
252// ============================================================================
253
254// Errors
255pub use serdes_ai_core::SerdesAiError;
256
257// Identifiers
258pub use serdes_ai_core::{ConversationId, RunId, ToolCallId};
259
260// Messages
261pub use serdes_ai_core::{
262 BinaryContent,
263 // Builtin tools
264 BuiltinToolCallPart,
265 BuiltinToolReturnContent,
266 BuiltinToolReturnPart,
267 CodeExecutionResult,
268 // File and binary content
269 FilePart,
270 FileSearchResult,
271 FileSearchResults,
272 FinishReason,
273 ModelRequest,
274 ModelRequestPart,
275 ModelResponse,
276 ModelResponsePart,
277 ModelResponsePartDelta,
278 // Streaming events
279 ModelResponseStreamEvent,
280 PartDeltaEvent,
281 PartEndEvent,
282 PartStartEvent,
283 SystemPromptPart,
284 TextPart,
285 ThinkingPart,
286 ToolCallPart,
287 ToolReturnPart,
288 UserContent,
289 WebSearchResult,
290 WebSearchResults,
291};
292
293// Settings
294pub use serdes_ai_core::ModelSettings;
295
296// Usage
297pub use serdes_ai_core::{RequestUsage, RunUsage, UsageLimits};
298
299// Format
300pub use serdes_ai_core::{
301 format_as_xml, format_as_xml_with_options, XmlFormatError, XmlFormatOptions,
302};
303
304// Agent
305pub use serdes_ai_agent::{
306 Agent, AgentBuilder, AgentRun, AgentRunResult, AgentStream, AgentStreamEvent, EndStrategy,
307 ModelConfig, RunContext, RunOptions, StepResult,
308};
309
310// Models
311pub use serdes_ai_models::Model;
312pub use serdes_ai_models::{build_model_extended, build_model_with_config, ExtendedModelConfig};
313
314#[cfg(feature = "openai")]
315#[cfg_attr(docsrs, doc(cfg(feature = "openai")))]
316pub use serdes_ai_models::openai::OpenAIChatModel;
317
318#[cfg(feature = "anthropic")]
319#[cfg_attr(docsrs, doc(cfg(feature = "anthropic")))]
320pub use serdes_ai_models::anthropic::AnthropicModel;
321
322#[cfg(feature = "gemini")]
323#[cfg_attr(docsrs, doc(cfg(feature = "gemini")))]
324pub use serdes_ai_models::GeminiModel;
325
326#[cfg(feature = "groq")]
327#[cfg_attr(docsrs, doc(cfg(feature = "groq")))]
328pub use serdes_ai_models::groq::GroqModel;
329
330#[cfg(feature = "mistral")]
331#[cfg_attr(docsrs, doc(cfg(feature = "mistral")))]
332pub use serdes_ai_models::mistral::MistralModel;
333
334#[cfg(feature = "ollama")]
335#[cfg_attr(docsrs, doc(cfg(feature = "ollama")))]
336pub use serdes_ai_models::ollama::OllamaModel;
337
338#[cfg(feature = "bedrock")]
339#[cfg_attr(docsrs, doc(cfg(feature = "bedrock")))]
340pub use serdes_ai_models::bedrock::BedrockModel;
341
342// Tools
343pub use serdes_ai_tools::{
344 ObjectJsonSchema, SchemaBuilder, Tool, ToolDefinition, ToolRegistry, ToolResult,
345};
346
347// Toolsets
348pub use serdes_ai_toolsets::{
349 AbstractToolset, ApprovalRequiredToolset, BoxedToolset, CombinedToolset, DynamicToolset,
350 ExternalToolset, FilteredToolset, FunctionToolset, PrefixedToolset, PreparedToolset,
351 RenamedToolset, ToolsetInfo, ToolsetTool, WrapperToolset,
352};
353
354// Output
355pub use serdes_ai_output::{
356 OutputSchema, StructuredOutputSchema, TextOutputSchema, ValidationResult,
357};
358
359// Streaming
360pub use serdes_ai_streaming::{ResponseDelta, ResponseStream};
361
362// Retries
363pub use serdes_ai_retries::{
364 ExponentialBackoff, FixedDelay, LinearBackoff, RetryConfig, RetryStrategy,
365};
366
367// Direct model access
368pub use direct::{
369 model_request, model_request_stream, model_request_stream_sync, model_request_sync,
370 DirectError, ModelSpec, StreamedResponseSync,
371};
372
373// ============================================================================
374// Optional Type Re-exports
375// ============================================================================
376
377// MCP
378#[cfg(feature = "mcp")]
379#[cfg_attr(docsrs, doc(cfg(feature = "mcp")))]
380pub use serdes_ai_mcp::{McpClient, McpToolset};
381
382// Embeddings
383#[cfg(feature = "embeddings")]
384#[cfg_attr(docsrs, doc(cfg(feature = "embeddings")))]
385pub use serdes_ai_embeddings::{EmbeddingModel, EmbeddingResult};
386
387// Graph
388#[cfg(feature = "graph")]
389#[cfg_attr(docsrs, doc(cfg(feature = "graph")))]
390pub use serdes_ai_graph::{
391 BaseNode, Edge, End, Graph, GraphError, GraphExecutor, GraphResult, GraphRunContext,
392 GraphRunResult, NodeResult,
393};
394
395// Evals
396#[cfg(feature = "evals")]
397#[cfg_attr(docsrs, doc(cfg(feature = "evals")))]
398pub use serdes_ai_evals::{
399 Case, ContainsScorer, Dataset, EvalCase, EvalRunner, EvalSuite, EvaluationReport,
400 EvaluationResult, Evaluator, ExactMatchScorer,
401};
402
403// ============================================================================
404// Prelude Module
405// ============================================================================
406
407/// Convenient prelude for common imports.
408///
409/// Import everything you need with a single use statement:
410///
411/// ```ignore
412/// use serdes_ai::prelude::*;
413/// ```
414pub mod prelude {
415 // Core types
416 pub use crate::core::{ConversationId, Result, RunId, SerdesAiError, ToolCallId};
417
418 // Messages
419 pub use crate::core::{
420 FinishReason, ModelRequest, ModelResponse, ModelSettings, RequestUsage, RunUsage,
421 UsageLimits, UserContent,
422 };
423
424 // Agent
425 pub use crate::agent::{
426 Agent, AgentBuilder, AgentRun, AgentRunResult, AgentStream, AgentStreamEvent, EndStrategy,
427 ModelConfig, RunContext, RunOptions,
428 };
429
430 // Models
431 pub use crate::models::Model;
432
433 #[cfg(feature = "openai")]
434 pub use crate::models::openai::OpenAIChatModel;
435
436 #[cfg(feature = "anthropic")]
437 pub use crate::models::anthropic::AnthropicModel;
438
439 // Tools
440 pub use crate::tools::{Tool, ToolDefinition, ToolRegistry, ToolResult};
441
442 // Toolsets
443 pub use crate::toolsets::{
444 AbstractToolset, BoxedToolset, CombinedToolset, DynamicToolset, FunctionToolset,
445 };
446
447 // Output
448 pub use crate::output::{
449 OutputSchema, StructuredOutputSchema, TextOutputSchema, ValidationResult,
450 };
451
452 // Streaming
453 pub use crate::streaming::{ResponseDelta, ResponseStream};
454
455 // Retries
456 pub use crate::retries::{ExponentialBackoff, RetryConfig, RetryStrategy};
457
458 // Direct model access
459 pub use crate::direct::{model_request, model_request_stream, DirectError, ModelSpec};
460
461 // Format
462 pub use crate::core::{format_as_xml, XmlFormatOptions};
463
464 // Macros
465 #[cfg(feature = "macros")]
466 pub use crate::{tool, OutputSchema as DeriveOutputSchema, Tool as DeriveTool};
467
468 // MCP
469 #[cfg(feature = "mcp")]
470 pub use crate::mcp::{McpClient, McpToolset};
471
472 // Graph
473 #[cfg(feature = "graph")]
474 pub use crate::graph::{
475 BaseNode, End, Graph, GraphError, GraphExecutor, GraphResult, GraphRunContext,
476 GraphRunResult, NodeResult,
477 };
478
479 // Evals
480 #[cfg(feature = "evals")]
481 pub use crate::evals::{EvalCase, EvalRunner, EvalSuite, Evaluator};
482}
483
484// ============================================================================
485// Version Information
486// ============================================================================
487
488/// Returns the current version of serdes-ai.
489pub fn version() -> &'static str {
490 env!("CARGO_PKG_VERSION")
491}
492
493/// Returns version information as a tuple (major, minor, patch).
494pub fn version_tuple() -> (u32, u32, u32) {
495 let version = version();
496 let parts: Vec<&str> = version.split('.').collect();
497 (
498 parts.first().and_then(|s| s.parse().ok()).unwrap_or(0),
499 parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(0),
500 parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0),
501 )
502}
503
504#[cfg(test)]
505mod tests {
506 use super::*;
507
508 #[test]
509 fn test_version() {
510 assert_eq!(version(), "0.1.3");
511 }
512
513 #[test]
514 fn test_version_tuple() {
515 let (major, minor, patch) = version_tuple();
516 assert_eq!(major, 0);
517 assert_eq!(minor, 1);
518 assert_eq!(patch, 3);
519 }
520
521 #[test]
522 fn test_prelude_imports() {
523 // Just verify these types exist and are accessible
524 let _: fn() -> &'static str = crate::version;
525 }
526}