Running an agent
An agent is a description. A runner is the thing that drives it, and it needs one more object first: somewhere to keep the conversation.
Three names arrive together here and stay for the rest of the course. A session is one conversation. A session service stores sessions. A runner takes your agent, a session and a message, and drives the loop.
The agent, with the model from lesson 4
from pretend_adk import PretendModel, say, call
from google.adk.agents import LlmAgent
def lookup_order(order_id: str) -> str:
"""Look up the status of an order by its id."""
return f"Order {order_id} shipped on 3 March."The imports, and the tool from lesson 2 unchanged. Nothing here is new.
agent = LlmAgent( name="support",
model=PretendModel(replies=[call("lookup_order", order_id="A17"),
say("Your order shipped on 3 March.")]),
instruction="Help customers with their orders.",
tools=[lookup_order],
)Two replies are scripted: first ask for the tool, then answer. That is one trip round the loop, written out in advance so the lesson can be about the runner rather than the model.
A runner and a session
from google.adk.runners import InMemoryRunner
runner = InMemoryRunner(agent=agent, app_name="demo")
session = await runner.session_service.create_session(app_name="demo", user_id="u1")
print("session id is a", type(session.id).__name__, "| events so far:", len(session.events))InMemoryRunner is the runner plus a session service that keeps everything in memory. The session has an id, a history and a state, and the history is empty because nothing has happened yet.
Sending a message
A message is a content object with a role and parts, the same shape the model produces.
from google.genai import types
question = types.Content(role="user", parts=[types.Part(text="Where is order A17?")])
async for event in runner.run_async(user_id="u1", session_id=session.id, new_message=question):
print(event.author, "->", "final" if event.is_final_response() else "step")Three events for one question, all from the agent. The first two are the tool request and its result. The last is the answer, and is_final_response() is how you tell.
Getting just the answer
Most of the time that is all you want, so it is worth keeping these four lines.
session = await runner.session_service.create_session(app_name="demo", user_id="u1")
answer = ""
async for event in runner.run_async(user_id="u1", session_id=session.id, new_message=question):
if event.is_final_response() and event.content:
answer = "".join(part.text or "" for part in event.content.parts)
print(answer)A fresh session, because the scripted model has used up its two replies. The loop keeps the text of whichever event says it is final, and that is your answer.
create_session is the most common first error, and the message you get is about a missing session rather than a missing agent.- Ask a second question in the same session and count the events.
- Create a second session and ask the same question. It knows nothing about the first.
Every expert started right here.