2026 年 3 月
今月のプラットフォーム全体の API、PVC、クライアントライブラリのアップデートは Changelog 2026(2026 年 3 月)に記載されています。
2026 年 2 月 4 日
AgentUpdateCall 出力イベント
会話中に通話設定を動的に更新するための AgentUpdateCall イベントが追加されました:
from line.events import AgentUpdateCall
# In an agent's process method:
yield AgentUpdateCall(voice_id="5ee9feff-1265-424a-9d7f-8e4d431a12c7")
yield AgentUpdateCall(pronunciation_dict_id="dict-123")
| フィールド | 説明 |
|---|
voice_id | エージェントのボイスを更新します |
pronunciation_dict_id | 発音辞書を更新します |
すべてのフィールドはオプションで、設定したフィールドのみが更新されます。詳細は イベント を参照してください。
2026 年 2 月 1 日
Line SDK v0.2 — メジャーリリース
Line SDK v0.2 をリリースしました。シンプルさ、ストリーミングパフォーマンス、シームレスな LLM 統合に焦点を当てた、音声エージェントフレームワークの全面的な再設計です。このリリースでは、以前のイベントバスシステムを置き換える新しい async iterable アーキテクチャを導入しています。
破壊的変更: v0.2 は v0.1.x との後方互換性がありません。詳細なアップグレード手順については以下の マイグレーションガイド を参照してください。
何が変わるのか? Line SDK v0.2 により、音声エージェントの構築がはるかにシンプルになります。複数のコンポーネント(システム、ブリッジ、ノード)を手動で組み合わせる代わりに、エージェントを返す単一の関数を書くだけになります。SDK が音声、割り込み、会話フローを自動的に処理します。
なぜアップグレードするのか?
- 開発の高速化 — ボイラープレートコードが減り、エージェントを数日ではなく数時間で構築可能
- メンテナンスの容易さ — 可動部分が少ないため、バグが減りデバッグが簡単
- より高い信頼性 — エラー処理、リトライ、フォールバックモデルが組み込み
- より高い柔軟性 — コード変更なしに 100 以上の AI プロバイダー(OpenAI、Anthropic、Google など)を切り替え可能
- 強力なツール — Web 検索、通話転送、マルチエージェントのハンドオフなどを 1 行のコードで追加
v0.2 の新機能
シンプルになったエージェントアーキテクチャ
新しいアーキテクチャでは、VoiceAgentSystem、Bus、Bridge、ReasoningNode パターンを単一の async iterable 関数で置き換えています:
import os
from line import CallRequest
from line.llm_agent import LlmAgent, LlmConfig, end_call
from line.voice_agent_app import AgentEnv, VoiceAgentApp
async def get_agent(env: AgentEnv, call_request: CallRequest):
return LlmAgent(
model="anthropic/claude-haiku-4-5-20251001",
api_key=os.getenv("ANTHROPIC_API_KEY"),
tools=[end_call],
config=LlmConfig(
system_prompt="You are a helpful assistant.",
introduction="Hello! How can I help you today?",
),
)
app = VoiceAgentApp(get_agent=get_agent)
利点:
- ボイラープレートコードの削減
- 手動のイベントルーティングやブリッジ構成が不要
- 会話履歴の自動管理
- 組み込みの割り込み処理
- 迅速で簡単なツール定義
LiteLLM 経由の組み込み LLM サポート
LlmAgent は LiteLLM を介して 100 以上の LLM プロバイダーへの統合アクセスを提供します:
# OpenAI
LlmAgent(model="gpt-5-nano", api_key=os.getenv("OPENAI_API_KEY"), ...)
# Anthropic
LlmAgent(model="anthropic/claude-haiku-4-5-20251001", api_key=os.getenv("ANTHROPIC_API_KEY"), ...)
# Google Gemini
LlmAgent(model="gemini/gemini-2.5-flash-preview-09-2025", api_key=os.getenv("GEMINI_API_KEY"), ...)
# With fallbacks
LlmAgent(
model="gpt-5-nano",
config=LlmConfig(fallbacks=["anthropic/claude-haiku-4-5-20251001", "gemini/gemini-2.5-flash-preview-09-2025"]),
...
)
宣言的なツールシステム
シンプルなデコレーターを使ってエージェントの機能を定義できます。3 種類のツールで一般的なシナリオをカバーします:
| ツールタイプ | デコレーター | 内容 | 用途の例 |
|---|
| Loopback | @loopback_tool | 情報を取得し、その後エージェントが自然に回答を話す | 注文ステータスの確認、口座残高の照会 |
| Passthrough | @passthrough_tool | 追加の AI 処理なしで即時にアクションを実行 | 通話の終了、電話番号への転送 |
| Handoff | @handoff_tool | 会話を別の専用エージェントに引き継ぐ | スペイン語サポートへのルーティング、課金部門へのエスカレーション |
from typing import Annotated
from line.llm_agent import loopback_tool, passthrough_tool, handoff_tool
from line.events import AgentEndCall
@loopback_tool
async def get_weather(ctx, city: Annotated[str, "City name"]) -> str:
"""Get current weather for a city."""
return f"72°F and sunny in {city}"
@passthrough_tool
async def end_call(ctx):
"""End the call."""
yield AgentEndCall()
@handoff_tool
async def transfer_to_support(ctx, event):
"""Transfer to support agent."""
async for output in support_agent.process(ctx.turn_env, event):
yield output
バックグラウンドでのツール実行
長時間実行されるツールは、LLM をブロックせずにバックグラウンドで実行できます:
from typing import Annotated
from line.llm_agent import loopback_tool
@loopback_tool(is_background=True)
async def check_bank_balance(ctx, account_id: Annotated[str, "Account ID"]):
"""Check account balance (may take a few seconds)."""
yield "Checking your balance..." # Immediate acknowledgment
balance = await api.get_balance(account_id) # Long operation
yield f"Your balance is ${balance:.2f}" # Triggers new LLM completion
組み込みツール
よく使う操作はすぐに利用できます:
from line.llm_agent import end_call, send_dtmf, transfer_call, web_search, agent_as_handoff
agent = LlmAgent(
tools=[
end_call, # End the call
send_dtmf, # Send DTMF tones
transfer_call, # Transfer to phone number
web_search, # Real-time web search
agent_as_handoff(other_agent, name="transfer_to_billing"),
],
...
)
マルチエージェントのワークフロー
agent_as_handoff で高度なエージェントルーティングを作成します:
spanish_agent = LlmAgent(
model="gpt-5-nano",
config=LlmConfig(system_prompt="Speak only in Spanish.", ...),
...
)
main_agent = LlmAgent(
tools=[
agent_as_handoff(
spanish_agent,
handoff_message="Transferring to Spanish support...",
name="transfer_to_spanish",
description="Transfer when user requests Spanish.",
),
],
...
)
構造化されたイベントシステム
イベントは、エージェントが外部の世界と通信する仕組みです。出力イベント はエージェントが取るアクション(発話、通話終了)です。入力イベント は通話中に発生する出来事(ユーザーの発話、通話開始)です。
出力イベント(エージェント → ハーネス):
AgentSendText — 話すテキストを送信
AgentEndCall — 通話を終了
AgentTransferCall — 別の番号に転送
AgentSendDtmf — DTMF トーンを送信
AgentToolCalled / AgentToolReturned — ツール実行の追跡
LogMetric / LogMessage — オブザーバビリティ
入力イベント(ハーネス → エージェント):
CallStarted / CallEnded — 通話ライフサイクル
UserTurnStarted / UserTurnEnded — ユーザーの発話
UserTextSent / UserDtmfSent — ユーザーのコンテンツ
AgentHandedOff — ハンドオフ通知
すべての入力イベントには、完全な会話コンテキストを含む history フィールドが含まれます。
強化された設定
エージェントの思考と応答の調整方法。LlmConfig を使うと、AI のパーソナリティ、応答の長さ、創造性、信頼性を制御できます:
LlmConfig(
system_prompt="You are a helpful assistant.",
introduction="Hello! How can I help?",
# Sampling parameters
temperature=0.7,
max_tokens=1024,
top_p=0.95,
# Resilience
num_retries=2,
fallbacks=["gpt-5-nano"],
timeout=30.0,
# Provider-specific options
extra={"reasoning_effort": "high"},
)
v0.1.x から v0.2 へのマイグレーションガイド
このガイドでは、既存の v0.1.x エージェントを v0.2 にアップグレードする手順を解説します。マイグレーションでは、インポートの更新、エージェントのセットアップの簡素化、新しいツールシステムの採用を行います。ほとんどのエージェントは 1 時間以内にマイグレートできます。
変更点の概要
| v0.1.x | v0.2 |
|---|
VoiceAgentSystem + Bus + Bridge | get_agent コールバックを持つ VoiceAgentApp |
ReasoningNode のサブクラス | LlmAgent またはカスタム Agent プロトコル |
call_handler(system, request) | get_agent(env, request) -> Agent |
| 手動のイベントルーティング | フィルターによる自動的なイベントディスパッチ |
process_context() メソッド | process(env, event) の async iterable |
ステップ 1: インポートを更新
# v0.1.x
from line.voice_agent_app import VoiceAgentApp
from line.voice_agent_system import VoiceAgentSystem
from line.bridge import Bridge
from line.nodes import ReasoningNode
from line.events import (
AgentSpeechSent,
UserTranscriptionReceived,
EndCall,
TransferCall,
)
# v0.2
from line.voice_agent_app import VoiceAgentApp, AgentEnv
from line.llm_agent import LlmAgent, LlmConfig
from line.llm_agent import end_call, transfer_call, loopback_tool, passthrough_tool
from line.events import (
AgentSendText,
AgentEndCall,
AgentTransferCall,
UserTurnEnded,
CallStarted,
)
ステップ 2: VoiceAgentSystem を get_agent に置き換える
v0.1.x では、bridge.on() を介してイベントルーティングを手動で構成していました。v0.2 では、カスタマイズ可能な run および cancel フィルターによってイベントディスパッチが自動的に行われます。
from line.voice_agent_app import VoiceAgentApp
from line.voice_agent_system import VoiceAgentSystem
from line.bridge import Bridge
from line.nodes import ReasoningNode
from line.events import (
UserTranscriptionReceived,
UserStoppedSpeaking,
DTMFInputEvent,
)
class MyReasoningNode(ReasoningNode):
async def process_context(self, context):
# Your LLM logic here
response = await call_llm(context.messages)
yield AgentResponse(content=response)
async def call_handler(system: VoiceAgentSystem, call_request):
node = MyReasoningNode(system_prompt="You are helpful.")
bridge = Bridge(node)
system.with_speaking_node(node, bridge)
# Manual event routing with bridge.on()
bridge.on(UserTranscriptionReceived).map(node.add_event)
bridge.on(UserStoppedSpeaking).stream(node.generate).broadcast()
# DTMF events required explicit routing
bridge.on(DTMFInputEvent).map(node.handle_dtmf)
await system.start()
await system.send_initial_message("Hello!")
await system.wait_for_shutdown()
app = VoiceAgentApp(call_handler=call_handler)
Run および Cancel フィルター
フィルターは通話中のエージェントの動作を制御します:
- Run フィルター はエージェントが応答するトリガー(例:ユーザーが発話を終えたとき)を決定します
- Cancel フィルター はエージェントを中断するイベント(例:ユーザーがエージェントに重ねて話し始めたとき)を決定します
エージェントだけを返す代わりに、タプルを返すことでこれらをカスタマイズできます:
from typing import Union, Tuple
AgentSpec = Union[Agent, Tuple[Agent, run_filter, cancel_filter]]
| フィルター | 目的 | デフォルト |
|---|
| run_filter | エージェント処理をトリガーするイベント | [CallStarted, UserTurnEnded, CallEnded] |
| cancel_filter | 実行中のエージェントタスクをキャンセルするイベント | [UserTurnStarted] |
例: DTMF 入力に応答するエージェント
from line.events import (
CallStarted, CallEnded, UserTurnEnded, UserTurnStarted, UserDtmfSent
)
async def get_agent(env: AgentEnv, call_request: CallRequest):
agent = LlmAgent(...)
# Include UserDtmfSent in run_filter to process DTMF
run_filter = [CallStarted, UserTurnEnded, UserDtmfSent, CallEnded]
cancel_filter = [UserTurnStarted]
return (agent, run_filter, cancel_filter)
例: 中断されないエージェント
async def get_agent(env: AgentEnv, call_request: CallRequest):
agent = LlmAgent(...)
# Empty cancel_filter = agent won't be interrupted
run_filter = [CallStarted, UserTurnEnded, CallEnded]
cancel_filter = []
return (agent, run_filter, cancel_filter)
例: カスタムフィルター関数
def my_run_filter(event: InputEvent) -> bool:
"""Only process events during business hours."""
if isinstance(event, CallStarted):
return is_business_hours()
return isinstance(event, (UserTurnEnded, CallEnded))
async def get_agent(env: AgentEnv, call_request: CallRequest):
agent = LlmAgent(...)
return (agent, my_run_filter, [UserTurnStarted])
ステップ 3: イベント処理をマイグレート
# Event names
AgentSpeechSent # Agent spoke
UserTranscriptionReceived # User spoke
EndCall # End call
TransferCall # Transfer call
# Manual event handling in ReasoningNode
class MyNode(ReasoningNode):
async def process_context(self, context):
for event in context.events:
if isinstance(event, UserTranscriptionReceived):
user_message = event.transcription
ステップ 4: カスタムツールをマイグレート
# Manual tool handling in ReasoningNode
class MyNode(ReasoningNode):
async def process_context(self, context):
# Parse tool calls from LLM response
if tool_call := extract_tool_call(response):
result = await self.execute_tool(tool_call)
# Manually add to context and call LLM again
context.add_tool_result(result)
response = await call_llm(context)
ステップ 5: マルチエージェントパターンをマイグレート
# Manual agent switching
class MainNode(ReasoningNode):
def __init__(self, spanish_node):
self.spanish_node = spanish_node
self.use_spanish = False
async def process_context(self, context):
if self.should_switch_to_spanish(context):
self.use_spanish = True
# Complex manual state management
削除された API
v0.1.x の以下の API は削除され、直接の代替はありません:
| 削除済み | 代替 |
|---|
VoiceAgentSystem | get_agent を持つ VoiceAgentApp を使用 |
Bus | イベントは自動的にディスパッチされる |
Bridge | AgentSpec の run/cancel フィルターを使用 |
ReasoningNode | LlmAgent を使うか、Agent プロトコルを実装 |
ConversationHarness | ConversationRunner によって内部的に処理 |
EventsRegistry | 型付きイベントクラスを直接使用 |
カスタムエージェントプロトコル
LlmAgent を超えるカスタムロジックが必要な場合は、Agent プロトコルを実装します:
from typing import AsyncIterable
from line.events import (
InputEvent,
OutputEvent,
AgentSendText,
CallStarted,
UserTurnEnded,
)
class CustomAgent:
"""Custom agent implementing the Agent protocol."""
async def process(self, env, event: InputEvent) -> AsyncIterable[OutputEvent]:
if isinstance(event, CallStarted):
yield AgentSendText(text="Hello from custom agent!")
elif isinstance(event, UserTurnEnded):
# Your custom logic here
user_message = event.content[0].content
response = await your_custom_logic(user_message, event.history)
yield AgentSendText(text=response)
破壊的変更のサマリー
このセクションでは、すべての破壊的変更へのクイックリファレンスを提供します。コードのマイグレーション時のチェックリストとしてご利用ください。
イベント名の変更
| v0.1.x | v0.2 |
|---|
AgentSpeechSent | AgentSendText(出力)/ AgentTextSent(入力) |
UserTranscriptionReceived | UserTextSent / UserTurnEnded |
UserStartedSpeaking | UserTurnStarted |
UserStoppedSpeaking | UserTurnEnded |
AgentStartedSpeaking | AgentTurnStarted |
AgentStoppedSpeaking | AgentTurnEnded |
EndCall | AgentEndCall |
TransferCall | AgentTransferCall |
DTMFInputEvent | UserDtmfSent |
DTMFOutputEvent | AgentSendDtmf |
出力イベント vs. 入力イベント: AgentSendText はエージェントに発話させるために yield する出力イベントです。AgentTextSent は発話された内容を確認する 受信 入力イベントです(履歴に表示されます)。
構造の変更
- イベントの履歴: すべての入力イベントに、完全な会話コンテキストを含むオプションの
history フィールドが追加されました。history が None の場合、そのイベントは履歴リスト内にあります。リストが含まれている場合、そのイベントには完全なコンテキストが添付されています。
- ツールイベント:
ToolCall/ToolResult は、構造化された AgentToolCalled/AgentToolReturned に置き換えられました
- イベント ID: すべてのイベントには追跡用の安定した
event_id フィールドが追加されました
設定の変更
| v0.1.x | v0.2 |
|---|
CallRequest.agent.system_prompt | LlmConfig.system_prompt |
CallRequest.agent.introduction | LlmConfig.introduction |
| 手動の LLM パラメータ | LiteLLM の完全サポートを持つ LlmConfig |
LlmConfig.from_call_request(call_request, fallback_system_prompt="...", fallback_introduction="...") を使用すると、Cartesia プレイグラウンドからの設定を自動的に継承しつつ、妥当なデフォルトを提供できます。詳細は Agents ドキュメント を参照してください。
新しい依存関係
v0.2 では以下の依存関係が導入されています:
litellm # Multi-provider LLM support
pydantic # Type validation for events
phonenumbers >= 9.0 # Phone number validation for transfer_call
例で使用する任意の依存関係:
exa-py # Exa web search integration
duckduckgo-search # Fallback web search
ヘルプを得る