a
hi
t
Thanks for reaching out, Yash. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Hi — thanks for reaching out! How can I help you today? If you’re not sure where to start, here are a few things I can assist with: • Troubleshooting a meeting or connection issue (please include your room name/ID and a brief description) • Setting up SDKs (which platform are you using: web, iOS, Android, or server?) • Managing rooms, participants, or permissions • Billing, account, or API key questions • Anything else — just tell me what you’re trying to do Share a bit more detail and I’ll guide you through the next steps. , with interactive elements
a
hello i have problem i am building a AI Interview taker using livekit voice agent but the problem is i am calling tools dynamically to fetch or generate questions of different varieties like (aptitude , logical , numerical , technical , etc). But when i used pipeline method(stt , llm , tts) then all tools called in a proper way but when i used realtime open ai model then no tool called, i had keep same method for both approaches so why is that . i have passed tool name in prompt and also mentioned that which tool should be used and when. but the problem is with realtime model why it is not calling i am also sharing realtime model ====== code _Using semantic_vad for better turn detection with tool calling_ _# semantic_vad uses a classifier to detect when user is done speaking_ # This prevents premature responses and works better with function tools realtime_model = realtime.RealtimeModel( model=REALTIME_MODEL, _api_key_=_api_keys_['OPENAI_API_KEY'], _base_url_=_api_keys_['OPENAI_BASE_URL'] if _api_keys_.get('OPENAI_BASE_URL') else None, modalities=["text"], # Text-only output; ElevenLabs handles TTS temperature=REALTIME_TEMPERATURE, _# Server-side noise reduction (near_field for interview close-range mics)_ _input_audio_noise_reduction_=OPENAI_NOISE_REDUCTION, # Transcribe audio input via Whisper for transcript logging _input_audio_transcription_=InputAudioTranscription( model="whisper-1", language=ENFORCED_LANGUAGE, ), _tool_choice_="auto", _# Use semantic_vad for better tool calling support_ _# semantic_vad detects when user is done speaking based on their words_ _# This is more reliable than server_vad for interview scenarios_ _turn_detection_=TurnDetection( type="semantic_vad", eagerness=REALTIME_VAD_EAGERNESS, # "low" = patient, lets users think _create_response_=True, _interrupt_response_=True, ), ) ==== pipeline method ==== # Create STT stt = openai.STT( _api_key_=_api_keys_['OPENAI_API_KEY'], model="whisper-1", _base_url_=_api_keys_['OPENAI_BASE_URL'] if _api_keys_['OPENAI_BASE_URL'] else None ) # Create LLM llm = openai.LLM( model=_api_keys_['OPENAI_MODEL'], _api_key_=_api_keys_['OPENAI_API_KEY'], _base_url_=_api_keys_['OPENAI_BASE_URL'] if _api_keys_['OPENAI_BASE_URL'] else None ) # Create TTS tts = elevenlabs.TTS( _voice_id_=VOICE_ID, model=VOICE_MODEL, language=VOICE_LANGUAGE, _streaming_latency_=STREAMING_LATENCY, _api_key_=_api_keys_['ELEVEN_API_KEY'] if _api_keys_['ELEVEN_API_KEY'] else None ) ==== i am also giving you prompt and tools --- example of one tool -- @function_tool() async def *detect_candidate_skills*(self, _context_: RunContext) -> str: """Analyze the candidate's resume and job description to extract key skills for evaluation. This tool should be called ONCE at the beginning of the technical interview section to understand what skills to evaluate. It analyzes the resume and job description to identify: - Technical skills (programming languages, frameworks, databases, tools) - Proficiency levels (beginner, intermediate, advanced, expert) - Priority of each skill for the role Call this tool when: - Starting Section 4 (Technical Questions) - Before asking the first technical question Returns: A JSON summary of detected skills with their levels and priorities. Use this information to understand the candidate's background before calling get_next_interview_question. """ start_time = time.time() # Mark tool execution start - prevents false silence detection self.tool_execution_in_progress = True self.tool_execution_start_time = time.time() logger.info("TOOL EXECUTION START: detect_candidate_skills - silence detection paused") _try_: logger.info("TOOL: detect_candidate_skills called") # Check if skills already detected if self.interview_state.skills_initialized: skills_summary = [ f"- {s.name} ({s.level.value})" for s in self.interview_state.detected_skills ] result = f"Skills already analyzed. Found {len(self.interview_state.detected_skills)} skills:\n" + "\n".join(skills_summary) self._log_tool_call( "detect_candidate_skills", {"resume_length": len(self.resume_text), "jd_length": len(self.job_description)}, result, (time.time() - start_time) * 1000 ) return result # Use the tools engine to detect skills detected_skills = await self.tools_engine.detect_skills( _resume_text_=self.resume_text, _job_description_=self.job_description ) # Store in interview state for skill in detected_skills: self.interview_state.add_skill(skill) self.interview_state.skills_initialized = True # Also update legacy fields for backward compatibility self.skills_to_cover = [ {"skill": s.name, "context": s.context, "level": s.level.value} for s in detected_skills ] # Build response skills_summary = [] for skill in detected_skills: skills_summary.append( f"- {skill.name}: {skill.level.value} level (Priority {skill.priority}) - {skill.context}" ) result = f"""Skills Analysis Complete! Found {len(detected_skills)} key skills to evaluate: ====== ======= prompt =====
Copy code
===========================================
AVAILABLE TOOLS (DYNAMIC INTERVIEW SYSTEM)
============================================
You have access to these tools for conducting an adaptive, resume-driven interview:

1. **check_user_listening**: Automatically called when user is silent for 30 seconds. Deliver its response exactly as returned.

2. **detect_candidate_skills**: Call this ONCE at the start of Section 4 to analyze the candidate's resume and extract key skills.
   - Identifies technical skills (programming languages, frameworks, databases, tools)
   - Determines proficiency levels (beginner, intermediate, advanced, expert)
   - Prioritizes skills based on job requirements
   - Returns a summary of skills to evaluate

3. **get_next_interview_question**: Get dynamically generated technical questions tailored to the candidate's skill level.
   - Generates challenging questions matched to the candidate's proficiency
   - Questions are personalized based on resume content
   - Tracks which skills have been covered
   - Returns "INTERVIEW_QUESTIONS_COMPLETE" when all skills are evaluated

4. **generate_tough_question**: Generate CHALLENGING questions to test the TRUE depth of a candidate's knowledge.
   - Creates tough questions that push candidates to their limits within their skill level
   - Requires deeper critical thinking and problem-solving
   - Includes edge cases, trade-offs, and real-world complexities
   - Differentiates good candidates from exceptional ones
   - Takes a performance parameter: "weak", "average", or "strong"
   - Use "weak" if they're struggling, "average" for normal, "strong" if they're excelling
   - **RECOMMENDED**: Use this for at least 1-2 questions per candidate to truly test their abilities

5. **generate_followup_question**: Generate contextual follow-up questions based on the candidate's answer.
   - Analyzes the depth and quality of their response
   - Creates targeted follow-ups to probe deeper
   - Returns "NO_FOLLOWUP_NEEDED" if the answer was thorough
   - Use after each candidate response for adaptive questioning

6. **get_aptitude_question**: Get logical reasoning and aptitude questions for critical thinking assessment.
   - Generates probability, logic puzzles, pattern recognition questions
   - MANDATORY for ALL candidates regardless of role (BTech, BBA, MBA, etc.)
   - Tests problem-solving ability, not domain knowledge
   - Ask 2-3 of these during or after technical questions

7. **get_interview_progress**: Check current interview progress (optional, for time management).
[11:28 AM] ============================================
SECTION 4: TECHNICAL QUESTIONS (18 min - Core of the interview)
============================================
**IMPORTANT: Use the dynamic interview tools for this section**

- Introduce: "I'll now ask some technical questions relevant to the role. Take your time to think before answering."

- **STEP 1 - SKILL ANALYSIS (First time entering Section 4):**
  1. Call detect_candidate_skills to understand the candidate's background
  2. Note the skills and levels returned - this guides the technical evaluation
  3. Track candidate performance mentally: "weak", "average", or "strong"

- **STEP 2 - QUESTION FLOW (Repeat until complete):**
  1. Decide which question type to use:
     - **For regular questions:** Call get_next_interview_question
     - **For tough/challenging questions:** Call generate_tough_question with performance level
       * Use "weak" if they've been struggling (fair but challenging)
       * Use "average" for normal performance (differentiate abilities)
       * Use "strong" if they're excelling (push their limits)
  2. Ask the returned question clearly to the candidate
  3. Wait for and listen to the candidate's full response
  4. Call generate_followup_question with their answer
     - If a follow-up is returned: Ask it, then listen to their response
     - If "NO_FOLLOWUP_NEEDED": Acknowledge briefly and move on
  5. Acknowledge their response: "Thank you, that's helpful." or "I appreciate that insight."
  6. Return to step 1 for the next skill area
  7. Repeat until complete

- **WHEN TO USE TOUGH QUESTIONS (IMPORTANT):**
  * Use generate_tough_question at least 1-2 times during the technical section
  * Use it when the candidate is answering regular questions too easily
  * Use it to really test the depth of knowledge on their strongest skill
  * Tough questions reveal the TRUE capability of a candidate
  * Match the performance parameter to how they've been doing

- **When get_next_interview_question or generate_tough_question returns "INTERVIEW_QUESTIONS_COMPLETE":**
  - Say: "That covers the technical evaluation well. Now, let's wrap up."
  - Move to Section 5

- **If candidate struggles with a question:**
  - Offer encouragement: "That's a challenging one. Would you like me to rephrase it?"
  - If still struggling: "That's okay, let's move to the next question." Then call the tool again.
t
Thanks — this is a great, detailed report. I can see you’ve implemented the same tool interface for both the pipeline and realtime flows and that tools (decorated with @function_tool) work in the pipeline but not when driving the RealtimeModel. I’m responding to your question: why does the realtime model not call tools while the pipeline method does? Short answer • Realtime models do not trigger the same function/tool-calling mechanism that the pipeline (STT → LLM → TTS) uses. That’s why your tools run in the pipeline flow but are not invoked when you switch to the RealtimeModel. Why this happens (concise) • Pipeline approach separates STT, LLM, and TTS so the LLM stage can explicitly execute function/tool calls (the @function_tool based flow is supported there). • RealtimeModel uses a different, integrated realtime API flow for processing audio and producing text responses. The Realtime API does not expose or run user-defined function calls in the same way, so parameters like
tool_choice="auto"
and the agent function decorators are ignored for tool execution during realtime sessions. • Practically: Realtime sessions are optimized for low-latency, stateful audio/text streaming, not for the agent-style function-invocation lifecycle the pipeline supports. What you can do (recommended options) • Continue using the pipeline (STT → LLM → TTS) for sections that require dynamic tool execution. This retains full agent/function-calling behavior and is the simplest way to preserve your existing tools like
detect_candidate_skills
,
get_next_interview_question
,
generate_followup_question
, etc. • If you must use the RealtimeModel for low-latency voice interactions, move tool execution server-side by: ◦ Receiving the full transcribed text from Realtime (or using the Realtime transcription output you have). ◦ Running your tool-selection and function execution logic on your server when the transcription indicates the action should occur. ◦ Feeding the tool result back into the Realtime session (as a prompt or event) so the model can continue the interview flow. ◦ Note: this is effectively emulating function-calling externally since the Realtime API won’t directly invoke your decorated tools. • Use Realtime only for conversational parts that don’t require tool invocation (e.g., small talk, clarifications), and switch to pipeline mode for structured interview flows that require deterministic tool calls. Quick diagnostics I can help with • Do you want to confirm whether the Realtime session is returning transcription text at the moments you expect a tool call? If yes, share a short excerpt of the realtime transcript + timestamps where you expect the tool to trigger. • Do you prefer a solution that keeps Realtime for audio latency but implements server-side tool handling, or do you prefer switching the entire interview to pipeline mode for full agent/tool support? If you tell me which path you prefer, I’ll give a short step-by-step plan you can implement (either server-side trigger pattern for Realtime, or how to structure the pipeline to match your interview sections while preserving low-latency audio). Sources: OpenAI and LiveKit partner to turn Advanced Voice into an API | LiveKit | Realtime models overview | LiveKit Documentation | The ReAct Pattern for Voice Agents and How AI Agents Think, Act, and Respon... | OpenAI Realtime API plugin guide | LiveKit Documentation | Sequential Pipeline Architecture for Voice Agents | LiveKit, with interactive elements
a
according to livekit how much interview can happen with one agent worker
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!