when testing agents, `result = await session.start...
# ask-ai
d
when testing agents,
result = await session.start(agent, capture_run=True)
gets stuck forever. Also, our agent starts the conversation, not the user, but session.run always expects a user_input, and the result contains no events, so we cannot capture the agent's tool calls or replies. What can we do?
✅ 1
t
Thanks for reaching out, Rubén. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I hear two things you’re hitting: (1)
session.start(..., capture_run=True)
appears to hang, and (2) when your agent initiates the conversation,
session.run()
expects user input and you can’t capture the agent’s initial messages or tool calls. I’ll address both and give concrete steps you can try. Why this happens (short) • If an agent starts the conversation (for example it calls
session.generate_reply()
in
on_enter()
), calling
session.run()
is the wrong flow because
session.run()
is designed to accept a user input and won’t capture agent-initiated outputs. • In Python, tests that use
TaskGroup
can briefly unset the LLM during task transitions. If you call
session.run()
too early (before the agent’s first sub-task/LLM is active), the runtime can error or appear to hang. What to do — quick actionable fixes 1. Use
capture_run=True
with
session.start()
when the agent should speak first ◦ Start the session and capture the run so the session records any agent-initiated replies and tool calls:
Copy code
result = await session.start(agent=agent, capture_run=True)
• The returned
result
contains events you can assert against (messages, function/tool calls, etc.). 1. If you still need to call
session.run()
after
start()
, add a small delay ◦ Give the task/LLM time to settle before calling `session.run(...)`:
Copy code
await session.start()
     await asyncio.sleep(0.5)
     await session.run(user_input="...")
• This avoids the TaskGroup LLM transition problem that can cause the session to hang. 1. Validate agent replies and tool calls using the fluent assertion API ◦ Example checks you can run against the
result
from `capture_run=True`:
Copy code
await result.expect.next_event().is_message(role="assistant").judge(llm, intent="Performs an initial greeting")
     result.expect.contains_function_call(name="consent_given")
• These let you assert the agent’s initial message and any function/tool invocations. If it’s still stuck or you see specific runtime errors • Tell me the exact error message (if any) you see, and whether you’re using
TaskGroup
or other concurrency primitives. • Share the minimal test flow: how you start the session, whether the agent calls
generate_reply()
in
on_enter()
, and where you call
session.run()
. I can then suggest the precise change or a small test snippet tailored to your setup. Sources: Tasks and task groups | LiveKit Documentation | Testing and evaluation | LiveKit Documentation, with interactive elements
d
Copy code
result = await session.start(agent, capture_run=True)
print(f"Result: {result.events}")
produces no output, it just gets stuck there forever. our agent does not use taskgroups or even an
on_enter
, we simply call
session.generate_reply
after starting the session:
Copy code
result = await session.start(agent, capture_run=True)
print(f"Result: {result.events}") # never executes
await session.generate_reply()
t
Thanks — that’s very helpful context. You’re seeing the hang because
capture_run=True
tells
session.start()
to wait for the agent to produce output during the start call. In your flow the agent does not produce output until you explicitly call
session.generate_reply()
after
start()
, so
start(..., capture_run=True)
waits forever for that (and never returns). What you can do (pick one) • Let
start()
return, then call
generate_reply()
and capture events a. Start without capture:
Copy code
await session.start(agent)   # returns immediately
     await session.generate_reply()   # agent produces output
     print(session.events)   # now contains events
1. If you want the result object from a captured run, call
start()
then
start(..., capture_run=True)
is not appropriate here — use the pattern above and inspect
session.events
after
generate_reply()
. • Make the agent produce output during start (so capture_run works) ◦ Move the initial
generate_reply()
into the agent lifecycle that runs during start (for example
on_enter()
or similar). Then:
Copy code
result = await session.start(agent, capture_run=True)
    # result.events will contain the agent-initiated messages and tool calls
• Start with capture_run but trigger the reply immediately after start in the same async flow (not recommended unless agent emits immediately) ◦ If you truly need
capture_run=True
, the agent must produce output before
start()
finishes. For your current code, that means calling
generate_reply()
inside lifecycle code that runs as part of
start()
. Extra tips • Don’t call
capture_run=True
if the agent only calls
generate_reply()
after
start()
returns — that causes the indefinite wait you’re seeing. • If you want to assert agent messages/tool calls in tests, two common patterns: ◦ Pattern A (agent starts): agent emits on start -> use
result = await session.start(agent, capture_run=True)
and assert on
result
. ◦ Pattern B (test drives agent): start without capture -> call
await session.generate_reply()
from the test -> assert on
session.events
. If you’d like, paste the small snippet showing how you create the agent and how/where you call
generate_reply()
and I’ll suggest the minimal change (move to
on_enter
vs change start/run usage) to get
result.events
populated. , with interactive elements
d
Oh that was it, moving the generate_reply to on_enter solved it. Thanks!!