is it safe if i call on_enter method of an agent i...
# ask-ai
c
is it safe if i call on_enter method of an agent inside a tool. Can there be any issues
✅ 1
t
Thanks for reaching out, Kushagra. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about calling an agent’s
on_enter
method from inside a tool. Short answer: it’s not recommended to call
on_enter
manually from a tool. Calling it can work, but there’s a known risk: if
on_enter
awaits speech playout (for example
await handle.wait_for_playout()
or
await self.session.generate_reply()
), awaiting inside the tool call can create a circular wait/deadlock because the tool call won’t finish until
on_enter
returns. What you can do instead: • Trigger the same behavior without awaiting speech. For example, call
self.session.generate_reply()
but do not
await
it from the tool. • Prefer letting the framework perform agent handoffs so
on_enter
is invoked naturally, or move the shared behavior into a helper method (safe to call from tools) and keep speech-playout/awaiting inside the normal
on_enter
flow. Quick clarifying question: are you planning to call
on_enter
to run audio/speech playback, or just to change internal agent state? That will help me suggest the safest code pattern. Sources: Pipeline nodes and hooks | LiveKit Documentation | Tasks and task groups | LiveKit Documentation | Agents and handoffs | LiveKit Documentation, with interactive elements
c
what if i do not call on_enter using await, though there is an await for generate_reply
t
Thanks — I’m responding to your follow-up about not awaiting
on_enter
while still awaiting
generate_reply
. Short answer: not awaiting
on_enter
does not avoid the deadlock risk if
generate_reply
is awaited inside
on_enter
. The tool call remains active until the tool returns; if
on_enter
(even invoked without awaiting) schedules and then awaits
generate_reply
, that awaited work can still create a circular wait between the tool execution and the session/speech playout. Safe options: • Do not await
generate_reply
inside the tool or inside any call invoked from the tool. Call
self.session.generate_reply()
without
await
so playback runs independently. • Extract non-speech logic into a helper method you can call synchronously from the tool, and reserve any awaited speech/playout calls for the normal
on_enter
flow that the framework triggers. • Prefer triggering agent handoffs or session updates so the framework calls
on_enter
naturally rather than invoking it manually. Quick check: do you need the reply/playout to finish before the tool returns, or can it run asynchronously? That determines whether to fire
generate_reply()
without awaiting or restructure the logic. , with interactive elements
c
suppose if i use await at both the places. how will it create wait loop. Since even if from inside a generate reply runs, either it makes the agent say something or call a tool and in both cases the generate reply ends and function returns.
t
You're asking why awaiting both
on_enter
(called from a tool) and
generate_reply
inside it can deadlock. Short answer: awaiting creates a circular wait because the tool call holds the execution context until it returns, and
generate_reply
(or TTS/playout) needs that context to progress — so both end up waiting on each other. Why that happens, step-by-step: 1. Tool A runs and calls
on_enter()
(sync or via await) while Tool A’s execution context is still active. 2.
on_enter()
calls
await session.generate_reply()
(or awaits speech playout). 3.
generate_reply()
schedules LLM/TTS work that depends on the agent/session event loop to continue and finish. 4. The agent/session can’t progress because Tool A hasn’t returned (it’s still awaiting
on_enter()
), and
on_enter()
can’t return because it’s awaiting
generate_reply()
→ circular wait / deadlock. Important clarifications: •
generate_reply()
does not always complete instantly; it can involve inference, TTS, and playout that require the session to move forward. • Simply not awaiting
on_enter()
but still awaiting
generate_reply()
inside it can still produce the same blocking behavior if the tool context remains tied to that call. Safe patterns: • Fire-and-forget the reply inside the tool: call
self.session.generate_reply(...)
without
await
. • Move non-speech logic into a helper you can call synchronously from the tool; keep awaited speech/playout in the normal
on_enter
path that the framework invokes. • Prefer letting the framework trigger
on_enter
via proper handoffs rather than invoking it manually from a tool. If you want, share a short snippet of your tool + on_enter code and I’ll point out where to change it to avoid the circular wait. Sources: Tasks and task groups | LiveKit Documentation | Agent speech and audio | LiveKit Documentation, with interactive elements
c
so now explain whywill it be a problem i call on_enter without awaiting
t
Thanks — I’m responding to your question about calling
on_enter
without awaiting it and whether that avoids problems. Short answer: calling
on_enter
without
await
reduces the immediate blocking risk, but it can still cause issues if
on_enter
(or anything it triggers) contains awaited operations like
generate_reply()
or speech playout. Those awaited operations can create indirect blocking or unexpected ordering because they rely on the session/agent event loop that the tool call still affects. Why this can still be a problem (step-by-step): 1. Tool starts and invokes
on_enter()
without awaiting it (fire-and-forget). 2.
on_enter()
begins running asynchronously and may call
await session.generate_reply()
or await TTS/playout. 3. Even though the tool didn’t await
on_enter()
, the session’s processing and event loop often expect the tool call to finish or yield control before progressing through response generation, TTS, or further tool calls. 4. If those downstream steps require the tool context to be released (or other parts of the session to run), they can stall or behave unpredictably because the asynchronous work was started from inside a tool context rather than via a normal handoff. Practical consequences: • Race conditions: the reply or playout may start later than you expect or interleave with other actions. • Partial/no execution: parts of the async work may never complete if the session shuts down or the context is cleaned up. • Hidden deadlocks: even without an explicit await on
on_enter
, the awaited work inside it can implicitly wait for resources the tool still holds. Safe patterns instead: • Call
session.generate_reply()
without awaiting it (fire-and-forget) and ensure
on_enter
avoids any awaits that depend on the tool context. • Move non-async or state-only logic into a helper you call synchronously from the tool. • Let the framework perform agent handoffs so
on_enter
runs in the intended context. If you want, paste your
tool.execute
+
on_enter
snippets and I’ll point out exactly where to change things. , with interactive elements