Agent Development Kit (RUST)
An open-source, code-first Rust framework for building, evaluating, and deploying sophisticated AI agents with flexibility and control.
Agent Development Kit (ADK) is a flexible, modular framework that applies software-engineering discipline to AI-agent construction. adk-rs is a Rust port of the Google's ADK Python implementation, aimed at teams that want low overhead, predictable latency, and the safety guarantees of the Rust toolchain. Like its Python counterpart, ADK is model-agnostic, deployment-agnostic, and integrates cleanly alongside other frameworks.
✨ Key Features
- First-class providers — Gemini (REST + SSE), Anthropic Claude (Messages API + SSE), and an OpenAI-compatible client that also serves Azure OpenAI, Ollama, and Groq via base-URL override.
- Composable agent primitives —
LlmAgent,SequentialAgent,ParallelAgent, andLoopAgent, all driven by a unified event stream overtokio. - Ergonomic tools — annotate any async function with
#[adk_rs::tool]; the macro derives the JSON schema, theFunctionDeclaration, and aToolimpl. Manual implementations remain available as an escape hatch. - Pluggable services — session, memory, artifact, and credential traits with in-memory, filesystem, SQLite, and PostgreSQL backends out of the box.
- MCP toolset — connect to any Model Context Protocol server over stdio.
- Production telemetry —
tracingintegration with optional OpenTelemetry OTLP export. - Evaluation framework — replay JSON eval sets (compatible with the Python ADK format) and score with trajectory and LLM-judge metrics.
- Dev server + CLI scaffolding — an
axum-based HTTP/SSE server and a library-style CLI that you embed in your own binary.
🚀 Installation
adk-rs ships as a single crate with cargo features. Opt in to the providers, storage backends, and subsystems you need:
[]
= { = "0.1", = ["gemini", "macros"] }
= { = "1", = ["macros", "rt-multi-thread"] }
= "0.3"
Available features
| Feature | Pulls in |
|---|---|
gemini / anthropic / openai |
the matching LLM provider |
fs |
filesystem artifact service |
sqlite / postgres |
SQL session backend |
mcp |
Model Context Protocol stdio client |
telemetry |
tracing-subscriber setup (add otel for OpenTelemetry OTLP export) |
eval |
evaluation framework |
server |
axum dev server with SSE |
cli |
embeddable clap-based CLI scaffolding |
macros |
the #[tool] proc-macro |
auth |
OAuth2 / ServiceAccount / API-key / HTTP credential flow |
openapi |
generate tools from an OpenAPI 3.x spec |
code-exec |
local-subprocess code executor |
code-exec-docker |
extra: ephemeral Docker container per call (docker on $PATH) |
full |
enables all of the above |
Requires Rust 1.85+ (edition 2024).
Provider credentials
Each provider reads its API key from the environment:
| Provider | Variable |
|---|---|
| Gemini | GOOGLE_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
| OpenAI-compatible | OPENAI_API_KEY (plus optional OPENAI_BASE_URL) |
🏁 Quick start
Define a single agent and stream its events to stdout:
use LlmAgent;
use Gemini;
use Runner;
use InMemorySessionService;
use StreamExt;
use Arc;
async
🤝 Multi-agent composition
Agents nest via the same BaseAgent trait. A coordinator can delegate to specialised children, with the runner choosing between them based on each agent's description:
use LlmAgent;
use Arc;
let greeter = new;
let task_executor = new;
let coordinator = builder
.model
.description
.sub_agent
.sub_agent
.build?;
SequentialAgent, ParallelAgent, and LoopAgent provide explicit orchestration when LLM-driven delegation is not appropriate.
🔐 Authenticated tools (feature = "auth")
adk-rs ships full Python ADK parity for the credential lifecycle: OAuth 2.0 (authorization-code + PKCE, client-credentials, refresh-token), Service Account JWTs (Google-style RS256), API keys, and HTTP basic/bearer. When a tool declares auth_config(), the runner resolves the credential via CredentialManager before dispatch and injects it into ToolContext::auth_credential. If the underlying flow requires interactive consent (authorization-code), the agent emits a synthetic adk_request_credential function-call response and pauses; the caller resubmits the exchanged credential on the next turn.
use ;
let cfg = new.with_raw;
🌐 OpenAPI tool generator (feature = "openapi")
Point OpenAPIToolset at an OpenAPI 3.x spec and get one tool per operation. Security schemes from the spec map to AuthConfig automatically:
use AuthCredential;
use OpenAPIToolset;
let tools = from_path?
.with_credential
.into_tools;
let agent = builder
.model
.tools
.build?;
🐍 Code execution (feature = "code-exec")
Attach a CodeExecutor to an LlmAgent and the agent will run any ExecutableCode parts the model emits, feeding CodeExecutionResult back on the next turn.
use LocalCodeExecutor;
use Arc;
let agent = builder
.model
.code_executor // python3 on $PATH
.build?;
Two executors ship in the box:
LocalCodeExecutor— spawns a child interpreter viatokio::processwith a configurable timeout. Subprocess isolation only; not a security boundary.ContainerCodeExecutor(feature = "code-exec-docker") — shells out todocker run --rm --network=none --read-only ...for a fresh ephemeral container per call. Requires thedockerCLI.
🛠 Defining a tool
Add #[tool] to any async function. The macro derives a JSON schema from the arguments struct and returns a constructor for an Arc<dyn Tool> that can be handed to LlmAgent::builder().tool(...).
use tool;
use JsonSchema;
use ;
/// Look up the current weather in `args.city`.
async
Attach it with .tool(get_weather()) on the agent builder.
💻 Embedding the CLI
Unlike the Python CLI, Rust agents are statically linked. Build your own binary on top of adk_rs::cli::App:
use Arc;
This gives you four subcommands out of the box:
🌐 Dev web server
adk-rs-server exposes the runner over HTTP and Server-Sent Events for local testing and integration with web frontends. The web subcommand above starts it; for embedding directly, see adk-rs-server.
📊 Evaluating agents
The eval framework loads eval-set JSON files compatible with the Python ADK format, replays them through any BaseAgent, and scores with trajectory and response-match metrics. From the CLI:
Programmatically:
let bytes = read.await?;
let set: EvalSet = from_slice?;
let runner = new;
let report = runner.run_set.await?;
📦 Module layout
adk-rs is a single crate organised by responsibility. Heavy dependencies (sqlx, axum, reqwest, OpenTelemetry, etc.) sit behind cargo features.
| Module | Feature gate | Responsibility |
|---|---|---|
error |
always on | Error / Result and error codes. |
genai_types |
always on | Wire-neutral data: Content, Part, Schema, FunctionCall, GenerateContentConfig. |
core |
always on | Domain primitives: Event, Session, State, LlmRequest/Response, InvocationContext, service traits. |
services::mem |
always on | In-memory session, memory, artifact, and credential services. |
services::fs |
fs |
Filesystem artifact service. |
services::sql |
sqlite / postgres |
SQL SessionService over sqlx. |
providers::gemini |
gemini |
Gemini REST + SSE provider. |
providers::anthropic |
anthropic |
Anthropic Messages API + SSE provider. |
providers::openai |
openai |
OpenAI-compatible provider (Azure / Ollama / Groq via base-URL). |
tools |
always on | Tool trait, FunctionTool, built-ins, load_artifacts, load_memory, get_user_choice, agent_tool, LongRunningFunctionTool. |
tools::openapi |
openapi |
OpenAPIToolset — generate RestApiTools from an OpenAPI 3.x spec. |
agents |
always on | BaseAgent, LlmAgent, SequentialAgent, ParallelAgent, LoopAgent. |
auth |
types always on, flow gated on auth |
AuthCredential, AuthScheme, AuthConfig, CredentialService, CredentialManager, OAuth2 AuthHandler, AuthPreprocessor. |
code_exec |
code-exec |
CodeExecutor trait; LocalCodeExecutor, ContainerCodeExecutor. |
runner |
always on | Orchestration: LLM flow, tool dispatch, agent transfer, plugins. |
mcp |
mcp |
MCP stdio client and McpToolset. |
telemetry |
telemetry (+ otel) |
tracing-subscriber setup with optional OTLP export. |
eval |
eval |
Eval-set IO and metrics. |
server |
server |
axum dev server with SSE. |
cli |
cli |
Embeddable CLI scaffolding. |
The #[tool] proc-macro lives in a sibling crate, adk-rs-macros, which is required by the Rust compiler to be its own crate. Enable it via the macros feature.
🧩 Examples
Runnable demos live under examples/:
gemini_chat— minimal single-agent loop.weather_agent—#[tool]-defined function tool.three_providers— the same prompt against Gemini, Claude, and OpenAI.code_agent— agent that emits shell snippets, runner executes them viaLocalCodeExecutor.
🤝 Contributing
Bug reports, feature requests, and pull requests are welcome. Before submitting:
Please open an issue before starting on substantial changes.
📄 License
Licensed under the Apache License, Version 2.0 — see LICENSE.