ツールを使うと、エージェントがアクションを実行したり情報を取得したりできます。SDK は会話フローへの影響が異なる 3 種類のツールパラダイムをサポートしています。
ツールの定義
適切に型注釈された関数はツールとして使用できます。SDK は関数の docstring を説明として、パラメータの型注釈を使用します:
from typing import Annotated
async def get_weather(
ctx,
city: Annotated[str, "The city to check weather for"],
units: Annotated[str, "celsius or fahrenheit"] = "fahrenheit"
):
"""
Look up the current weather in a given city.
"""
return f"72°F and sunny in {city}"
すべてのツールの最初のパラメータは ctx(ツールコンテキスト)である必要があります。これは会話状態へのアクセスを提供し、将来的な互換性のために必須です。ツールのパラメータは ctx の後に続けて定義します。
ツールの種類
tools に渡されるプレーンな関数は、自動的にループバックツールとしてラップされます。明示的な制御には、デコレーター(@loopback_tool、@passthrough_tool、@handoff_tool)を使用してください。
デフォルトの動作です。ツールの結果は LLM に返され、LLM はそれを使って応答の生成を続行できます。
from line.llm_agent import loopback_tool
@loopback_tool
async def get_account_balance(ctx, account_id: Annotated[str, "The account ID"]):
"""Look up the balance for a customer account."""
balance = await api.get_balance(account_id)
return f"${balance:.2f}"
用途: 情報取得、計算、API クエリ。
出力イベントは LLM を経由せずに、直接ユーザーに送信されます。決定的なアクションに使用します。
from line.llm_agent import passthrough_tool
from line.events import AgentSendText, AgentEndCall
@passthrough_tool
async def end_call_with_message(ctx, message: Annotated[str, "Goodbye message"]):
"""End the call with a custom goodbye message."""
yield AgentSendText(text=message)
yield AgentEndCall()
用途: 通話制御(EndCall、TransferCall、SendDtmf)、決定的な応答。
制御を別のハンドラーに移譲します。以降のイベントはすべて、元のエージェントではなくハンドオフ先にルーティングされます。
from typing import Annotated
from line.llm_agent import handoff_tool
from line.events import AgentHandedOff, AgentSendText, UserTurnEnded, AgentEndCall
@handoff_tool
async def run_satisfaction_survey(
ctx,
customer_name: Annotated[str, "The customer's name"],
event
):
"""Hand off to a customer satisfaction survey at the end of the call."""
if isinstance(event, AgentHandedOff):
# First call - send introduction
yield AgentSendText(
text=f"Thank you for your call, {customer_name}. "
"Please stay on the line for a brief satisfaction survey. "
"On a scale of 1 to 5, how would you rate your experience today?"
)
return
# Subsequent calls - handle survey responses
if isinstance(event, UserTurnEnded):
user_response = event.content[0].content if event.content else ""
yield AgentSendText(text=f"You rated us {user_response}. Thank you for your feedback!")
yield AgentEndCall()
用途: カスタムのマルチステップフロー、独自のロジックを持つ専用ハンドラー。
ハンドオフツールを使用する場合、event パラメータはタイミングによって異なる値を受け取ります:
- 最初の呼び出し:
event は AgentHandedOff。これを使って遷移メッセージを送信します
- その後の呼び出し:
event は実際の InputEvent(UserTurnEnded など)
ハンドオフが発生すると、元のエージェントはそれ以降イベントを受け取りません。ハンドオフツール関数が、それ以降のすべての会話ターンを処理します。
別の LlmAgent にハンドオフするには、生の @handoff_tool を書く代わりに agent_as_handoff ヘルパーを使用してください。委譲が自動的に処理されます。
組み込みツール
import os
from line.llm_agent import LlmAgent, LlmConfig, end_call, knowledge_base, send_dtmf, transfer_call, web_search
agent = LlmAgent(
model="anthropic/claude-haiku-4-5-20251001",
api_key=os.getenv("ANTHROPIC_API_KEY"),
tools=[end_call, send_dtmf, transfer_call, web_search, knowledge_base],
config=LlmConfig(...),
)
| ツール | 説明 | 用途 |
|---|
end_call | 通話を終了する | ユーザーが「さようなら」と言ったとき、またはエージェントの目的が達成されたとき |
transfer_call | 別の番号(E.164 形式)に転送する | 人間のエージェントへのエスカレーション、部署へのルーティング |
web_search | リアルタイム情報のために Web を検索する | 最新の出来事、リアルタイム価格、LLM が知らない最近のニュース |
knowledge_base | エージェントに添付されたドキュメントを参照する | LLM が推測すべきでない製品情報、ポリシー、内部の事実。ナレッジベース を参照。 |
例:
# End call: Let the LLM decide when conversation is complete
tools=[end_call] # LLM calls this when user says "thanks, bye!"
# Transfer: Route to human support
tools=[transfer_call] # LLM calls transfer_call(target_phone_number="+18005551234")
# Web search with custom context size
tools=[web_search(search_context_size="high")] # More context for complex queries
# Knowledge base: look up the agent's attached documents
tools=[knowledge_base] # LLM calls this to answer from uploaded docs
# Knowledge base scoped to a metadata filter with a tailored prompt
tools=[knowledge_base(
filters={"category": "billing"},
top_k=10,
description="Look up billing and payment policy details.",
)]
ドキュメントのアップロードおよびパラメータの完全なリストについては ナレッジベース を参照してください。
end_call
現在の通話を終了し、切断します。エージェントの最終的な発話が完了した後に実際の切断が行われるため、ユーザーは切断前に終了の挨拶を最後まで聞くことができます。
from line.llm_agent import LlmAgent, LlmConfig, end_call
agent = LlmAgent(
model="anthropic/claude-haiku-4-5-20251001",
api_key=os.getenv("ANTHROPIC_API_KEY"),
tools=[end_call],
config=LlmConfig(...),
)
デフォルトでは、end_call は次のいずれかの条件を満たす場合にのみ通話を終了する保守的なポリシーを使用します:
- ユーザーの目的が完全に達成されている
- ユーザーが明確にお別れを述べている
- エージェントが自然なお別れを述べている
カスタムの説明
ユースケースに合わせてカスタマイズした説明を提供することを推奨します。説明はデフォルトを 完全に置き換えます(追記ではありません)。そのため、do/don’t の明示的なガイダンスを含む完全な指示を含めてください。
from line.llm_agent import end_call
# Restaurant reservation agent
tools=[end_call(description="""Ends the call and disconnects.
Call when ALL of the following are true:
- The reservation is confirmed with date, time, party size, and name.
- You have repeated the reservation details back to the guest.
- The guest confirms the details are correct or says goodbye.
Do not call when:
- The guest asks to modify the reservation.
- Details are missing or unconfirmed.
- The guest says 'okay' or 'thanks' without an explicit goodbye.
If unsure, ask: 'Is there anything else I can help you with for your reservation?'
""")]
# Order confirmation agent
tools=[end_call(description="""Ends the call and disconnects.
Call when ALL of the following are true:
- The order is placed and confirmed.
- You have provided the order number and estimated delivery time.
- The customer acknowledges with a goodbye phrase.
Do not call when:
- The customer has questions about their order.
- Payment has not been confirmed.
- The customer says 'got it' without saying goodbye.
""")]
| パラメータ | 型 | 説明 |
|---|
description | Optional[str] | デフォルトの説明を完全に置き換えます。LLM が通話を終了すべきタイミングを示す完全な指示を含めてください。 |
agent_as_handoff
別の Agent からハンドオフツールを作成します。マルチエージェントワークフローを実装する最も簡単な方法です。
from line.llm_agent import LlmAgent, LlmConfig, agent_as_handoff, end_call, UpdateCallConfig
spanish_agent = LlmAgent(
model="gpt-5-nano",
api_key=os.getenv("OPENAI_API_KEY"),
tools=[end_call],
config=LlmConfig(
system_prompt="You speak only in Spanish.",
introduction="¡Hola! ¿Cómo puedo ayudarte?",
),
)
main_agent = LlmAgent(
model="anthropic/claude-haiku-4-5-20251001",
api_key=os.getenv("ANTHROPIC_API_KEY"),
tools=[
end_call,
agent_as_handoff(
spanish_agent,
handoff_message="Transferring to Spanish support...",
update_call=UpdateCallConfig(
voice_id="spanish-voice-id",
pronunciation_dict_id="spanish-pronunciation-dict-id"
),
name="transfer_to_spanish",
description="Use when user requests Spanish.",
),
],
config=LlmConfig(...),
)
| パラメータ | 型 | 説明 |
|---|
agent | Agent | ハンドオフ先のエージェント |
handoff_message | Optional[str] | ハンドオフ前に話されるメッセージ |
update_call | Optional[UpdateCallConfig] | ハンドオフ前に通話設定(ボイス、発音、言語)を更新するための任意の設定 |
name | Optional[str] | LLM 向けのツール名 |
description | Optional[str] | LLM がこのツールを使用すべきタイミング |
呼び出されると、agent_as_handoff は自動的にハンドオフメッセージを送信し、指定されていれば通話設定を更新し、新しいエージェントの導入をトリガーし、以降のすべてのイベントをそちらにルーティングします。
ループバック、パススルー、ハンドオフツールを組み合わせた完全なマルチエージェント例については 高度なパターン を参照してください。
長時間実行ツール
デフォルトでは、エージェントが中断されるとツール呼び出しは終了します(ただし、すでに生成された推論内容やツール呼び出しのレスポンス値は、次の生成での利用のために保持されます)。
完了までに長時間かかることが想定されるツールには、is_background=True を設定してください。中断に関わらずツールはバックグラウンドで完了するまで実行され、その後 LLM にループバックしてレスポンスを生成します。
from typing import Annotated
from line.llm_agent import loopback_tool
@loopback_tool(is_background=True)
async def search_database(ctx, query: Annotated[str, "Search query"]) -> str:
"""Search the database - may take several seconds."""
results = await slow_database_search(query)
return format_results(results)
@loopback_tool(is_background=True)
async def generate_report(ctx, report_type: Annotated[str, "Type of report"]) -> str:
"""Generate a detailed report - runs in background."""
report = await compile_report(report_type)
return report
組み込みの knowledge_base ツールも is_background を受け付けるため、取得処理が進行中でもエージェントは話し続けることができます:
from line.llm_agent import knowledge_base
# Knowledge base lookups run in the background
tools=[knowledge_base(is_background=True, top_k=10)]
バックグラウンドツールは次のような場合に有用です:
- 操作が一般的なユーザーの忍耐時間を超える可能性がある場合(例:複雑な検索、レポート生成)
- 操作の完了中にユーザーが話せるようにしたい場合
- ユーザーが別の質問で割り込んだとしても結果を届けたい場合