I don't have a shutdown call back but I still get ...
# ask-ai
b
I don't have a shutdown call back but I still get "process did not exit in time, killing process" why?
t
Thanks for reaching out, Vineeth. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
It looks like you're encountering the message "process did not exit in time, killing process." This happens when a supervised process doesn't shut down within the expected time after receiving a shutdown request. Even if there's no shutdown callback defined, the system still expects the process to exit quickly. Without that custom shutdown logic, the process might be busy or unresponsive when asked to stop, which can cause this delay. If the process takes too long to exit, the supervisor will have to forcefully terminate it. To help with this, you can try increasing the timeout duration by adjusting the
shutdown_process_timeout
setting in
WorkerOptions
. This gives your process a bit more time to close gracefully. I hope this helps clarify things! Sources: examples/voice_agents/basic_agent.py | Inside a session | LiveKit Docs
b
In my hangup tool, I am doing some processing and at the end I am doing delete room to remove all participants, does that automatically call the shutdown immediately or is there something else which needs to be done?
t
When you delete a room in LiveKit, it gently disconnects all participants in that room and triggers a shutdown for them. The
DeleteRoom
API takes care of removing everyone, and the
Disconnected
room event is sent with the reason
ROOM_DELETED
. So, you don’t need to worry about handling participant disconnections separately after deleting the room — it’s all managed for you! Sources: cmd/lk/room.go | Agents telephony integration | LiveKit Docs | livekit-api/livekit/api/room_service.py | pkg/service/roommanager.go | Connecting to LiveKit | LiveKit Docs
When you delete a room in LiveKit, it gently disconnects everyone in that room and gracefully shuts things down for them. The
DeleteRoom
API takes care of removing all participants, and you'll see the
Disconnected
room event with the reason
ROOM_DELETED
. So, there’s no need to worry about handling participant disconnections afterward—it’s all handled smoothly for you.
b
Once I delete a room, what kind of processes running could cause "process did not exit in time, killing process", I am sure I am not running anything
t
I'm sorry you're encountering the error "process did not exit in time, killing process" after deleting a room. This usually happens when some agent processes don't shut down smoothly within the set timeout. It might be due to things like: • Cleanup tasks taking longer than expected during agent shutdown. • Subprocesses not responding to health checks, such as ping timeouts. • Processes going beyond the
close_timeout
limit while shutting down. Even if it seems like no tasks are running, it's a good idea to double-check that all shutdown callbacks finish quickly. If needed, you can also adjust the
close_timeout
setting to give the processes a bit more time to close gracefully. I hope this helps, and please feel free to reach out if you need more assistance! Sources: examples/avatar_agents/audio_wave/dispatcher.py | Docs::Home | mcp/server.py
b
How do I go about handling a common process of let's say saving conversation data, the call could end in different methods, user could disconnect, agent could disconnect but at the end I need to process the conversation data.
t
I'm glad you're looking into ways to save conversation data when a call ends, whether it's due to a user disconnect, agent disconnect, or room deletion. Here's a friendly approach that can help you manage this smoothly: • Use Shutdown Callbacks: You can register a shutdown callback in your job entrypoint using
ctx.add_shutdown_callback
. This is a great way to make sure any cleanup tasks, like saving conversation data, happen no matter how the session ends. • Detect Session End Reason: By listening to the
close
event on the session, you can find out why the session ended (such as user disconnect or room deletion) and then take any specific actions you might need. • Access Conversation History: Using
ctx.session.history
lets you retrieve the full conversation transcript, including messages, roles, and timestamps, which is perfect for saving to a database or file. • Real-Time Transcription: You might also consider listening to events like
conversation_item_added
to save messages as they come in during the session, so nothing gets missed. By following this approach, you can feel confident that your conversation data will be saved reliably, no matter how the call wraps up. If you have any questions or want to explore this further, I'm here to help! Sources: Session recording and transcripts | LiveKit Docs | Session recording and transcripts | LiveKit Docs | How to capture real-time agent transcriptions during conversations | Events and error handling | LiveKit Docs | Inside a session | LiveKit Docs
I understand how important it is to make sure your conversation data is saved no matter how a call ends. Let me guide you through a friendly approach to handle this smoothly: 1. Use Shutdown Callbacks: You can register a shutdown callback in your job entrypoint with
ctx.add_shutdown_callback
. This way, any cleanup tasks like saving your conversation data will run no matter how the session finishes. 2. Detect Session End Reason: By listening to the
close
event on the session, you can find out why the session ended—whether it was a user disconnect, room deletion, or something else. 3. Access Conversation History: You can grab the full conversation transcript, including messages, roles, and timestamps, using
ctx.session.history
. This makes it easy to save everything to a database or a file. 4. Real-Time Updates: If you want to save data as the conversation happens, listening to events like
conversation_item_added
can help you capture updates in real time. Here’s a simple example of how you might set up a shutdown callback to save your conversation data:
Copy code
async def entrypoint(ctx: JobContext):
    async def save_conversation_data():
        history = ctx.session.history
        # Save history to database or file
    
    ctx.add_shutdown_callback(save_conversation_data)
This approach helps ensure your conversation data is saved reliably, no matter how the call ends. If you have any questions or want to explore this further, I’m here to help!
b
how do I trigger a shutdown when a user disconnects and in the agent hangup tool
t
I'm happy to guide you through how to trigger a shutdown when a user disconnects or uses the agent hangup tool. Here are some helpful methods you can use: • Automatic Shutdown on User Disconnect: Simply set
close_on_disconnect=True
in
RoomInputOptions
. This way, the session will automatically close when the user leaves, making things seamless for you. • Manual Shutdown via Hangup Tool: You can create a function tool (for example,
end_session
) that calls
session.aclose()
to gracefully end the session whenever needed. • Room Deletion: Once the session ends, using
ctx.delete_room()
will disconnect all participants and shut down the room, keeping everything tidy. • Final Cleanup: It’s a great idea to register shutdown callbacks with
ctx.add_shutdown_callback()
. This helps you handle important tasks like saving data or releasing resources smoothly. By using these methods, you can ensure a complete and controlled shutdown process, whether it’s triggered by a user disconnect or the agent hangup tool. If you have any questions or need further assistance, I’m here to help! Sources: examples/warm-transfer/warm_transfer.py | avatars/hedra/education_avatar/education-frontend/components/livekit/agent-... | Inside a session | LiveKit Docs
b
what happens after shutdown callback is successfully executed
t
When the shutdown callback is successfully executed in LiveKit, the framework kindly disconnects the agent from the room, closes any open HTTP contexts, and then allows the process to end smoothly. If all the shutdown tasks finish within the timeout period (which is 60 seconds by default), the process exits gracefully. If not, to avoid any indefinite waiting, the process is gently forcefully terminated. We're here to help if you have any questions about this! Sources: livekit-plugins/livekit-plugins-aws/livekit/plugins/aws/experimental/realti... | Job lifecycle | LiveKit Docs | Inside a session | LiveKit Docs | Inside a session | LiveKit Docs
When the shutdown callback in LiveKit finishes successfully, the framework kindly disconnects the agent from the room, closes any open HTTP contexts, and lets the process come to a close. If all the shutdown tasks wrap up within the timeout period (which is 60 seconds by default), the process exits smoothly and gracefully. If not, the process is gently but firmly terminated to avoid any endless waiting. We're here to make sure everything goes as smoothly as possible for you!
b
If I set close_on_disconnect=True, In the hangup tool I do delete room which leads to participant disconnet triggering close_on_disconnect=True to shutdown, does the shutcallback get triggered twice?
t
I completely understand how this might be a bit confusing, so let me walk you through it. When you have
close_on_disconnect=True
and you call
delete_room
, the shutdown callback actually doesn't get triggered twice. Here's why: deleting the room disconnects all participants with the reason
ROOM_DELETED
, which then triggers the shutdown logic just once. The
close_on_disconnect
setting works at the participant level, but when the room is deleted, that action takes priority, resulting in only one shutdown callback. I hope this helps clarify things! If you have any more questions, feel free to ask—I’m here to help. Sources: Job lifecycle | LiveKit Docs | examples/voice_agents/realtime_joke_teller.py | Inside a session | LiveKit Docs | Managing rooms | LiveKit Docs | livekit-rtc/livekit/rtc/_proto/participant_pb2.pyi