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.
| Field | Type | Meaning |
|---|---|---|
id | String | Unique event id, auto-assigned (UUID). |
invocation_id | String | The invocation this event belongs to. |
author | String | "user" or the name of the agent that produced it. |
timestamp | f64 | Wall-clock seconds since the epoch, sub-second precision. |
branch | Option<String> | Agent-tree branch, e.g. parent.child, for multi-agent runs. |
response | LlmResponse | Content, usage, finish reason, error code/message — flattened into the event on the wire. |
actions | EventActions | Side effects to apply on append; see below. |
long_running_tool_ids | Option<Vec<String>> | Ids of long-running (or gated) tool calls — a non-empty list signals a paused invocation. |
partial | Option<bool> | Some(true) marks a transient streaming chunk — produced by LlmAgent under StreamingMode::Sse. Partial events are never persisted. |
turn_complete | Option<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_idstarts 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 wrappingContent::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
FunctionCallparts in the event content (empty if none). fn function_responses(&self) -> Vec<FunctionResponse>- All
FunctionResponseparts 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-emptylong_running_tool_idsforce 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.
| Field | Type | Meaning |
|---|---|---|
state_delta | StateDelta | Key/value updates applied to session state on append. |
artifact_delta | IndexMap<String, u64> | Filename → new version for artifacts saved during this event. |
transfer_to_agent | Option<String> | Transfer control to the named agent (see Multi-agent). |
escalate | Option<bool> | The agent is escalating control upward (e.g. to exit a LoopAgent). |
skip_summarization | Option<bool> | Skip LLM summarization of a function response. |
end_of_agent | Option<bool> | The current agent has finished its run. |
compaction | Option<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_confirmations | IndexMap<String, ToolConfirmation> | Confirmations requested by this event, keyed by function-call id. Answered with adk_request_confirmation function responses. See Tool confirmation. |
agent_state | Option<serde_json::Value> | Free-form agent checkpoint for resumption. |
rewind_before_invocation_id | Option<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:
- Returns the event untouched if
partial == Some(true)— streaming chunks never enter the log. - Copies
temp:-scoped delta keys into the live in-memory state, so the current invocation can read them. - Trims
temp:keys out ofactions.state_deltaviaState::trim_temp_keys— ephemeral keys are never persisted. - Applies the trimmed delta to
session.state. - Bumps
session.last_update_timeand pushes the event ontosession.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.
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);
}
}Related pages
- The Runner — who persists events and yields the stream.
- Streaming —
partial/turn_completesemantics. - Sessions & state — where
state_deltalands. - Event compaction — summarizing long sessions.