import asyncio
import json
import logging
from dataclasses import dataclass
from dotenv import load_dotenv
from livekit.agents import (
Agent,
AgentSession,
AutoSubscribe,
JobContext,
JobProcess,
JobRequest,
MetricsCollectedEvent,
WorkerOptions,
cli,
metrics,
function_tool,
RoomInputOptions,
)
from livekit.agents.voice import RunContext
from livekit.plugins import deepgram, openai, silero
from livekit.plugins.turn_detector.english import EnglishModel
from livekit.rtc import RemoteParticipant
from livekit.agents.metrics import UsageCollector
from livekit import api
from prompts import system_prompt
_ = load_dotenv(override=True)
# Set up logging
logger = logging.getLogger("make-call")
logger.setLevel(
logging.INFO)
@dataclass
class UserData:
"""Store user data for the navigator agent."""
ctx: JobContext
metadata: str
RunContext_T = RunContext[UserData]
def prewarm(proc: JobProcess):
proc.userdata["vad"] = silero.VAD.load()
class PatientAdvocateAgent(Agent):
"""Initialize the navigator agent"""
def __init__(self, job_context=None) -> None:
self.job_context = job_context
super().__init__(instructions="")
async def on_enter(self) -> None:
logger.info("PatientAdvocate started")
formatted_prompt = system_prompt.format(
client_details=self.session.userdata.metadata
)
logger.info(formatted_prompt)
await self.update_instructions(instructions=formatted_prompt)
async def entrypoint(ctx: JobContext):
logger.info(f"connecting to room {ctx.room.name}")
english_model = EnglishModel()
await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
participant = await ctx.wait_for_participant()
logger.info(f"new particiapant joined {participant.metadata}")
user_data = UserData(ctx=ctx, metadata=str(participant.metadata))
session = AgentSession(
userdata=user_data,
turn_detection=english_model,
vad=ctx.proc.userdata["vad"],
stt=deepgram.STT(model="nova-3"),
llm=openai.LLM(model="gpt-4o-mini"),
tts=deepgram.TTS(),
)
usage_collector = UsageCollector()
@session.on("metrics_collected")
def _on_metrics_collected(ev: MetricsCollectedEvent):
metrics.log_metrics(ev.metrics)
async def my_logs():
summary = usage_collector.get_summary()
logger.info(f"latency: {summary}")
async def shutdown_hook():
await my_logs()
with open("ts.json", "w") as f:
json.dump(
session.history.to_dict(), f, indent=2)
await session.start(
room=ctx.room,
agent=PatientAdvocateAgent(),
room_input_options=RoomInputOptions(),
)
ctx.add_shutdown_callback(shutdown_hook)
if
name == "__main__":
cli.run_app(
WorkerOptions(
entrypoint_fnc=entrypoint,
prewarm_fnc=prewarm,
agent_name="outbound",
drain_timeout=1,
shutdown_process_timeout=15,
),
)
when I dispatch the agent to my room via sip participants, the agent doesn't join the room but I get in log like this
2025-07-09 13
3013,950 - INFO livekit.agents - received job request {"job_id": "AJ_yptXETgAF7tC", "dispatch_id": "", "room_name": "sip-e7d6a7e9", "agent_name": "outbound", "resuming": false}
2025-07-09 13
3013,969 - INFO livekit.agents - initializing process {"pid": 29814}
2025-07-09 13
3014,056 - INFO livekit.agents - process initialized {"pid": 29814, "elapsed_time": 0.09}
2025-07-09 13
3014,057 - DEBUG asyncio - Using selector: EpollSelector {"pid": 29814, "job_id": "AJ_yptXETgAF7tC"}
2025-07-09 13
3014,061 - INFO make-call - connecting to room sip-e7d6a7e9 {"pid": 29814, "job_id": "AJ_yptXETgAF7tC"}