Highlights
- Token-level streaming — RunConfig { streaming_mode: StreamingMode::Sse } now streams real token deltas through the
agent loop as partial events, aggregated into one persisted final event. Previously the setting was accepted but
ignored. - Lifecycle callbacks are live — all eight hooks (before/after_agent, before/after_model, on_model_error,
before/after_tool, on_tool_error) are registrable on LlmAgentBuilder and fire in the run loop: rewrite requests,
short-circuit calls, recover from errors. - Agent transfer that just works — declaring .sub_agent(...) now auto-registers the transfer_to_agent tool and
advertises sub-agents to the model. Transfer resolves through the invocation's agent-tree root, so siblings and
ancestors are reachable. A hallucinated agent name returns a recoverable tool error instead of aborting the run. - Anthropic extended thinking — thinking_config.thinking_budget maps to the Messages API thinking parameter; thinking
blocks round-trip with their cryptographic signature, redacted_thinking payloads are preserved, and streaming handles
thinking_delta/signature_delta. Gemini thoughtSignature (including on function calls) now survives round-trips too. - Python ADK eval-set wire compatibility — eval files written by Python's adk eval now load unmodified
(eval_set_id/eval_id, optional final_response, (author, parts) intermediate responses, session_input fixtures), and
session_input.state actually seeds the eval session.
Fixed
- Tool-written state was silently discarded. ToolContext::state_delta / artifact_delta now land on the tool-response
event's actions and persist; skip_summarization ends the turn with the tool response as the final answer. - Streams died at 60 seconds. The provider HTTP clients no longer apply a total timeout to SSE bodies; timeout now
governs non-streaming requests only (streams get a 10 s connect timeout). - Concurrent invocations on one session lost events (in-memory backend): the store now merges appended events instead
of replacing the whole session per writer. - Circular $refs crashed the process. Both the OpenAPI spec converter and the #[tool] schema converter now return an
error at nesting depth 64 instead of overflowing the stack. - #[tool] failed to compile downstream unless the user also depended on async-trait/schemars/serde_json; the expansion
now goes through adk_rs::__private re-exports. A trybuild suite pins the misuse diagnostics. - Forward-compatibility: unknown Gemini finishReason/harm-category values and unknown Anthropic content-block types no
longer fail the whole response; refusal maps to Safety and pause_turn to Stop on both parse paths. Added
FinishReason::ImageSafety / UnexpectedToolCall. - Eval scoring: multi-turn cases report the average across invocations (per-invocation scores in
details.per_invocation) instead of silently keeping only the last turn; ResponseMatch matches whole tokens ("cat" no
longer matches "concatenate"); metric defaults are strict (ResponseMatch 0.8, TrajectoryMatch 1.0) instead of
pass-everything 0.0. - Anthropic non-streaming refusal responses, OpenAI/Azure quirks, A2A push-notification docs, and various stale doc
comments.
Full Changelog: v0.5.0...v0.6.0