agtrace_sdk/lib.rs
1//! agtrace-sdk: The Observability Platform for AI Agents.
2//!
3//! **Note**: README.md is auto-generated from this rustdoc using `cargo-rdme`.
4//! To update: `cargo rdme --workspace-project agtrace-sdk`
5//!
6//! # Overview
7//!
8//! `agtrace-sdk` provides a high-level, stable API for building observability
9//! tools on top of agtrace. It abstracts away the internal complexity of
10//! providers, indexing, and runtime orchestration, exposing only the essential
11//! primitives for monitoring and analyzing AI agent behavior.
12//!
13//! # Quickstart
14//!
15//! ```no_run
16//! use agtrace_sdk::{Client, Lens, types::SessionFilter};
17//!
18//! # #[tokio::main]
19//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
20//! // Connect to the local workspace (uses XDG data directory)
21//! let client = Client::connect_default().await?;
22//!
23//! // List sessions and analyze the most recent one
24//! let sessions = client.sessions().list(SessionFilter::all())?;
25//! if let Some(summary) = sessions.first() {
26//! let handle = client.sessions().get(&summary.id)?;
27//! let report = handle.analyze()?
28//! .through(Lens::Failures)
29//! .report()?;
30//! println!("Health: {}/100", report.score);
31//! }
32//! # Ok(())
33//! # }
34//! ```
35//!
36//! For complete examples, see the [`examples/`](https://github.com/lanegrid/agtrace/tree/main/crates/agtrace-sdk/examples) directory.
37//!
38//! # Architecture
39//!
40//! This SDK acts as a facade over:
41//! - `agtrace-types`: Core domain models (AgentEvent, etc.)
42//! - `agtrace-providers`: Multi-provider log normalization
43//! - `agtrace-engine`: Session analysis and diagnostics
44//! - `agtrace-index`: Metadata storage and querying
45//! - `agtrace-runtime`: Internal orchestration layer
46//!
47//! # Usage Patterns
48//!
49//! ## Real-time Monitoring
50//!
51//! ```no_run
52//! use agtrace_sdk::Client;
53//! use futures::stream::StreamExt;
54//!
55//! # #[tokio::main]
56//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
57//! let client = Client::connect_default().await?;
58//! let mut stream = client.watch().all_providers().start()?;
59//! let mut count = 0;
60//! while let Some(event) = stream.next().await {
61//! println!("New event: {:?}", event);
62//! count += 1;
63//! if count >= 10 { break; }
64//! }
65//! # Ok(())
66//! # }
67//! ```
68//!
69//! ## Session Analysis
70//!
71//! ```no_run
72//! use agtrace_sdk::{Client, Lens, types::SessionFilter};
73//!
74//! # #[tokio::main]
75//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
76//! let client = Client::connect_default().await?;
77//! let sessions = client.sessions().list(SessionFilter::all())?;
78//! if let Some(summary) = sessions.first() {
79//! let handle = client.sessions().get(&summary.id)?;
80//! let report = handle.analyze()?
81//! .through(Lens::Failures)
82//! .through(Lens::Loops)
83//! .report()?;
84//!
85//! println!("Health score: {}", report.score);
86//! for insight in &report.insights {
87//! println!("Turn {}: {:?} - {}",
88//! insight.turn_index + 1,
89//! insight.severity,
90//! insight.message);
91//! }
92//! }
93//! # Ok(())
94//! # }
95//! ```
96//!
97//! ## Standalone API (for testing/simulations)
98//!
99//! ```no_run
100//! use agtrace_sdk::{SessionHandle, types::AgentEvent};
101//!
102//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
103//! // When you have raw events without Client (e.g., testing, simulations)
104//! let events: Vec<AgentEvent> = vec![/* ... */];
105//! let handle = SessionHandle::from_events(events);
106//!
107//! let session = handle.assemble()?;
108//! println!("Session has {} turns", session.turns.len());
109//! # Ok(())
110//! # }
111//! ```
112
113pub mod analysis;
114pub mod client;
115pub mod error;
116pub mod types;
117pub mod watch;
118
119// Re-export core domain types for convenience
120pub use agtrace_engine::AgentSession;
121
122// Public facade
123pub use analysis::{AnalysisReport, Insight, Lens, Severity};
124pub use client::{
125 Client, ClientBuilder, InsightClient, ProjectClient, SessionClient, SessionHandle,
126 SystemClient, WatchClient,
127};
128pub use error::{Error, Result};
129pub use types::{
130 AgentEvent, EventPayload, ExportStrategy, SessionFilter, SessionSummary, StreamId, ToolKind,
131};
132pub use watch::{LiveStream, WatchBuilder};
133
134// ============================================================================
135// Low-level Utilities (Power User API)
136// ============================================================================
137
138/// Utility functions for building custom observability tools.
139///
140/// These are stateless, pure functions that power the CLI and can be used
141/// by external tool developers to replicate or extend agtrace functionality.
142///
143/// # When to use this module
144///
145/// - Building custom TUIs or dashboards that need event stream processing
146/// - Writing tests that need to compute project hashes
147/// - Implementing custom project detection logic
148///
149/// # Examples
150///
151/// ## Event Processing
152///
153/// ```no_run
154/// use agtrace_sdk::{Client, utils};
155/// use agtrace_sdk::watch::{StreamEvent, WorkspaceEvent};
156/// use futures::stream::StreamExt;
157///
158/// # #[tokio::main]
159/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
160/// let client = Client::connect_default().await?;
161/// let mut stream = client.watch().all_providers().start()?;
162///
163/// let mut count = 0;
164/// while let Some(workspace_event) = stream.next().await {
165/// if let WorkspaceEvent::Stream(StreamEvent::Events { events, .. }) = workspace_event {
166/// for event in events {
167/// let updates = utils::extract_state_updates(&event);
168/// if updates.is_new_turn {
169/// println!("New turn started!");
170/// }
171/// if let Some(usage) = updates.usage {
172/// println!("Token usage: {:?}", usage);
173/// }
174/// }
175/// }
176/// count += 1;
177/// if count >= 10 { break; }
178/// }
179/// # Ok(())
180/// # }
181/// ```
182///
183/// ## Project Hash Computation
184///
185/// ```no_run
186/// use agtrace_sdk::utils;
187///
188/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
189/// let project_root = utils::discover_project_root(None)?;
190/// let hash = utils::project_hash_from_root(&project_root.to_string_lossy());
191/// println!("Project hash: {}", hash);
192/// # Ok(())
193/// # }
194/// ```
195pub mod utils {
196 use crate::types::TokenLimits;
197 use agtrace_providers::ProviderModelLimitResolver;
198
199 // Event processing utilities
200 pub use agtrace_engine::extract_state_updates;
201
202 // Project management utilities
203 pub use agtrace_core::{
204 discover_project_root, project_hash_from_root, resolve_effective_project_hash,
205 resolve_workspace_path,
206 };
207
208 /// Create a TokenLimits instance with the default provider resolver.
209 ///
210 /// This is a convenience function for creating TokenLimits without needing
211 /// to manually instantiate the ProviderModelLimitResolver.
212 ///
213 /// # Example
214 ///
215 /// ```no_run
216 /// use agtrace_sdk::utils;
217 ///
218 /// let token_limits = utils::default_token_limits();
219 /// let limit = token_limits.get_limit("claude-3-5-sonnet");
220 /// ```
221 pub fn default_token_limits() -> TokenLimits<ProviderModelLimitResolver> {
222 TokenLimits::new(ProviderModelLimitResolver)
223 }
224}