1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
//! Rust agent orchestration library for tool-using, long-horizon, traceable AI systems.
//!
//! Appam is designed for agent workloads where the hard parts are operational:
//! repeated tool use across multiple turns, streaming UX, session persistence,
//! trace capture, and provider portability. The shared runtime stays provider
//! agnostic while the provider modules own wire-format quirks, auth, retry, and
//! streaming details.
//!
//! # What Appam Gives You
//!
//! - Rust-first agent construction through [`AgentBuilder`], [`RuntimeAgent`],
//! and the shortcut constructors in [`agent::quick`]
//! - typed and untyped tool definitions via [`Tool`], [`AsyncTool`],
//! [`ToolRegistry`], [`tool`], and [`Schema`]
//! - streaming-first execution through [`agent::streaming::StreamEvent`],
//! [`agent::streaming_builder::StreamBuilder`], and built-in consumers
//! - durable session history through [`SessionHistory`]
//! - portable LLM routing across Anthropic, OpenAI, OpenAI Codex, OpenRouter,
//! Vertex, Azure, and Bedrock via [`LlmProvider`] and [`DynamicLlmClient`]
//!
//! # Recommended Entry Points
//!
//! Use [`Agent::quick`](crate::agent::quick::Agent::quick) when you want the
//! smallest working setup:
//!
//! ```no_run
//! use appam::prelude::*;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let agent = Agent::quick(
//! "anthropic/claude-sonnet-4-5",
//! "You are a concise Rust assistant.",
//! vec![],
//! )?;
//!
//! agent
//! .stream("Explain ownership in Rust in three sentences.")
//! .on_content(|text| print!("{text}"))
//! .run()
//! .await?;
//!
//! println!();
//! Ok(())
//! }
//! ```
//!
//! Use [`AgentBuilder`] when you need explicit runtime control:
//!
//! ```no_run
//! use appam::prelude::*;
//! use std::sync::Arc;
//! # use serde_json::{json, Value};
//! # struct EchoTool;
//! # impl Tool for EchoTool {
//! # fn name(&self) -> &str { "echo" }
//! # fn spec(&self) -> Result<ToolSpec> {
//! # Ok(serde_json::from_value(json!({
//! # "type": "function",
//! # "function": {
//! # "name": "echo",
//! # "description": "Echo a message",
//! # "parameters": {
//! # "type": "object",
//! # "properties": {
//! # "message": {"type": "string"}
//! # },
//! # "required": ["message"]
//! # }
//! # }
//! # }))?)
//! # }
//! # fn execute(&self, args: Value) -> Result<Value> {
//! # Ok(json!({ "output": args["message"].clone() }))
//! # }
//! # }
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let agent = AgentBuilder::new("assistant")
//! .provider(LlmProvider::OpenAI)
//! .model("openai/gpt-5.4")
//! .system_prompt("You are a careful assistant. Use tools before guessing.")
//! .with_tool(Arc::new(EchoTool))
//! .enable_history()
//! .build()?;
//!
//! agent.run("Say hello via the echo tool.").await?;
//! Ok(())
//! }
//! ```
//!
//! Use [`TomlAgent`] when configuration lives on disk and needs to be extended
//! with Rust tools at runtime:
//!
//! ```no_run
//! use appam::prelude::*;
//! use std::sync::Arc;
//! # use serde_json::{json, Value};
//! # struct CustomTool;
//! # impl Tool for CustomTool {
//! # fn name(&self) -> &str { "custom" }
//! # fn spec(&self) -> Result<ToolSpec> {
//! # Ok(serde_json::from_value(json!({
//! # "type": "function",
//! # "function": {
//! # "name": "custom",
//! # "description": "Example custom tool",
//! # "parameters": {"type": "object", "properties": {}}
//! # }
//! # }))?)
//! # }
//! # fn execute(&self, _: Value) -> Result<Value> { Ok(json!({"ok": true})) }
//! # }
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let agent = TomlAgent::from_file("agent.toml")?
//! .with_additional_tool(Arc::new(CustomTool));
//!
//! agent.run("Use the custom tool if it helps.").await?;
//! Ok(())
//! }
//! ```
//!
//! # Architecture
//!
//! Appam keeps the crate split along subsystem boundaries:
//!
//! - [`agent`] owns runtime orchestration, continuation logic, stream events,
//! and session history
//! - [`tools`] owns schemas, execution traits, managed state, and runtime lookup
//! - [`llm`] owns provider-neutral message types plus provider-specific clients
//! - [`config`] owns global configuration, env overrides, and builder APIs
//! - [`logging`] owns tracing setup and persisted session logs
//!
//! # Security and Operational Notes
//!
//! - Tool calls are model output and must be treated as untrusted input.
//! - Managed state access fails closed when state was not registered.
//! - The legacy web API surface remains intentionally disabled; the trace
//! visualizer helpers in [`web`] remain available.
//! - Provider-specific secrets are never meant to be logged or embedded in
//! trace artifacts.
//!
//! # Docs.rs Navigation
//!
//! If you are new to the crate, the most useful pages are usually:
//!
//! - [`prelude`] for the ergonomic import surface
//! - [`AgentBuilder`] and [`RuntimeAgent`] for programmatic agents
//! - [`Tool`] and [`AsyncTool`] for tool authoring
//! - [`tool`] and [`Schema`] for macro-driven tool definitions
//! - [`StreamBuilder`](crate::agent::streaming_builder::StreamBuilder) for
//! closure-based streaming
//! - [`SessionHistory`] for durable sessions
// TODO: Implement these modules in future phases
// pub mod interface;
// Re-export commonly used types for convenience
pub use SessionHistory;
pub use ;
pub use ;
pub use ;
pub use ;
// Re-export procedural macros
pub use ;
pub use async_trait;
/// Convenient import surface for the most common Appam workflows.
///
/// The prelude intentionally favors the Rust-first SDK path: agent builders,
/// quick constructors, streaming types, tool traits, macro helpers, and the
/// most common `anyhow`, `serde`, and `tokio` re-exports used by examples.
///
/// Import it when you want to prototype quickly or write concise examples:
///
/// ```
/// use appam::prelude::*;
/// ```
///
/// For library code that exposes Appam types in its own public API, prefer
/// importing only the specific items you need so your dependency surface stays
/// explicit.
///
/// # Examples
///
/// ```no_run
/// use appam::prelude::*;
/// use anyhow::Result;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// // Use Agent::quick() for one-liner creation
/// let agent = Agent::quick(
/// "anthropic/claude-sonnet-4-5",
/// "You are helpful.",
/// vec![],
/// )?;
///
/// // Use closure-based streaming
/// agent
/// .stream("Hello")
/// .on_content(|text| print!("{}", text))
/// .run()
/// .await?;
///
/// Ok(())
/// }
/// ```