Events and error handling

参照元: LiveKit Agents Documentation ロードマップ: 学習ロードマップ

公式ページ: https://docs.livekit.io/reference/agents/events/ 公式サンプル: https://github.com/livekit/agents/blob/main/examples/voice_agents/inactive_user.py 公式サンプル: https://github.com/livekit/agents/blob/main/examples/voice_agents/error_callback.py

What(何についてか)

AgentSession が発行するイベント群と、セッション中の障害に対する回復・終了制御を扱う。対象は会話進行イベント(transcription, state change, speech creation, tool execution)、割り込み観測イベント(overlapping_speech, agent_false_interruption)、終端イベント(close)、およびエラーハンドリング(FallbackAdapter, ErrorEvent)である。

Why(なぜ必要か)

音声エージェントでは「会話品質」と「可用性」を同時に満たす必要がある。イベントを観測しないと、遅延や誤割り込みの原因分解ができない。エラー処理を設計しないと、推論API障害時に会話が途切れる。したがって、本ページの理解は運用可能なエージェント設計の前提になる。

How(どう動くか)

AgentSession は状態変化ごとにイベントを発行する。user_input_transcribed は逐次認識(partial/final)を通知し、conversation_item_added は履歴コミットを通知する。function_tools_executed はツール実行バッチ完了を通知し、metrics_collected はSTT/LLM/TTS/EOUなどの計測値を公開する。agent_state_changeduser_state_changed は状態遷移を公開し、overlapping_speechagent_false_interruption は割り込み判定品質を可視化する。終了時は close が発火し、reasonerror で終端理由を取得できる。

エラー処理は FallbackAdapter による事前冗長化と、ErrorEvent による事後判定で構成される。error.recoverable が真なら継続、偽なら介入が必要という判断軸で運用する。

graph TD
    A[User Speech] --> B[user_input_transcribed]
    B --> C[conversation_item_added]
    C --> D[function_tools_executed]
    D --> E[speech_created]
    E --> F[agent_state_changed]
    A --> G[user_state_changed]
    A --> H[overlapping_speech]
    H --> I[agent_false_interruption]
    F --> J[close]
    K[ErrorEvent] --> L{recoverable?}
    L -->|yes| M[continue session]
    L -->|no| N[notify / handoff / close]

主要イベントの実装判断

user_input_transcribedis_final を持つため、重い処理(DB書き込みや外部API呼び出し)は is_final=True 側に寄せる。partial 更新は表示用途に限定する。

conversation_item_added は履歴にコミットされた単位で通知される。ChatMessage はテキストだけでなく画像・音声コンテンツを含み得るため、ログ設計では item.content の型分岐を前提にする。

function_tools_executed はツール呼び出し完了後の制御点である。zipped() で call/output 対応を確認し、cancel_tool_reply()cancel_agent_handoff() で自動挙動を抑止できる。

speech_created は発話オブジェクト生成イベントであり、音声再生完了保証ではない。speech_handle は生成発話の追跡・制御用ハンドルとして扱う。

close はセッション終端の統一イベントである。運用では close.reason を必ず分岐条件に使い、正常終了と異常終了の後処理を分離する。

公式サンプル読解: inactive_user.py

@session.on("user_state_changed")
def _user_state_changed(ev: UserStateChangedEvent):
    nonlocal inactivity_task
    if ev.new_state == "away":
        inactivity_task = asyncio.create_task(user_presence_task())
        return
 
    # ev.new_state: listening, speaking, ..
    if inactivity_task is not None:
        inactivity_task.cancel()

この実装は away 遷移で監視タスクを開始し、speaking/listening に戻ったらタスクを停止する。user_presence_task() 側では一定間隔で呼びかけを行い、応答がなければ session.shutdown() する。無応答時の段階的エスカレーションをイベント駆動で構成した例である。

公式サンプル読解: error_callback.py

@session.on("error")
def on_error(ev: ErrorEvent):
    if ev.error.recoverable:
        return
 
    session.say(
        "I'm having trouble connecting right now. Let me transfer your call.",
        audio=audio_frames_from_file(custom_error_audio),
        allow_interruptions=False,
    )

この実装は recoverable 判定で処理を分岐し、致命時に事前録音音声で案内する。TTS障害時でも案内を再生できる点が重要である。

@session.on("close")
def on_close(_: CloseEvent):
    ...
    ctx.transfer_sip_participant(participant, "tel:+18003310500")

このサンプルでは close.reason を参照せず転送しているため、終了理由に関係なくSIP転送へ進む設計になっている。実運用では CloseEvent.reason による条件分岐を入れる必要がある。

Key Concepts

用語説明
user_input_transcribedSTT逐次結果イベント。is_final を軸に処理コストを分離する。
conversation_item_added履歴コミットイベント。確定ログ・分析投入の基点。
function_tools_executedツール実行後の統合制御点。reply/handoffの抑止が可能。
metrics_collectedSTT/LLM/TTS/EOU/Interruption の計測値公開イベント。
overlapping_speech重なり音声検知イベント。割り込み判定遅延・確率を観測。
agent_false_interruption誤割り込み確定イベント。復帰可否(resumed)を観測。
ErrorEvent障害通知イベント。error.recoverable が運用分岐の中心。
FallbackAdapterプロバイダ障害時の自動フォールバック機構。

一言まとめ

Events and error handling は、会話進行の可視化と障害時の継続性を同時に設計するための中核リファレンスである。