Is userdata the best place to store state in my cu...
# ask-ai
f
Is userdata the best place to store state in my custom agent class? Can I only store userdata within a function tool or can I also use it in a pipeline node as well?
t
Thanks for reaching out, Abdullah. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
I'm glad you're exploring how to manage state in your custom agent class! Using
UserData
is actually the best way to go. It helps keep your agents stateless while still holding onto session-specific context, which is fantastic for making your system scalable and reusable. You can use
UserData
in both function tools and pipeline nodes: • For function tools, you can access
UserData
through the
RunContext
parameter. This makes it easy to manage and update session-specific data as your tool runs. • Within pipeline nodes,
UserData
is available via
self.session.userdata
, so you can maintain consistent state throughout your agent's workflow. To get started with
UserData
, just define it as a dataclass and pass an instance to the
AgentSession
constructor. This way, your agent will smoothly handle state across all its operations. If you have any questions while setting this up, feel free to ask—I’m here to help! Sources: Building Multi-Agent Architectures with LiveKit Agents | Workflows | LiveKit Docs | complex-agents/nova-sonic/form_agent.py | examples/voice_agents/restaurant_agent.py | Building an Automated IVR Menu Caller | LiveKit Docs
f
How do I access the userdata in my entrypoint function?
<http://logger.info|logger.info>(f"Userdata in main: {_ctx_.proc.userdata}")
This doesn't appear to have anything after I set
_self_.session.userdata.test = "testing"
on the on_enter function in my agent class.
t
When working with your entrypoint function, a helpful approach is to access
userdata
by initializing it as you create the
AgentSession
. For instance, you can define a dataclass for
userdata
, set it up with some initial values, and then pass it along to the
AgentSession
constructor. This way, the session and all its parts stay in sync with the same state. The challenge you’re seeing happens because the
on_enter
function runs asynchronously after the session has started, while your entrypoint function finishes running beforehand. So, any changes made to
userdata
inside
on_enter
won’t show up in the entrypoint function since it’s already done executing. To work around this, try to make sure that important updates to
userdata
happen right within the entrypoint function, or access the updated state later on in components that run after
on_enter
, like tools or downstream agents. I hope this helps clarify things! Feel free to ask if you'd like me to walk through it with you step-by-step. Sources: Building an Automated IVR Menu Caller | LiveKit Docs | Workflows | LiveKit Docs | complex-agents/nova-sonic/form_agent.py | examples/voice_agents/restaurant_agent.py | Workflows | LiveKit Docs
f
<http://logger.info|logger.info>(f"Userdata in main: {_ctx_.proc.userdata}")
To clarify this is running in the shutdown callback
t
To access
userdata
in the shutdown callback, a helpful approach is to make sure the callback can reach the session or
userdata
by capturing it within the closure when you register the callback. Here’s a simple example to guide you:
Copy code
async def entrypoint(ctx: JobContext):
    @dataclass
    class MySessionInfo:
        test: str = "default"

    userdata = MySessionInfo()
    session = AgentSession[MySessionInfo](userdata=userdata)

    async def cleanup_hook():
        <http://logger.info|logger.info>(f"Userdata in shutdown: {userdata.test}")

    ctx.add_shutdown_callback(cleanup_hook)
    await session.start(...)
In your situation, if
userdata
is being set in
on_enter
, it’s important to make sure the session stays alive until the shutdown callback runs. If the session ends before the callback gets a chance to execute,
userdata
won’t be available. I hope this helps clarify things for you! Sources: examples/voice_agents/basic_agent.py | Inside a session | LiveKit Docs | Job lifecycle | LiveKit Docs | Building an Automated IVR Menu Caller | LiveKit Docs | Inside a session | LiveKit Docs