Events

The Event type, its actions payload, and how appending an event mutates the session.

Everything an adk-rs run produces is an Event: user input, model text, tool calls and their results, state changes, transfers, escalations, and compaction summaries. Sessions are append-only logs of events, and a run is a stream of them.

The Event struct

An Event wraps an LlmResponse (the response field is #[serde(flatten)]-ed, so content, finish reason, and error fields serialize at the top level) plus identity, ordering, and control metadata.

FieldTypeMeaning
idStringUnique event id, auto-assigned (UUID).
invocation_idStringThe invocation this event belongs to.
authorString"user" or the name of the agent that produced it.
timestampf64Wall-clock seconds since the epoch, sub-second precision.
branchOption<String>Agent-tree branch, e.g. parent.child, for multi-agent runs.
responseLlmResponseContent, usage, finish reason, error code/message — flattened into the event on the wire.
actionsEventActionsSide effects to apply on append; see below.
long_running_tool_idsOption<Vec<String>>Ids of long-running (or gated) tool calls — a non-empty list signals a paused invocation.
partialOption<bool>Some(true) marks a transient streaming chunk — produced by LlmAgent under StreamingMode::Sse. Partial events are never persisted.
turn_completeOption<bool>Some(true) marks the event that ends a streaming turn.

Constructors and helpers

fn Event::new(author: impl Into<String>, response: LlmResponse) -> Event
Fresh id, current timestamp, default actions. invocation_id starts empty; the emitting agent stamps its own events (the runner stamps only the user event it creates), so custom agents must set it themselves.
fn Event::user_text(text: impl Into<String>) -> Event
A "user"-authored event wrapping Content::user_text(text).
fn Event::model_text(author, text) -> Event
An agent-authored event wrapping Content::model_text(text).
fn Event::new_id() -> String
Generate a UUID event id.
fn function_calls(&self) -> Vec<FunctionCall>
All FunctionCall parts in the event content (empty if none).
fn function_responses(&self) -> Vec<FunctionResponse>
All FunctionResponse parts in the event content.
fn is_final_response(&self) -> bool
True for events that end an agent’s response: no function calls or responses, not partial, no trailing code result — or skip_summarization/non-empty long_running_tool_ids force it.
fn has_trailing_code_result(&self) -> bool
True if the last content part is a CodeExecutionResult.

EventActions

EventActions is the control channel: agents and tools attach side effects here, and the session service applies them when the event is appended. Every field is skipped during serialization when empty or None.

FieldTypeMeaning
state_deltaStateDeltaKey/value updates applied to session state on append.
artifact_deltaIndexMap<String, u64>Filename → new version for artifacts saved during this event.
transfer_to_agentOption<String>Transfer control to the named agent (see Multi-agent).
escalateOption<bool>The agent is escalating control upward (e.g. to exit a LoopAgent).
skip_summarizationOption<bool>Skip LLM summarization of a function response.
end_of_agentOption<bool>The current agent has finished its run.
compactionOption<EventCompaction>Marks a summary event that replaces a range of earlier events; carries start_timestamp, end_timestamp, and compacted_content. See Event compaction.
requested_tool_confirmationsIndexMap<String, ToolConfirmation>Confirmations requested by this event, keyed by function-call id. Answered with adk_request_confirmation function responses. See Tool confirmation.
agent_stateOption<serde_json::Value>Free-form agent checkpoint for resumption.
rewind_before_invocation_idOption<String>Invocation id to rewind to, for rewind events.

How appending mutates the session

The free function apply_event_to_session in adk_rs::core::services is the single place where an event becomes session history. It is pure and synchronous, so backends can call it under a parking_lot::Mutex guard. In order, it:

  1. Returns the event untouched if partial == Some(true) — streaming chunks never enter the log.
  2. Copies temp:-scoped delta keys into the live in-memory state, so the current invocation can read them.
  3. Trims temp: keys out of actions.state_delta via State::trim_temp_keys — ephemeral keys are never persisted.
  4. Applies the trimmed delta to session.state.
  5. Bumps session.last_update_time and pushes the event onto session.events.

A related helper, history_with_compaction(&[Event]) -> Vec<Content>, assembles LLM conversation history from a session log: events covered by an EventCompaction range are replaced by the compaction’s summary content, and when overlapping compactions cover the same event the newest one wins.

EventStream

Agents and the runner return EventStream<'a>, defined in adk_rs::core::stream as Pin<Box<dyn Stream<Item = Result<Event>> + Send + 'a>>. You consume it with ordinary futures combinators.

Consuming a stream and matching on partsrust
use adk_rs::genai_types::Part;
use futures::StreamExt;

let mut events = runner.run("alice", Some("s1"), "What's 2 + 2?").await?;
while let Some(event) = events.next().await {
    let event = event?;

    // Structured views over the content.
    for call in event.function_calls() {
        println!("-> tool call {} {}", call.name, call.args);
    }
    for resp in event.function_responses() {
        println!("<- tool result {}: {}", resp.name, resp.response);
    }

    // Or match part-by-part.
    if let Some(content) = &event.response.content {
        for part in &content.parts {
            match part {
                Part::Text(t) => print!("{t}"),
                Part::FunctionCall(_) | Part::FunctionResponse(_) => {}
                other => println!("[{other:?}]"),
            }
        }
    }

    if event.is_final_response() {
        println!("\n[{} done]", event.author);
    }
}