Skip to main content

gemini_adk_rs/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![warn(unreachable_pub)]
3#![cfg_attr(not(test), forbid(unsafe_code))]
4#![cfg_attr(test, deny(unsafe_code))]
5#![warn(missing_docs)]
6//! # gemini-adk-rs
7//!
8//! The agent **runtime** for Gemini Live — layer 1 of a three-crate stack.
9//! Below it, [`gemini_genai_rs`] speaks the wire protocol. Above it,
10//! [`gemini-adk-fluent-rs`](https://docs.rs/gemini-adk-fluent-rs) wraps this
11//! crate in the builder API most applications should start from. Come here
12//! when you are building a custom processor, a tool backend, a persistence
13//! layer, or an evaluation harness — or when you want to see what the fluent
14//! builder actually assembles.
15//!
16//! ## What lives here
17//!
18//! | Concern | Start at |
19//! |---------|----------|
20//! | A Live session and its three-lane processor | [`live::LiveSessionBuilder`], [`live::LiveHandle`] |
21//! | Tools the model can call | [`tool::ToolFunction`], [`tool::SimpleTool`], [`tool::TypedTool`], [`tool::ToolDispatcher`] |
22//! | Concurrent typed state with prefix scopes | [`state::State`], [`state::StateKey`] |
23//! | Text agents and combinators | [`text::LlmTextAgent`] and the `*TextAgent` family in [`text`] |
24//! | Declarative conversation phases | [`live::PhaseMachine`], [`live::Phase`] |
25//! | Governed flows enforced while the model speaks | [`flow::Flow`], [`flow::FlowMonitor`] |
26//! | Turn extraction, watchers, temporal patterns | [`live::TurnExtractor`], [`live::watcher`], [`live::temporal`] |
27//! | Session persistence and telemetry | [`live::persistence`], [`live::SessionTelemetry`] |
28//!
29//! Anything behind a Cargo feature is marked on its page — `vertex-ai-sessions`,
30//! `database-sessions`, `templates`, `otel`, and the rest — and the full list is
31//! in this crate's `Cargo.toml`.
32//!
33//! ## The shape of the runtime
34//!
35//! Every Live session runs one **router** and two lanes. The *fast lane* is
36//! synchronous and handles audio, text deltas and transcripts in under a
37//! millisecond per event; the *control lane* is async and runs tool calls,
38//! phase transitions, extractors and watchers. A third, independent
39//! *telemetry lane* observes both. The callback you register decides which
40//! lane it runs on, and the rule is written once at the top of
41//! [`live::callbacks`].
42//!
43//! ## A first taste
44//!
45//! [`state::State`] is the piece every layer shares — tools write it,
46//! guards read it, extractors fill it — so it is the smallest thing worth
47//! showing on its own:
48//!
49//! ```
50//! use gemini_adk_rs::state::{State, StateKey};
51//!
52//! const TURNS: StateKey<u32> = StateKey::new("session:turn_count");
53//!
54//! let state = State::new();
55//! state.set("user:name", "Alice");
56//! state.modify("session:turn_count", 0u32, |n| n + 1);
57//!
58//! assert_eq!(state.get::<String>("user:name").as_deref(), Some("Alice"));
59//! assert_eq!(state.get_key(&TURNS), Some(1));
60//! ```
61//!
62//! For a running session, see the `examples/` directory of the repository or
63//! the `Live::builder()` walkthrough in the fluent crate's documentation.
64
65// The proc macros expand to `::gemini_adk_rs::…`; this makes that path valid
66// inside the crate itself (its own tests and doctests included).
67extern crate self as gemini_adk_rs;
68
69pub mod a2a;
70pub mod agent;
71pub mod agent_config;
72pub mod agent_session;
73pub mod agent_tool;
74pub mod agents;
75pub mod artifacts;
76pub mod auth;
77pub mod clock;
78pub mod code_executors;
79pub mod code_mode;
80pub mod confirmation;
81pub mod context;
82pub mod credentials;
83pub mod decision;
84pub mod error;
85pub mod evaluation;
86pub mod events;
87pub mod expr;
88pub mod extract;
89pub mod flow;
90pub mod frame;
91pub mod instruction;
92pub mod live;
93pub mod llm;
94pub mod llm_agent;
95pub mod memory;
96pub mod middleware;
97pub mod optimization;
98pub mod orchestration;
99pub mod planners;
100pub mod plugin;
101pub mod primitives;
102pub mod processors;
103pub mod router;
104pub mod run_config;
105pub mod runner;
106pub mod session;
107pub mod skills;
108pub mod state;
109pub mod tape;
110pub mod tasks;
111pub mod telemetry;
112pub mod text;
113pub mod text_agent_tool;
114pub mod text_runner;
115pub mod tool;
116pub mod tools;
117pub mod toolset;
118pub mod utils;
119pub mod workflow;
120
121#[cfg(test)]
122pub(crate) mod test_helpers;
123
124// ── Shared closure shapes ─────────────────────────────────────────────────
125// Named once here so every module (phases, workflows, watchers, temporal
126// patterns, callbacks, resolvers) spells the same shape the same way.
127
128/// A boxed, sendable, `'static` future — the return type of every async
129/// callback and hook in the runtime.
130pub type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + 'static>>;
131
132/// A synchronous predicate over shared [`State`]: `true` admits (a phase
133/// transition, a workflow node, a guard).
134pub type StatePredicate = std::sync::Arc<dyn Fn(&State) -> bool + Send + Sync>;
135
136/// An async source of a JSON value — the seam for a tool call, an HTTP fetch,
137/// an MCP request, or a workflow function node. `In` is what the source is
138/// bound from: the whole [`State`] by default, or a pre-bound args
139/// [`Value`](serde_json::Value) for extraction-kit field resolvers.
140///
141/// The `Err(String)` payload is a human-readable reason; it lands in
142/// `{name}:error` state keys and in extraction diagnostics.
143pub type AsyncSourceFn<In = State> = std::sync::Arc<
144    dyn Fn(
145            In,
146        ) -> std::pin::Pin<
147            Box<dyn std::future::Future<Output = Result<serde_json::Value, String>> + Send>,
148        > + Send
149        + Sync,
150>;
151
152// Ergonomic re-exports — existing
153pub use a2a::{A2aMessage, A2aPart, to_a2a_message, to_a2a_parts, to_adk_event, to_genai_parts};
154pub use agent::Agent;
155pub use agent_tool::AgentTool;
156pub use agents::{LoopAgent, ParallelAgent, SequentialAgent};
157#[cfg(feature = "gcs-artifacts")]
158pub use artifacts::GcsArtifactService;
159pub use artifacts::{Artifact, ArtifactService, FileArtifactService, InMemoryArtifactService};
160pub use auth::{
161    AuthConfig, AuthHandler, AuthScheme, CredentialExchanger, CredentialExchangerRegistry,
162    OAuthGrantType,
163};
164pub use code_executors::{
165    BuiltInCodeExecutor, CodeExecutionInput, CodeExecutionResult, CodeExecutor, CodeFile,
166};
167pub use confirmation::{
168    ConfirmationProvider, ConfirmationRequest, StaticConfirmation, ToolConfirmation,
169};
170pub use context::{AgentEvent, CallbackContext, InvocationContext, ToolContext};
171pub use credentials::{
172    AuthCredential, CredentialError, CredentialService, InMemoryCredentialService,
173};
174pub use error::{AgentError, AgentResult, ConfigError, ToolError};
175pub use events::{Event, EventActions, EventType, StructuredEvent};
176pub use extract::{Extract, Recognizer, RecordExtractor};
177pub use flow::{
178    CompiledFlow, Enforcement, Flow, FlowError, FlowErrors, FlowExplanation, FlowMonitor,
179    FlowStack, Guard, Overlay, RepairPolicy, Resume, SharedFlowMonitor, SharedFlowStack,
180    StepAction, ToolSurface, Verdict, Violation, on_enter,
181};
182pub use frame::{ConfirmPolicy, Frame, FrameSpec, SlotRecognizer, SlotSpec, SlotValidator};
183/// Re-exports the `#[tool]`/`#[derive(..)]` macros route their generated code
184/// through, so downstream crates don't need the upstream crate names
185/// (`serde`/`schemars`/`async_trait`/`serde_json`) in scope or under those exact
186/// names. Not public API.
187#[doc(hidden)]
188pub mod __macros {
189    pub use async_trait;
190    pub use schemars;
191    pub use serde;
192    pub use serde_json;
193
194    use crate::error::ToolError;
195
196    /// An infallible `#[tool]` fn's return value, as the tool's JSON output.
197    pub fn tool_output<T: serde::Serialize>(value: T) -> Result<serde_json::Value, ToolError> {
198        serde_json::to_value(value).map_err(|e| {
199            ToolError::ExecutionFailed(format!("the tool's output is not valid JSON: {e}"))
200        })
201    }
202
203    /// A fallible `#[tool]` fn's `Result`, with any error type accepted.
204    pub fn tool_result<T, E>(result: Result<T, E>) -> Result<serde_json::Value, ToolError>
205    where
206        T: serde::Serialize,
207        E: Into<Box<dyn std::error::Error + Send + Sync>>,
208    {
209        result.map_err(ToolError::from_error).and_then(tool_output)
210    }
211}
212
213/// The `#[derive(Extract)]` macro — builds an [`extract::Extract`] record from a
214/// struct's `#[recognize(..)]` fields. Shares the name `Extract` with the
215/// struct (macro vs type namespace), so both can be imported together.
216///
217/// See the [`gemini_adk_macros_rs::Extract`](macro@gemini_adk_macros_rs::Extract)
218/// documentation for details.
219pub use gemini_adk_macros_rs::Extract;
220/// Derive macro that generates a [`frame::Frame`] impl from a struct's
221/// `#[slot(..)]` fields. Shares the name `Frame` with the trait (macro vs type
222/// namespace), so both can be imported together.
223pub use gemini_adk_macros_rs::Frame;
224/// The `#[tool]` attribute macro — turns an `async fn` into a registrable Gemini tool.
225///
226/// See the [`gemini_adk_macros_rs::tool`] documentation for details.
227pub use gemini_adk_macros_rs::tool;
228pub use instruction::inject_session_state;
229pub use live::{
230    EventCallbacks, ExecutionMode, LiveHandle, LiveSessionBuilder, LlmExtractor, PersistenceError,
231    SessionHook, ToolCallSummary, TranscriptBuffer, TranscriptTurn, TurnExtractor,
232};
233pub use llm::{BaseLlm, GeminiLlm, GeminiLlmParams, LlmRegistry, LlmRequest, LlmResponse};
234pub use llm_agent::{LlmAgent, LlmAgentBuilder};
235pub use memory::{InMemoryMemoryService, MemoryEntry, MemoryService};
236pub use middleware::{Middleware, MiddlewareChain};
237pub use orchestration::{AgentMode, Resolver, call_agent, provenance};
238pub use plugin::{Plugin, PluginManager, PluginResult};
239pub use processors::{
240    ContentFilter, InstructionInserter, RequestProcessor, RequestProcessorChain, ResponseProcessor,
241    ResponseProcessorChain,
242};
243pub use router::AgentRegistry;
244pub use run_config::{RunConfig, StreamingMode};
245pub use runner::Runner;
246#[cfg(feature = "database-sessions")]
247pub use session::DatabaseSessionService;
248pub use session::{InMemorySessionService, Session, SessionId, SessionService, db_schema};
249pub use state::{FileJournalSink, JournalSink, MemoryJournalSink};
250pub use state::{PrefixedState, ReadOnlyPrefixedState, StateError};
251pub use state::{SlotEvidence, State, StateMutation, StateMutationOrigin};
252pub use text::{
253    DispatchTextAgent, FallbackTextAgent, FnTextAgent, JoinTextAgent, LlmTextAgent, LoopTextAgent,
254    MapOverTextAgent, ParallelTextAgent, RaceTextAgent, RouteRule, RouteTextAgent,
255    SequentialTextAgent, TapTextAgent, TaskRegistry, TextAgent, TimeoutTextAgent,
256};
257pub use text_agent_tool::TextAgentTool;
258pub use text_runner::{RunEvent, TextRunner};
259pub use tool::{SimpleTool, ToolDispatcher, ToolFunction, ToolPolicy, TypedTool};
260pub use tools::GoogleSearchTool;
261pub use tools::long_running::LongRunningFunctionTool;
262pub use tools::mcp::{McpConnectionParams, McpTool, McpToolset};
263pub use toolset::{StaticToolset, Toolset};
264pub use utils::model_name::{extract_model_name, is_gemini_model, is_gemini2_or_above};
265pub use utils::variant::{GoogleLlmVariant, get_google_llm_variant};
266
267// New re-exports — A2A
268pub use a2a::{AgentCard, AgentSkill, RemoteA2aAgent, RemoteA2aAgentConfig};
269
270// New re-exports — Evaluation
271pub use evaluation::{
272    EvalCase, EvalMetric, EvalResult, EvalSet, Evaluator, Invocation, LlmAsJudge,
273    PerInvocationResult, ResponseEvaluator, TrajectoryEvaluator,
274};
275
276// New re-exports — Planners
277pub use planners::{BuiltInPlanner, PlanReActPlanner, Planner, PlannerError};
278
279// New re-exports — Optimization
280pub use optimization::{
281    AgentOptimizer, EvalSample, OptimizerError, OptimizerResult, Sampler, SimplePromptOptimizer,
282    SimplePromptOptimizerConfig,
283};
284
285// New re-exports — Code Executors
286pub use code_executors::{
287    ContainerCodeExecutor, ContainerCodeExecutorConfig, UnsafeLocalCodeExecutor,
288};
289#[cfg(feature = "vertex-ai-code-executor")]
290pub use code_executors::{VertexAiCodeExecutor, VertexAiCodeExecutorConfig};
291
292// New re-exports — Plugins
293pub use plugin::{ContextFilterPlugin, GlobalInstructionPlugin, ReflectRetryToolPlugin};
294
295// New re-exports — Memory
296pub use memory::{VertexAiMemoryBankConfig, VertexAiMemoryBankService};
297#[cfg(feature = "vertex-ai-rag")]
298pub use memory::{VertexAiRagMemoryConfig, VertexAiRagMemoryService};
299
300// New re-exports — Sessions
301#[cfg(feature = "postgres-sessions")]
302pub use session::{PostgresSessionConfig, PostgresSessionService};
303pub use session::{SqliteSessionConfig, SqliteSessionService};
304#[cfg(feature = "vertex-ai-sessions")]
305pub use session::{VertexAiSessionConfig, VertexAiSessionService};
306
307// New re-exports — Tools
308pub use tools::retrieval::{BaseRetrievalTool, FilesRetrievalTool, RetrievalResult};
309#[cfg(feature = "vertex-ai-rag")]
310pub use tools::retrieval::{VertexAiRagConfig, VertexAiRagRetrievalTool};
311pub use tools::{
312    BashToolPolicy, DiscoveryEngineSearchTool, Example, ExampleTool, ExecuteBashTool, ExitLoopTool,
313    GetUserChoiceTool, LoadMemoryTool, PreloadMemoryTool, TransferToAgentTool, UrlContextTool,
314    VertexAiSearchConfig, VertexAiSearchTool,
315};
316
317// New re-exports — Agent Config
318pub use agent_config::{
319    AgentConfig, AgentConfigError, ToolConfig as AgentToolConfig, discover_agent_configs,
320};
321
322// Wire re-export
323pub use gemini_genai_rs;