can i call a function tool from an agent in on_ent...
# ask-ai
c
can i call a function tool from an agent in on_enter method directly. If so explain with an example
✅ 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 — you're asking whether an agent can call a function tool directly from its
on_enter
method and want an example. Good question. Short answer: No — you should not call a function tool directly (e.g.,
await self.my_tool(...)
) inside
on_enter
.
on_enter
is a lifecycle method for initializing agent behavior and generating messages; function tools are intended to be invoked by the LLM during its reasoning. Calling the tool synchronously from
on_enter
bypasses the LLM-driven tool call flow and can cause incorrect behavior. What to do instead: prompt the LLM in
on_enter
so it decides to invoke the tool. Example pattern:
Copy code
from livekit.agents import Agent, function_tool, RunContext

class WeatherAgent(Agent):
    def __init__(self):
        super().__init__(instructions="You are a weather assistant. On start, check weather for New York.")

    async def on_enter(self) -> None:
        # Prompt the model so it will choose to call the tool
        await self.session.generate_reply(instructions="Please check the current weather in New York.")

    @function_tool()
    async def lookup_weather(self, context: RunContext, location: str) -> str:
        # This is a tool the LLM can invoke (LLM will supply `location`)
        return f"The weather in {location} is sunny and 75°F."
Key points: • Use
on_enter
to generate a message that instructs the LLM to call the tool. • Do not call the tool method directly inside `on_enter`; let the LLM invoke it so the tool call is recorded and handled correctly. If you'd like, I can adapt the example to your specific tool signature or show how to capture the tool's result back into agent state. Which tool or use case do you have in mind? Sources: Function tool definition | LiveKit Documentation, with interactive elements
c
instead can i define the function as a normal function and can i create a function_tool wrapper on it
t
You're asking whether you can define a regular Python function and then directly wrap it with
@function_tool
. You cannot decorate an arbitrary standalone function with
@function_tool
as if that makes it an LLM-invocable tool directly. Instead, define a small wrapper method decorated with
@function_tool
that calls your normal function. That preserves normal Python logic while exposing the tool to the LLM. Example pattern:
Copy code
# normal function (pure Python, reusable)
def compute_tax(amount: float, rate: float) -> float:
    return amount * rate

from livekit.agents import function_tool, RunContext

class BillingAgent:
    @function_tool()
    async def compute_tax_tool(self, context: RunContext, amount: float, rate: float) -> float:
        # wrapper calls the normal function
        return compute_tax(amount, rate)
Notes: • Keep business logic in plain functions (testable, reusable). • Expose only small, well-typed wrappers with
@function_tool()
so the LLM can invoke them. • Do not call the tool function directly when you need an LLM-invoked call; let the LLM invoke the decorated wrapper so the tool call is tracked and handled correctly. If you want, tell me the signature of your existing function and I’ll show the exact wrapper for it. , with interactive elements
c
what if i want it to be a function tool, how do i pass the parameter ctx
t
You're asking how to make a function a
function_tool
and how to receive the `ctx`/`context` parameter. Short answer: include a
RunContext
(commonly named
context
or
ctx
) as the first parameter of the tool wrapper; the framework injects it automatically—you don't pass it yourself. Python example:
Copy code
from livekit.agents import function_tool, RunContext

def compute_tax(amount: float, rate: float) -> float:
    return amount * rate

class BillingAgent:
    @function_tool()
    async def compute_tax_tool(self, context: RunContext, amount: float, rate: float) -> float:
        # `context` is automatically provided by the framework
        # you can access session/state via context.session, context.userdata, etc.
        return compute_tax(amount, rate)
Node.js example:
Copy code
// plain function
function computeTax(amount: number, rate: number) {
  return amount * rate;
}

export default {
  execute: async ({ amount, rate }, { ctx }) => {
    // `ctx` is automatically provided
    // you can use ctx.session, ctx.userdata, etc.
    return computeTax(amount, rate);
  }
}
Key points: • The tool signature must include
context: RunContext
(Python) or receive
{ ctx }
(Node). • You never manually pass
ctx
when the LLM invokes the tool; the system injects it. • Use
context
to access session, userdata, interruption status, and playback helpers. Would you like an example showing use of
context.session
or
context.userdata
inside the tool? Sources: Function tool definition | LiveKit Documentation, with interactive elements
c
what happens if i return a value from on_enter function in an agent
t
You're asking what happens if your agent's
on_enter
returns a value. Short answer: nothing useful —
on_enter
is an async lifecycle hook that is expected to return
None
. Any value you return is not consumed or acted on by the framework. Use
on_enter
for side effects (generate a reply, set state, etc.) rather than returning data. If you need to pass data out of
on_enter
, store it on session/state (for example
context.userdata
or
self.session
), or trigger a message that causes the LLM or another handler to run and produce/consume the value. Would you like an example showing how to save data from
on_enter
into
context.userdata
? Sources: Agents and handoffs | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentation, with interactive elements