bored-country-30093
02/21/2026, 9:41 AMtall-airline-16756
02/21/2026, 9:41 AMtall-airline-16756
02/21/2026, 9:41 AMsummarize_chat_ctx=False and repeat the workflow.
1. Make task and agent instructions explicit and narrow:
◦ Ensure each task_group.add() includes a clear id and unambiguous description that states when the task is considered finished.
◦ Add explicit exit/complete criteria so the LLM knows not to probe after completion.
1. Review tool definitions and confidence thresholds:
◦ Confirm no broadly-named clarification tools or general-purpose helpers are available to the LLM during the TaskGroup run, or tighten their guardrails.
1. Reproduce with logging enabled:
◦ Log model calls, tool invocations, and the pre- and post-summary context. The logs will show whether the model regenerated a follow-up because it thought the goal was incomplete or because a tool was triggered.
When to change behavior vs accept it
• If you want strictly linear, deterministic flows: make task descriptions and exit criteria strict, disable summarization, and remove general clarification tools from the TaskGroup scope.
• If adaptive behavior is acceptable (the agent can ask clarifying questions when needed): keep summarization but tighten task descriptions so the model understands the bounds of necessary follow-ups.
If you’d like, tell me:
• How you construct the TaskGroup (code snippet or key options you set), and
• Whether you’re using summarization or any general-purpose tools.
With that I can point out which exact setting or instruction is most likely causing the extra question and suggest a targeted change.
Sources: Tasks and task groups | LiveKit Documentation | Building multi-agent architectures with LiveKit agents | LiveKitbored-country-30093
02/21/2026, 9:47 AMtall-airline-16756
02/21/2026, 9:48 AMbored-country-30093
02/21/2026, 9:50 AMtall-airline-16756
02/21/2026, 9:51 AMuv run agent.py start --log-level=DEBUG
• Python (dev):
uv run agent.py dev --log-level=DEBUG
• Node.js:
pnpm run start --log-level=debug
This increases verbosity for the agent runtime so you’ll see model prompts, tool calls, and internal events.
2) Use verbose test-time output for evals
• For test runs with the evaluation framework:
LIVEKIT_EVALS_VERBOSE=1 uv run pytest -s -o log_cli=true <your-test-file>
This prints full RunResult events (LLM messages, function/tool calls, judgments) useful for replaying the exact flow.
3) Turn on Agent Observability (project/dashboard)
• If enabled in your LiveKit project, Agent Observability provides:
◦ Conversation transcripts and turn-by-turn traces
◦ Timing and metadata for LLM, TTS, and tool calls
◦ Logs and traces you can inspect after a session completes
Note: Observability requires a supported SDK version and that the feature is enabled in project settings. It shows session-level traces (not necessarily real-time).
4) Forward logs to an external monitoring service (recommended for production)
• Configure your project to forward logs to Datadog, CloudWatch, Sentry, or similar.
• This gives persistent searchable logs and easier correlation across runs (recommended over relying solely on short-term agent logs).
5) Add explicit debug logs in your code
• Python example:
import logging
logger = logging.getLogger("myAgent")
logger.setLevel(logging.DEBUG)
logger.debug(f"TaskGroup chat_ctx before prompt: {chat_ctx}")
• Node.js example:
import { log } from '@livekit/agents';
log().debug('TaskGroup chat_ctx before prompt:', chat_ctx);
Log the exact prompt you send the model (system + task context + prior turns) and any tool inputs/outputs. Include identifiers like session ID, task id, and worker id.
6) Capture model input/output and tool calls for the problematic turn
• Ensure logs include:
◦ Full assembled prompt passed to the model (system + assistant + task context)
◦ Any tool invocation and its input/response
◦ Model raw output (including tokens/metadata if available)
• This will show whether the model invented the question, or if a tool call or earlier message triggered it.
7) Reproduce with a minimal test case and logging
• Create a small TaskGroup with 2–3 tasks and no external tools.
• Run with DEBUG logs. If hallucination disappears, reintroduce instructions/tools incrementally until it reappears to isolate the cause.
Quick diagnostic checklist
• Log the pre-prompt that led to the hallucinated question (most important).
• Confirm no general-purpose “clarify” tool is available during the TaskGroup run.
• Verify model settings (temperature, top_p); set temperature to 0.0–0.3 to reduce creative outputs during tests.
If you want, share (redact secrets) the log excerpt for the turn where the hallucination appears:
• The full prompt the model received
• The model response that contains the unexpected question
• Any tool call entries around that turn
I’ll review the log lines and point to the exact trigger (missing context, tool invocation, or instruction wording) and suggest the precise change to stop those extra questions.
Sources: Where to find your Agent Logs | LiveKit | Testing and evaluation | LiveKit Documentation | Streamline troubleshooting with Agent Observability | Job lifecycle | LiveKit Documentationbored-country-30093
02/21/2026, 9:52 AMtall-airline-16756
02/21/2026, 9:52 AMtemperature when you create the LLM used by your AgentSession (the LLM instance your agent uses to generate responses). Lower values make outputs more deterministic and reduce hallucinations.
Examples:
• Python
from livekit.agents import AgentSession
from livekit.plugins import openai
session = AgentSession(
llm=openai.LLM(
model="gpt-4o-mini",
temperature=0.3, # set here
),
# other config...
)
• Node.js / TypeScript
import * as openai from '@livekit/agents-plugin-openai';
const session = new voice.AgentSession({
llm: openai.LLM({
model: "gpt-4o-mini",
temperature: 0.3, // set here
}),
// other config...
});
Recommended values
• 0.0–0.3: very deterministic — best for preventing unexpected questions.
• 0.3–0.5: some flexibility but still controlled.
• >0.7: more creative (not recommended when you need strict, linear behavior).
Extra tips
• Combine a low temperature with explicit, narrow system/agent instructions and strict task exit criteria to prevent the model from inventing follow-ups.
• If you’re still seeing hallucinated questions after lowering temperature, enable DEBUG logs and capture the exact prompt the model received for the offending turn — I can help review it if you paste the redacted prompt and response. Sources: OpenAI LLM plugin guide | LiveKit Documentation | Tasks and task groups | LiveKit Documentationbored-country-30093
02/21/2026, 10:08 AMtall-airline-16756
02/21/2026, 10:09 AMclarify_intent, ask_user) available during the TaskGroup run or add a guard that only allows it when a specific flag is present.
1. Lower temperature and force determinism for tests
◦ Set the LLM temperature to 0.0–0.3 for test runs to reduce creative probing. Reproduce the flow with temperature = 0.0 to see if the diabetes question still appears.
1. Constrain allowed next actions or allowed question templates
◦ Provide the LLM with an explicit list of allowable next-turn outputs (or templates). If the model’s candidate output is not on that list, reject/regen. This enforces linear behavior.
1. Reproduce with a minimal TaskGroup and log
◦ Create a tiny TaskGroup with only the tasks you expect. Run and inspect logs. If the hallucination disappears, incrementally reintroduce instructions/tools until it reappears — this isolates the offending instruction or tool.
Quick diagnostic checklist (high priority)
• Find the log entry for the turn that asked about diabetes. Look at the assembled prompt. That single step usually reveals whether the model inferred a broad goal or a tool was invoked.
• Confirm system prompt wording doesn’t include global goals like “ensure the user’s intent is fully satisfied by probing all related conditions.”
• Confirm no summarization reintroduced broader language (you already turned summarization off, which helps).
If you want, I can do a focused review
• Share (redact secrets) these items and I’ll point to the exact change to stop the diabetes question:
◦ The agent/system prompt
◦ The task descriptions for the tasks just before the hallucination
◦ The assembled prompt and model response from the debug log for that turn
◦ Current temperature and tool list
Send those snippets and I’ll mark the exact phrase(s) that caused the model to probe and provide the minimal edits to eliminate the extra question.
Sources: Tasks and task groups | LiveKit Documentation | How to Test Your Agent Using Another Agent | LiveKit | Prompting guide | LiveKit Documentation | Azure OpenAI LLM plugin guide | LiveKit Documentationbored-country-30093
02/21/2026, 10:12 AMtall-airline-16756
02/21/2026, 10:12 AMinstructions, state the single allowed purpose, required fields, and a strict “do not ask anything else” rule.
• Example phrasing to include near the top of each task:
◦ “Your ONLY job is to [collect X / ask Y].”
◦ “Ask at most once (or at most twice) for missing information.”
◦ “If the user refuses, record refusal and STOP.”
◦ “DO NOT ask about conditions or topics not listed as tasks in this TaskGroup.”
Python example (task definition):
class CollectDOBTask(AgentTask[DOBResult]):
def __init__(self):
super().__init__(
instructions="""
Task: Collect the user's date of birth (MM-DD-YYYY).
- Ask exactly: 'Please provide your date of birth (MM-DD-YYYY).'
- If user gives a valid DOB, call set_dob(date) and STOP.
- If user provides incomplete DOB, ask once for the missing part and STOP.
- If user refuses or says 'I don't want to provide', call set_dob('REFUSED') and STOP.
- DO NOT ask about any other health conditions or additional screening questions.
""",
)
2) Immediately complete the task in your tool/handler
• When the required data or refusal is received, call self.complete(result) (or your framework’s equivalent) right away so control returns to the TaskGroup and the model won’t continue probing.
Python example (tool that saves and completes):
@function_tool()
async def set_dob(self, ctx: RunContext, date_of_birth: str):
# Save whatever persistence you need...
self.complete(DOBResult(date_of_birth=date_of_birth))
# Do not send any extra assistant messages here.
3) Use strict description text when adding tasks to the TaskGroup
• The description is visible to the LLM as meta-guidance. Make it explicit about non-regression.
• Example:
task_group.add(
lambda: CollectDOBTask(),
id="dob",
description="Collect DOB only. After DOB is set (or refused), DO NOT return to this task or ask unrelated questions."
)
4) After a task completes, programmatically control the next turn
• Don’t rely on the model to decide whether to ask more questions. Explicitly instruct the agent what to do next (e.g., proceed to next task or finish).
• Example after awaiting TaskGroup:
results = await task_group
# Immediately produce a bounded reply that does NOT invite extra screening
await session.generate_reply(instructions="All required screening tasks complete. Do not ask additional health questions.")
5) Add parent-agent guardrails in the system prompt
• Top-level rules prevent the model from inventing topics across the whole session.
• Example lines to add to the system prompt:
◦ “Never ask about topics not defined as tasks for this session.”
◦ “After all tasks are completed, do not ask follow-up screening questions unless explicitly requested by the user.”
6) Combine with runtime controls
• Set model temperature low (0.0–0.3) during tests to reduce creativity.
• Remove or gate any broad “clarify” tools during this TaskGroup run.
7) Test with logging and minimal reproduction
• Run a minimal TaskGroup (2–3 tasks) with DEBUG logging enabled and temperature = 0.0 to confirm no extraneous questions appear.
• If an unexpected question still appears, capture the assembled prompt that produced it and inspect which instruction line or tool call preceded it.
Checklist summary (short):
• Add explicit “DO NOT ask X” lines in each task’s instructions.
• Call self.complete(...) immediately when done.
• Use strict description when adding tasks to the group.
• Make the parent agent explicitly forbid extra questions after completion.
• Lower temperature and disable broad clarification tools for testing.
If you want, paste (redact any secrets) one task’s current instructions and the surrounding system prompt and I’ll rewrite each to the minimal, strict wording that stops extra probes (I can also point out exactly where to call self.complete() in your code).
Sources: Prompting guide | LiveKit Documentation | Tasks and task groups | LiveKit Documentation | Survey Calling Agent | LiveKit Documentationbored-country-30093
02/21/2026, 10:14 AMtall-airline-16756
02/21/2026, 10:15 AMself.complete(...) or equivalent) as soon as you have the result, and avoid sending any extra assistant message from inside the task.
• This prevents the LLM from remaining “active” in task scope and inventing follow-ups.
Example (Python tool that completes):
@function_tool()
async def set_task_result(self, ctx: RunContext, result_value: str):
# persist result...
self.complete(TaskResult(value=result_value))
# do NOT generate any further assistant messages here
2) Insert an explicit deterministic transition message
• Right after a task completes and control returns to your agent code, programmatically inject a short assistant-turn that instructs the model what to do next (and what not to do). This replaces an open-ended model continuation with a constrained, explicit instruction.
Example:
# After await task_group or after the specific task completes:
await session.generate_reply(
instructions="Task X is complete. DO NOT ask any additional screening or unrelated questions. Proceed to Task Y."
)
3) Add explicit “no new topics” guard in both task and transition prompts
• In each task's instructions and in the transition message, include a line like:
◦ “Do not ask about conditions or topics that are not listed as tasks in this TaskGroup.”
◦ “If the next task is defined, proceed directly — do not ask additional screening questions.”
4) Use TaskGroup description to discourage re-entry
• When adding tasks, set description text that tells the LLM not to regress:
task_group.add(lambda: SomeTask(), id="some", description="Collect X only. After completion do not return or ask unrelated questions.")
5) Gate or remove general clarification tools during transitions
• If you expose a general-purpose clarification tool or allow open tool invocation across tasks, temporarily remove it or add a guard so it is only callable when a specific explicit flag exists. Broad clarification tools are a common source of unexpected questions.
6) Force deterministic model behavior at the boundary
• For the model call that occurs at task handoff, set temperature to 0.0 (or very low) so it produces deterministic, directive-following text instead of inventing probes.
• If you can set model parameters per-call, apply low temperature for the transition prompt only.
7) Shorten and prioritize system-level guardrails
• Put the “do not ask outside the task list” rule at the very top of the system prompt so it has priority when the model composes responses during transitions.
8) Log the exact handoff prompt to debug remaining cases
• Capture and inspect the exact assembled prompt at the moment the hallucination occurs (system + conversation + task context). If you still see the diabetes question after applying the above, paste the redacted pre-prompt and model response and I’ll point to the exact offending line.
Minimal reproduction strategy (to isolate cause)
1. Create a tiny TaskGroup with two tasks (A -> B).
2. In both tasks, add strict “ask only X; do not ask anything else” instructions and immediate self.complete() in the tool.
3. Run with temperature = 0.0 and DEBUG logging.
4. If the hallucination still appears, inspect the exact handoff prompt; that will reveal whether the model inferred a broader goal or a tool/regression was triggered.
If you’d like, share these three redacted items for the transition where the diabetes question occurs:
• The top of your system prompt (first ~6–10 lines)
• The two task instructions and description fields (task before and after transition)
• The assembled prompt and model response from the debug log for that transition
I’ll point to the exact phrase or missing guard that’s causing the model to probe and provide the minimal edit to prevent it.