v0.3.0
Tool confirmation (HITL) & resumable invocations
- FunctionTool::require_confirmation(true) (plus .with_confirmation_hint(..)) and per-tool ConfirmationPolicy on
McpToolset gate tool calls behind explicit user approval. - Gated calls pause the invocation with an adk_request_confirmation request (wire-compatible with Python ADK's
ToolConfirmation payloads, including actions.requested_tool_confirmations); reply with a FunctionResponse carrying
{"confirmed": true/false} to approve or deny. Denials surface to the model as a rejection result — the tool never runs. - Runner::builder().resumable(true) + Runner::resume(user, session, invocation_id, content, config) resume a paused
invocation in place: SequentialAgent records checkpoints and skips completed steps; LoopAgent suspends on pause.
Approved tools execute exactly once. - A2A tasks that pause now end in input-required (instead of completed), unblocking cross-runtime HITL with Python
google-adk clients.
Context caching & event compaction
- LlmAgent::static_instruction(..) pins a byte-stable system prefix; dynamic instructions ride in the request contents
so the prefix stays cacheable. - Runner::builder().context_cache_config(ContextCacheConfig { ttl_seconds, cache_intervals, min_tokens }) enables
explicit Gemini cachedContents management: create-once, reuse across calls, TTL/use-count refresh, and graceful
fallback (with cache invalidation) if the server rejects an entry. Responses carry cache_metadata (cache_name,
cache_hit). - Runner::builder().compaction(EventsCompactionConfig::new(model)) summarizes old events after every N invocations via
LlmEventSummarizer (pluggable EventSummarizer trait). History assembly transparently swaps compacted ranges for the
summary.
Structured output & instruction templating
- LlmAgent::output_key("answer") writes the final response into session state (the backbone of Sequential pipelines);
with output_schema(..) the model is forced to JSON and the parsed value is stored. - include_contents(IncludeContents::None) for stateless pipeline steps.
- Python-compatible {state_key} templating in static instructions: {key}, {key?} (optional),
{app:key}/{user:key}/{temp:key}, and {artifact.name}.
adk api_server-compatible dev server (adk-web UI support)
- The axum server now implements Python ADK's wire contract: camelCase event/session JSON, GET /list-apps, /health,
/version, full session CRUD under /apps/{app}/users/{user}/sessions (409 on duplicate, PATCH state-delta, {"detail":
...} errors), POST /run (bare event array) and POST /run_sse (data: framing, artifact-split quirk included),
artifact and memory endpoints, and graceful trace/eval stubs. - AgentRunRequest accepts both camelCase and snake_case, supports stateDelta, and invocationId for resume.
- CORS via AppState::with_allow_origins(..) / adk web --allow-origins http://localhost:4200 — point adk-web's
backendUrl at adk-rs and go.
🐛 Fixes
- Resumed tool calls are now replayed exactly once, by the agent that owns them. Previously the resume bookkeeping was
invocation-global and never consumed, so in multi-agent pipelines a user-confirmed (or OAuth-resumed) tool could
execute twice downstream, or kill the pipeline with an unknown-tool error.