5-08-19 12:25:00,645 - DEBUG livekit.agents - http...
# ask-ai
m
2025-08-19 122500,645 - DEBUG livekit.agents - http_session(): closing the httpclient ctx this takes too long causing tts deepgram connection to stay open. how to forcefully shut everything once the call disconnects
t
Thanks for reaching out, Usama. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Hey there! To make sure HTTP sessions and TTS Deepgram connections close nicely after a call ends, here are some friendly steps you can follow: • Agent Session Cleanup: Try using
await session.drain()
and then
await session.aclose()
to gently wrap things up and free resources. • Automatic Cleanup: Good news—LiveKit agents usually handle session cleanup automatically when participants leave. Just double-check your session is connected to participant events like
CLIENT_INITIATED
or
ROOM_DELETED
. • Manual Termination: If you want more control, you can create a handy function to close the session programmatically, like with
asyncio.create_task(self.session.aclose())
. • Deepgram TTS Specific: Don’t forget to close all active TTS streams and the connection pool using
await stream.aclose()
and
await self._pool.aclose()
to keep things tidy. • Worker-Level Shutdown: When you want to disconnect the agent but keep others going, use `ctx.shutdown(reason="Session ended")`—it’s a smooth way to say goodbye to just that session. Following these tips will help you clean up all connections and resources properly. If you want a hand setting any of this up, just let me know—I’m here to help! Sources: Inside a session | LiveKit Docs | basics/exit_message.py | livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/tts.py | Agents Core Architecture | livekit/livekit_composite | DeepWiki
m
this only happens in outbound calling agent
t
Hey there! When you're working with outbound calling agents, cleaning up sessions properly is super important, and here are some friendly ways to do it: • Session Close Callbacks: You can use the
@session.on("close")
event to tidy things up when the session ends. If you want, you can also delete the room to free up all the resources. • Shutdown Hooks: Try adding shutdown callbacks with
ctx.add_shutdown_callback()
to handle any cleanup or post-processing after the session finishes. • Outbound Call-Specific Cleanup: It’s handy to have a helper function like
hangup()
that deletes the room and ends the call smoothly. • Function Tools: Tools like
end_call()
are great for gracefully wrapping up sessions in a controlled way. • Voicemail Detection: If you want to catch things like voicemail,
detected_answering_machine()
can help you detect that and end the call properly. • Manual Cleanup: You can always manually close sessions and free resources using
await session.drain()
and
await session.aclose()
. Using these methods will help you keep everything neat and tidy with your outbound calls. If you want a hand setting any of this up, just let me know—I’m here to help! Sources: Inside a session | LiveKit Docs | agent.py | Agents Core Architecture | livekit/livekit_composite | DeepWiki | basics/exit_message.py | livekit-plugins/livekit-plugins-aws/livekit/plugins/aws/experimental/realti...
m
worker never shuts down
t
If your worker isn’t shutting down as expected, no worries! Here are some friendly steps to help you get it sorted: • Graceful Drain: Try using `await worker.drain(timeout=60)`—this lets any active jobs finish up nicely before shutting down. You can tweak the timeout to fit your needs. • Immediate Shutdown: If you need to close things quickly,
await worker.aclose()
will force the worker to stop and end all tasks. • Shutdown Hooks: Consider registering shutdown callbacks with
ctx.add_shutdown_callback()
to clean up resources when jobs wrap up. • Timeout Configuration: Setting the
shutdown_process_timeout
in WorkerOptions helps make sure the worker shuts down within a set timeframe. • SIGTERM Handling: Make sure your worker is set to receive SIGTERM signals—this tells it to stop taking new jobs and shut down once current tasks finish. These tips should help your worker shut down smoothly. If you want a hand with any of these or run into any issues, just let me know—I’m here to help! Sources: agents/src/worker.ts | examples/voice_agents/session_close_callback.py | Job lifecycle | LiveKit Docs | Inside a session | LiveKit Docs | pkg/sip/outbound.go
m
how to get the worker instance
t
To get the worker instance in LiveKit, here’s a simple way to do it: • Python: You can create a worker instance using
Worker
and
WorkerOptions
like this:
Copy code
from livekit.agents import Worker, WorkerOptions

# Create worker options
opts = WorkerOptions(entrypoint_fnc=your_agent_function)

# Create worker instance
worker = Worker(opts)

# Run the worker
await worker.run()

# When you need to shut it down
await worker.drain(timeout=30)  # Graceful shutdown
await worker.aclose()  # Close the worker
Accessing Worker Info: You can use the
JobContext
to get details like
ctx.worker_id
and even add shutdown callbacks with
ctx.add_shutdown_callback()
. • JavaScript: Here’s how to create a worker instance using
Worker
and `WorkerOptions`:
Copy code
import { Worker, WorkerOptions } from '@livekit/agents';

// Create worker options
const opts = new WorkerOptions({ agent: './path/to/your/agent.js' });

// Create worker instance
const worker = new Worker(opts);

// Run the worker
await worker.run();

// When it’s time to shut down
await worker.drain(30000);  // Graceful shutdown
await worker.close();       // Close the worker
If you have any questions or want a hand with managing your workers or the shutdown process, just let me know—I’m here to help! Sources: LiveKit Agents | livekit-agents/livekit/agents/job.py | agents/src/worker.ts | Worker | LiveKit Agents
m
tts = deepgram.TTS( model="aura-2-andromeda-en", api_key=os.getenv("DEEPGRAM_API_KEY"), ) import aiohttp # Connection pooling is handled internally tts._pool = agents.utils.ConnectionPool[aiohttp.ClientWebSocketResponse]( connect_cb=tts._connect_ws, close_cb=tts._close_ws, max_session_duration=3600, mark_refreshed_on_get=False, ) self.pool = tts._pool # Prewarm connections tts.prewarm() this causes the connection to be open
t
Hey there! To make sure you properly close your Deepgram TTS connections and avoid leaving them open, here’s a friendly step-by-step guide: • Close the TTS Instance: Just call the
aclose()
method on your TTS instance. This tidies up all active streams and the connection pool for you:
Copy code
await tts.aclose()
Close the Connection Pool: If you’re handling the pool yourself, use
await pool.aclose()
. This will cancel any prewarm tasks, invalidate connections, and close any pending ones. • Stream Cleanup: Always remember to close individual streams with
await stream.aclose()
or even better, use them as async context managers like this:
Copy code
async with tts.stream() as stream:
    # Use the stream
    pass
Best Practices: Make it a habit to call
aclose()
on your TTS instance when your app is shutting down. Also, handle exceptions so everything gets cleaned up nicely, even if something unexpected happens. If you want, I’m here to help you with implementing these steps or if you have any other questions. Just let me know! Sources: livekit-agents/livekit/agents/tts/tts.py