Skip to content

v0.3.0

Choose a tag to compare

@skundu42 skundu42 released this 10 Jun 05:40
· 6 commits to main since this release

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.