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 confirmation;
80pub mod context;
81pub mod credentials;
82pub mod error;
83pub mod evaluation;
84pub mod events;
85pub mod expr;
86pub mod extract;
87pub mod flow;
88pub mod frame;
89pub mod instruction;
90pub mod live;
91pub mod llm;
92pub mod llm_agent;
93pub mod memory;
94pub mod middleware;
95pub mod optimization;
96pub mod orchestration;
97pub mod planners;
98pub mod plugin;
99pub mod primitives;
100pub mod processors;
101pub mod router;
102pub mod run_config;
103pub mod runner;
104pub mod session;
105pub mod skills;
106pub mod state;
107pub mod tape;
108pub mod telemetry;
109pub mod text;
110pub mod text_agent_tool;
111pub mod text_runner;
112pub mod tool;
113pub mod tools;
114pub mod toolset;
115pub mod utils;
116pub mod workflow;
117
118#[cfg(test)]
119pub(crate) mod test_helpers;
120
121// ── Shared closure shapes ─────────────────────────────────────────────────
122// Named once here so every module (phases, workflows, watchers, temporal
123// patterns, callbacks, resolvers) spells the same shape the same way.
124
125/// A boxed, sendable, `'static` future — the return type of every async
126/// callback and hook in the runtime.
127pub type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + 'static>>;
128
129/// A synchronous predicate over shared [`State`]: `true` admits (a phase
130/// transition, a workflow node, a guard).
131pub type StatePredicate = std::sync::Arc<dyn Fn(&State) -> bool + Send + Sync>;
132
133/// An async source of a JSON value — the seam for a tool call, an HTTP fetch,
134/// an MCP request, or a workflow function node. `In` is what the source is
135/// bound from: the whole [`State`] by default, or a pre-bound args
136/// [`Value`](serde_json::Value) for extraction-kit field resolvers.
137///
138/// The `Err(String)` payload is a human-readable reason; it lands in
139/// `{name}:error` state keys and in extraction diagnostics.
140pub type AsyncSourceFn<In = State> = std::sync::Arc<
141    dyn Fn(
142            In,
143        ) -> std::pin::Pin<
144            Box<dyn std::future::Future<Output = Result<serde_json::Value, String>> + Send>,
145        > + Send
146        + Sync,
147>;
148
149// Ergonomic re-exports — existing
150pub use a2a::{A2aMessage, A2aPart, to_a2a_message, to_a2a_parts, to_adk_event, to_genai_parts};
151pub use agent::Agent;
152pub use agent_tool::AgentTool;
153pub use agents::{LoopAgent, ParallelAgent, SequentialAgent};
154#[cfg(feature = "gcs-artifacts")]
155pub use artifacts::GcsArtifactService;
156pub use artifacts::{Artifact, ArtifactService, FileArtifactService, InMemoryArtifactService};
157pub use auth::{
158    AuthConfig, AuthHandler, AuthScheme, CredentialExchanger, CredentialExchangerRegistry,
159    OAuthGrantType,
160};
161pub use code_executors::{
162    BuiltInCodeExecutor, CodeExecutionInput, CodeExecutionResult, CodeExecutor, CodeFile,
163};
164pub use confirmation::{
165    ConfirmationProvider, ConfirmationRequest, StaticConfirmation, ToolConfirmation,
166};
167pub use context::{AgentEvent, CallbackContext, InvocationContext, ToolContext};
168pub use credentials::{
169    AuthCredential, CredentialError, CredentialService, InMemoryCredentialService,
170};
171pub use error::{AgentError, AgentResult, ConfigError, ToolError};
172pub use events::{Event, EventActions, EventType, StructuredEvent};
173pub use extract::{Extract, Recognizer, RecordExtractor};
174pub use flow::{
175    CompiledFlow, Enforcement, Flow, FlowError, FlowErrors, FlowExplanation, FlowMonitor,
176    FlowStack, Guard, Overlay, RepairPolicy, Resume, SharedFlowMonitor, SharedFlowStack,
177    StepAction, ToolSurface, Verdict, Violation, on_enter,
178};
179pub use frame::{ConfirmPolicy, Frame, FrameSpec, SlotRecognizer, SlotSpec, SlotValidator};
180/// Re-exports the `#[tool]`/`#[derive(..)]` macros route their generated code
181/// through, so downstream crates don't need the upstream crate names
182/// (`serde`/`schemars`/`async_trait`/`serde_json`) in scope or under those exact
183/// names. Not public API.
184#[doc(hidden)]
185pub mod __macros {
186    pub use async_trait;
187    pub use schemars;
188    pub use serde;
189    pub use serde_json;
190
191    use crate::error::ToolError;
192
193    /// An infallible `#[tool]` fn's return value, as the tool's JSON output.
194    pub fn tool_output<T: serde::Serialize>(value: T) -> Result<serde_json::Value, ToolError> {
195        serde_json::to_value(value).map_err(|e| {
196            ToolError::ExecutionFailed(format!("the tool's output is not valid JSON: {e}"))
197        })
198    }
199
200    /// A fallible `#[tool]` fn's `Result`, with any error type accepted.
201    pub fn tool_result<T, E>(result: Result<T, E>) -> Result<serde_json::Value, ToolError>
202    where
203        T: serde::Serialize,
204        E: Into<Box<dyn std::error::Error + Send + Sync>>,
205    {
206        result.map_err(ToolError::from_error).and_then(tool_output)
207    }
208}
209
210/// The `#[derive(Extract)]` macro — builds an [`extract::Extract`] record from a
211/// struct's `#[recognize(..)]` fields. Shares the name `Extract` with the
212/// struct (macro vs type namespace), so both can be imported together.
213///
214/// See the [`gemini_adk_macros_rs::Extract`](macro@gemini_adk_macros_rs::Extract)
215/// documentation for details.
216pub use gemini_adk_macros_rs::Extract;
217/// Derive macro that generates a [`frame::Frame`] impl from a struct's
218/// `#[slot(..)]` fields. Shares the name `Frame` with the trait (macro vs type
219/// namespace), so both can be imported together.
220pub use gemini_adk_macros_rs::Frame;
221/// The `#[tool]` attribute macro — turns an `async fn` into a registrable Gemini tool.
222///
223/// See the [`gemini_adk_macros_rs::tool`] documentation for details.
224pub use gemini_adk_macros_rs::tool;
225pub use instruction::inject_session_state;
226pub use live::{
227    EventCallbacks, ExecutionMode, LiveHandle, LiveSessionBuilder, LlmExtractor, PersistenceError,
228    SessionHook, ToolCallSummary, TranscriptBuffer, TranscriptTurn, TurnExtractor,
229};
230pub use llm::{BaseLlm, GeminiLlm, GeminiLlmParams, LlmRegistry, LlmRequest, LlmResponse};
231pub use llm_agent::{LlmAgent, LlmAgentBuilder};
232pub use memory::{InMemoryMemoryService, MemoryEntry, MemoryService};
233pub use middleware::{Middleware, MiddlewareChain};
234pub use orchestration::{AgentMode, Resolver, call_agent, provenance};
235pub use plugin::{Plugin, PluginManager, PluginResult};
236pub use processors::{
237    ContentFilter, InstructionInserter, RequestProcessor, RequestProcessorChain, ResponseProcessor,
238    ResponseProcessorChain,
239};
240pub use router::AgentRegistry;
241pub use run_config::{RunConfig, StreamingMode};
242pub use runner::Runner;
243#[cfg(feature = "database-sessions")]
244pub use session::DatabaseSessionService;
245pub use session::{InMemorySessionService, Session, SessionId, SessionService, db_schema};
246pub use state::{FileJournalSink, JournalSink, MemoryJournalSink};
247pub use state::{PrefixedState, ReadOnlyPrefixedState, StateError};
248pub use state::{SlotEvidence, State, StateMutation, StateMutationOrigin};
249pub use text::{
250    DispatchTextAgent, FallbackTextAgent, FnTextAgent, JoinTextAgent, LlmTextAgent, LoopTextAgent,
251    MapOverTextAgent, ParallelTextAgent, RaceTextAgent, RouteRule, RouteTextAgent,
252    SequentialTextAgent, TapTextAgent, TaskRegistry, TextAgent, TimeoutTextAgent,
253};
254pub use text_agent_tool::TextAgentTool;
255pub use text_runner::{RunEvent, TextRunner};
256pub use tool::{SimpleTool, ToolDispatcher, ToolFunction, ToolPolicy, TypedTool};
257pub use tools::GoogleSearchTool;
258pub use tools::long_running::LongRunningFunctionTool;
259pub use tools::mcp::{McpConnectionParams, McpTool, McpToolset};
260pub use toolset::{StaticToolset, Toolset};
261pub use utils::model_name::{extract_model_name, is_gemini_model, is_gemini2_or_above};
262pub use utils::variant::{GoogleLlmVariant, get_google_llm_variant};
263
264// New re-exports — A2A
265pub use a2a::{AgentCard, AgentSkill, RemoteA2aAgent, RemoteA2aAgentConfig};
266
267// New re-exports — Evaluation
268pub use evaluation::{
269    EvalCase, EvalMetric, EvalResult, EvalSet, Evaluator, Invocation, LlmAsJudge,
270    PerInvocationResult, ResponseEvaluator, TrajectoryEvaluator,
271};
272
273// New re-exports — Planners
274pub use planners::{BuiltInPlanner, PlanReActPlanner, Planner, PlannerError};
275
276// New re-exports — Optimization
277pub use optimization::{
278    AgentOptimizer, EvalSample, OptimizerError, OptimizerResult, Sampler, SimplePromptOptimizer,
279    SimplePromptOptimizerConfig,
280};
281
282// New re-exports — Code Executors
283pub use code_executors::{
284    ContainerCodeExecutor, ContainerCodeExecutorConfig, UnsafeLocalCodeExecutor,
285};
286#[cfg(feature = "vertex-ai-code-executor")]
287pub use code_executors::{VertexAiCodeExecutor, VertexAiCodeExecutorConfig};
288
289// New re-exports — Plugins
290pub use plugin::{ContextFilterPlugin, GlobalInstructionPlugin, ReflectRetryToolPlugin};
291
292// New re-exports — Memory
293pub use memory::{VertexAiMemoryBankConfig, VertexAiMemoryBankService};
294#[cfg(feature = "vertex-ai-rag")]
295pub use memory::{VertexAiRagMemoryConfig, VertexAiRagMemoryService};
296
297// New re-exports — Sessions
298#[cfg(feature = "postgres-sessions")]
299pub use session::{PostgresSessionConfig, PostgresSessionService};
300pub use session::{SqliteSessionConfig, SqliteSessionService};
301#[cfg(feature = "vertex-ai-sessions")]
302pub use session::{VertexAiSessionConfig, VertexAiSessionService};
303
304// New re-exports — Tools
305pub use tools::retrieval::{BaseRetrievalTool, FilesRetrievalTool, RetrievalResult};
306#[cfg(feature = "vertex-ai-rag")]
307pub use tools::retrieval::{VertexAiRagConfig, VertexAiRagRetrievalTool};
308pub use tools::{
309    BashToolPolicy, DiscoveryEngineSearchTool, Example, ExampleTool, ExecuteBashTool, ExitLoopTool,
310    GetUserChoiceTool, LoadMemoryTool, PreloadMemoryTool, TransferToAgentTool, UrlContextTool,
311    VertexAiSearchConfig, VertexAiSearchTool,
312};
313
314// New re-exports — Agent Config
315pub use agent_config::{
316    AgentConfig, AgentConfigError, ToolConfig as AgentToolConfig, discover_agent_configs,
317};
318
319// Wire re-export
320pub use gemini_genai_rs;