Reading the event stream
Everything ADK does reaches you as an event. Learning to read one is the difference between debugging an agent and guessing at it.
The documentation calls events the fundamental unit of information flow. A user message, a reply, a tool request, a tool result, a change to state: each is an Event, and each says who produced it.
Opening one up
The agent and runner are the ones from lesson 5. This is the loop over events, printing what is inside each one.
async for event in runner.run_async(user_id="u1", session_id=session.id, new_message=question):
for part in (event.content.parts if event.content else []):
if part.text:
print(f"{event.author:<8} text {part.text.strip()}")
if part.function_call:
print(f"{event.author:<8} tool call {part.function_call.name} {dict(part.function_call.args)}")
if part.function_response:
print(f"{event.author:<8} tool result {part.function_response.response}")Read it against the loop from lesson 5. The agent asked for a tool with an argument it chose, ADK ran the function and put the result back as another event, and the model answered from it. Nothing is hidden in the middle.
What is on an event
| Field | What it holds |
|---|---|
author | Which agent produced it, or the user |
content | The parts: text, a function call, a function response |
actions | Side effects, like a change to state or a handover to another agent |
partial | True while a streamed reply is still arriving |
is_final_response() | Whether this is the answer rather than a step towards it |
actions is the one to remember. It is how state changes travel, which is lesson 21, and how one agent hands work to another, which is lesson 16.
The history is the same events
After a run, the session holds everything that happened, in order.
done = await runner.session_service.get_session(
app_name="demo", user_id="u1", session_id=session.id)
for event in done.events:
kinds = []
for part in (event.content.parts if event.content else []):
kinds.append("text" if part.text else "call" if part.function_call else "result")
print(f"{event.author:<8} {kinds}")Four now, because your question is an event too. That list is what gets sent back to the model on the next turn, which is why a long conversation costs more than a short one.
- Print
event.actionsfor each event and see what is on it. - Take the tool away from the agent and run it again. Read what the model does instead.
Little by little, you're building something great.