セッションイベントストリーム
イベントを送信し、レスポンスをストリーミングし、実行中のセッションを中断またはリダイレクトします。
Claude Managed Agents との通信はイベントベースです。ユーザーイベントをエージェントに送信し、ステータスを追跡するためにエージェントイベントとセッションイベントを受け取ります。
イベントタイプ
イベントは2つの方向に流れます。
- ユーザーイベントとシステムイベントは、あなたがエージェントに送信するものです。
user.*イベントはセッションを開始し、進行に合わせてセッションを操縦します。system.messageは、付随するターンとそれ以降のすべてのターンに適用されるシステムレベルのコンテキストを追加します。 - セッションイベント、スパンイベント、エージェントイベントは、セッションの状態とエージェントの進捗を観測できるようにあなたに送信されます。オプトインしたストリーム接続は、イベントデルタも受け取ります。
セッション、スパン、エージェント、ユーザー、システムの各イベントタイプ文字列は、{domain}.{action} という命名規則に従います。ストリーム専用のデルタプレビューイベント(event_start、event_delta)は例外です。完全なカタログについては、リファレンスのイベントタイプを参照してください。Webhook イベントタイプは別物であり、一部の名前はストリームのものと異なります(たとえば、session.status_idle ではなく session.status_idled)。
永続化されるすべてのイベントには、イベントの処理が完了したときに設定される processed_at タイムスタンプが含まれます。あなたが送信するイベントでは、そのイベントが先行するイベントの後ろでまだキューに入っている間、processed_at は null です。例外は user.define_outcome、user.custom_tool_result、user.tool_result で、これらは受信時に処理され、processed_at がすでに設定された状態でエコーバックされます。
イベントの統合
エージェントの作業を開始または継続するには、user.message イベントを送信します。
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Analyze the performance of the sort function in utils.py",
},
],
},
],
)実行中のエージェントを停止するには user.interrupt イベントを送信し、続けて user.message イベントを送信してリダイレクトします。
# Agent is currently analyzing a file...
# Interrupt with a new direction:
client.beta.sessions.events.send(
session.id,
events=[
{"type": "user.interrupt"},
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Instead, focus on fixing the bug in line 42.",
},
],
},
],
)この呼び出しはイベントがキューに入るとすぐに返り、割り込みの processed_at はエージェントがそれを適用するまで null のままです。進行中のモデルレスポンスは即座に停止します。ツール呼び出しの実行中は割り込みの適用に時間がかかることがあり、適用されるまでセッションは running のままです。その後 user.interrupt イベントがストリームに現れ、中断されたターンは session.status_idle イベントで終了します。その stop_reason は end_turn で、自然に終了したターンと同じ値です。中断に固有の停止理由はありません。エージェントは、割り込みの後に送信した user.message で次のターンを開始します。
セッションからイベントをストリーミングして、エージェントの作業中にリアルタイムの更新を受け取ります。ストリームを開いた後に発行されたイベントのみが配信されるため、競合状態を避けるためにイベントを送信する前にストリームを開いてください。
# Open the stream first, then send the user message
with client.beta.sessions.events.stream(session.id) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Summarize the repo README"}],
},
],
)
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
break
case "session.error":
error_message = event.error.message if event.error else "unknown"
print(f"\n[Error: {error_message}]")
breakイベントを取りこぼすことなく既存のセッションに再接続するには、次のようにします。
- 新しいストリームを開きます。
- 完全なイベント履歴をリストして、既に見たイベント ID のセットを初期化します。
- ライブストリームを追跡し、履歴リストで既に返されたイベントをスキップします。
with client.beta.sessions.events.stream(session.id) as stream:
# Stream is open and buffering. List history before tailing live.
history = client.beta.sessions.events.list(session.id)
seen_event_ids = {past_event.id for past_event in history}
# Tail live events, skipping anything already seen
for event in stream:
if event.type == "event_start" or event.type == "event_delta":
# Delta previews aren't enabled on this connection.
continue
if event.id in seen_event_ids:
continue
seen_event_ids.add(event.id)
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
breakセッションの完全なイベント履歴を取得します。
events = client.beta.sessions.events.list(session.id)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")特定のイベントタイプのみを返すには、types フィルターを渡します。
events = client.beta.sessions.events.list(
session.id,
types=["agent.tool_use", "agent.tool_result"],
)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")イベントデルタ
デフォルトでは、エージェントのレスポンステキストはバッファリングされた agent.message イベントとしてストリームに届き、それぞれはそれを生成したモデルリクエストが完了した後にのみ発行されます。「event deltas」(イベントデルタ)を使用すると、モデルがまだ生成している間に、そのテキストをライブプレビューとして段階的にレンダリングできます。プレビューはレスポンスではありません。プレビューはベストエフォートの表示補助であり、バッファリングされた agent.message が常に正式な記録です。プレビューを無視するクライアントでも、完全で正しいストリームを受け取ります。
プレビューへのオプトイン
プレビューはストリーム接続ごとのオプトインです。読み取るストリームに event_deltas[] クエリパラメータを追加し、プレビューしたいイベントタイプごとに1回ずつ繰り返します。[] はシェルのグロブパターンであるため、シェルでリクエストを組み立てる場合は必ず URL を引用符で囲んでください。例では角括弧を %5B%5D としてパーセントエンコードしており、これも機能します。両方のストリームエンドポイントがこのパラメータを受け付けます。GET /v1/sessions/{session_id}/events/stream のセッションレベルのストリームと、各セッションスレッド自身の GET /v1/sessions/{session_id}/threads/{thread_id}/stream のストリームです。受け付けられる値は agent.message と agent.thinking です。それ以外の値は 400 エラーを返し、100 個を超える値を持つリクエストも同様です。サブエージェントのプレビューは、そのサブエージェント自身のスレッドストリームに現れます。
プレビュー対象のイベントが始まると、ストリームは今後のイベントのタイプと id を持つ event_start を発行します。
{
"type": "event_start",
"event": {
"type": "agent.message",
"id": "sevt_01abc..."
}
}agent.message の場合、start の後に増分テキストを持つ event_delta イベントが続きます。各デルタは、拡張対象のイベントを event_id で、拡張対象のコンテンツブロックを delta.index で指定します。
{
"type": "event_delta",
"event_id": "sevt_01abc...",
"delta": {
"type": "content_delta",
"index": 0,
"content": {
"type": "text",
"text": "Here is the summary"
}
}
}agent.thinking イベントがプレビューされる場合、event_start のみが発行されます。event_delta イベントは続かず、プレビューを締めくくるバッファリングされた agent.thinking イベントには思考コンテンツが含まれません。これは進捗シグナルであり、コンテンツの運び手ではありません。
永続化されるイベントとは異なり、event_start と event_delta は独自の id や processed_at を持ちません。これらが持つ唯一の識別子は、プレビュー対象のイベントの id です。
蓄積と照合
イベントデルタをサポートするすべての SDK には、index の管理を代行するアキュムレータヘルパーが含まれています。Go、Java、Ruby、C# のヘルパーは、蓄積中のプレビューをイベントの id でもキー付けします。Python、TypeScript、PHP のヘルパーでは、そのマップを自分で保持し、各デルタをその id のエントリに畳み込みます。カスタムの管理が必要な場合は、手動パターンもすべての言語で機能します。生成されたイベントタイプに適用してください。
手動パターンでは、プレビューをスクラッチバッファとして、バッファリングされたイベントを記録として扱います。バッファを (event_id, index) でキー付けします。モデルリクエストごとに照合します。ターンは単一の session.status_running イベントで始まり、正常に完了するターンでは各モデルリクエストが順に span.model_request_start、event_start、event_delta イベント群、バッファリングされた agent.message、そして最後に span.model_request_end(スパンイベントタブ内)を生成します。ワイヤー上では、これはそのシーケンスのプレビュー部分であり、接続の他のバッファリングされたイベントと交互に現れます。
event_start {"event": {"type": "agent.message", "id": "sevt_01abc..."}}
event_delta {"event_id": "sevt_01abc...", "delta": {"type": "content_delta", "index": 0, "content": {"type": "text", "text": "..."}}}
...
agent.message {"id": "sevt_01abc...", "content": [...]}event_delta 行はテキストフラグメントごとに1回繰り返されます。各イベントを到着順に処理します。
event_startで、通知されたidを記録します。識別子は常に一致します。event_start.event.id、すべてのevent_delta.event_id、バッファリングされたagent.messageのidは同じ値です。- 各
event_deltaで、delta.content.textを(event_id, delta.index)のエントリに追加し、累積テキストをレンダリングします。あるindexの最初のデルタがそのエントリを作成します。 - バッファリングされた
agent.messageが到着したら、idで照合し、蓄積したプレビューを破棄して、代わりにメッセージのコンテンツをレンダリングします。 span.model_request_endで、バッファリングされたイベントによって照合されていないプレビューをすべて閉じます。それに対するデルタはもう来ません。ターンがエラーになったり中断されたりした場合、バッファリングされたイベントは到着しない可能性がありますが、span.model_request_endは到着します。
このパターンが依拠する保証は次のとおりです。
- プレビューのデルタを
(event_id, index)でキー付けして到着順に連結すると、バッファリングされたイベントのcontent[index].textのプレフィックスが得られます(負荷時にデルタが破棄される可能性があるため、必ずしもテキスト全体ではなくプレフィックスです)。 - 1つの接続は
event_idごとに最大1つのevent_startを発行し、バッファリングされたイベントはその接続がそのidに対して配信する最後のものです。
# Preview snapshots, keyed by event id. accumulate_managed_agents_event folds each
# event_start / event_delta into an agent.message snapshot; the buffered
# agent.message replaces it.
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}
# Opt in to agent.message previews on this connection
with client.beta.sessions.events.stream(
session.id, event_deltas=["agent.message"]
) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Describe the repo in one sentence."}],
},
],
)
for event in stream:
match event.type:
case "event_start":
snapshot = accumulate_managed_agents_event(None, event)
if snapshot is not None:
previews[event.event.id] = snapshot
print(f"event_start {event.event.type} {event.event.id}")
case "event_delta":
preview = accumulate_managed_agents_event(previews.get(event.event_id), event)
if preview is not None:
previews[event.event_id] = preview
text = "".join(block.text for block in preview.content)
print(f"event_delta preview: {text!r}")
case "agent.message":
# The buffered event is the record: it replaces and closes the preview
preview = accumulate_managed_agents_event(previews.pop(event.id, None), event)
text = "".join(block.text for block in preview.content)
print(f"agent.message {event.id} {text!r}")
case "span.model_request_end":
# No more deltas are coming. Close any preview whose
# buffered event never arrived.
for event_id in previews:
print(f"span.model_request_end closing preview for {event_id}")
previews.clear()
case "session.status_idle":
breakセッションスレッドイベントのプレビュー
マルチエージェントセッションでは、すべてのセッションスレッドが GET /v1/sessions/{session_id}/threads/{thread_id}/stream に独自のイベントストリームを持ち、同じ値を持つ同じ event_deltas[] パラメータを受け付けます。プレビューは設計上スレッドスコープです。接続は読み取っているスレッドのみをプレビューします。子スレッドのプレビューはその子自身のストリームで配信され、セッションレベルのストリームにクロスポストされることはありません。セッションレベルのストリームのプレビューはプライマリスレッドにスコープされたままです。モデルが生成するサブエージェントのテキストを見るには、そのサブエージェントのスレッドストリームを開いてください。
スレッドストリームのパスは間違えやすいものです。/events/stream(これはセッションレベルにのみ存在します)ではなく /threads/{thread_id}/stream であり、/threads/{thread_id}/events/stream エンドポイントは存在しません。
プレビューイベント自体は変わりません。event_start と event_delta は、スレッドストリーム上でもセッションレベルのストリーム上と同じ形状を持ち、蓄積と照合のパターンがそのまま適用されます。唯一の調整は管理面です。ストリーム接続ごとに1つのアキュムレータインスタンスを実行してください。
# List the session's threads and pick a child: child threads carry a non-null
# parent_thread_id, and the primary thread's parent_thread_id is null.
child_thread = next(
thread
for thread in client.beta.sessions.threads.list(session.id)
if thread.parent_thread_id is not None
)
# The child thread's stream takes the same event_deltas parameter as the
# session stream.
with client.beta.sessions.threads.events.stream(
child_thread.id,
session_id=session.id,
event_deltas=["agent.message"],
) as stream:
for event in stream:
match event.type:
case "event_delta":
print(event.delta.content.text, end="")
case "agent.message":
# The buffered event is the authoritative record; render its content
print()
for block in event.content:
if block.type == "text":
print(block.text, end="")
print()
case "session.thread_status_idle":
break読み取りループは session.thread_status_idle で終了します。これは、セッションスレッドのターンが終了してスレッドがアイドルになったときに発行されるイベントです。
制限事項
プレビューは応答性を重視して調整されています。次の制約を前提に構築してください。
- ベストエフォート: 負荷時には、サーバーがあるイベントのデルタを破棄することがあります。その場合、テキストの連続したプレフィックスを受け取り、その後そのイベントに対するデルタは届きません。バッファリングされた
agent.messageは完全な形で到着します。蓄積したプレビューを最終的なものとして扱わないでください。 - 再接続時のリプレイなし: デルタは、オプトインした接続が開いている間、その接続にのみ配信されます。これはセッションレベルのストリームにも各セッションスレッドストリームにも同様に当てはまり、モデルリクエストの開始後に開かれた接続は、その進行中のイベントに対するデルタを受け取りません。ストリームが切断された場合は、イベントのストリーミングタブの再接続手順に従ってください。ストリームを再度開き、イベント履歴をリストします。履歴には、切断中に発行されたバッファリングされたイベント(プレビューが待っていた
agent.messageを含む)がすべて含まれます。取りこぼしたデルタを再リクエストする方法はありません。 - 1スレッド、テキストのみ: プレビューは、接続が読み取っているスレッド上のアシスタントテキストを対象とします。ツール使用、ツール結果、MCP 結果、および他のセッションスレッド上のアクティビティは、その接続でプレビューされることはありません。
- start のみの
agent.thinking:agent.thinkingのプレビューは、思考ブロックが開始したことのシグナルとしてevent_startのみを発行します。その後にevent_deltaイベントは続きません。 - 永続化されない:
event_startとevent_deltaはライブストリーム上にのみ存在します。セッションのイベント履歴(GET /v1/sessions/{session_id}/events)にも、どのセッションスレッドのイベント履歴にも現れません。
プレビューのトラブルシューティング
ストリームが期待どおりに動作しない場合は、次を確認してください。
| 見られる現象 | 意味 |
|---|---|
バッファリングされたイベントはあるが event_start や event_delta がないストリーム | 読み取っている接続がオプトインしていない(event_deltas[] はセッションごとではなく接続ごとに適用されます)か、ターンがストリーミングしているスレッドに一度も触れていません。プレビューはスレッドスコープなので、セッションのスレッドをリスト(GET /v1/sessions/{session_id}/threads)して、どれが実行されたかを確認してください。 |
| ストリーム URL での 404 | パスまたは ID が間違っているか、リクエストに managed-agents ベータヘッダーがまったく含まれていません。スレッドエンドポイントはベータゲートされているため、ヘッダーがなければ存在しません。 |
event_deltas を指摘する 400 | agent.message と agent.thinking のみが受け付けられます。 |
その他のシナリオ
カスタムツール呼び出しの処理
エージェントがカスタムツールを呼び出すと、次のようになります。
- セッションは、ツール名と入力を含む
agent.custom_tool_useイベントを発行します。 - セッションは、
stop_reason: requires_actionを含むsession.status_idleイベントで一時停止します。ブロックしているイベント ID はstop_reason.event_ids配列にあります。 - あなたのシステムでツールを実行し、それぞれに対して
user.custom_tool_resultイベントを送信します。custom_tool_use_idパラメータにイベント ID を、結果コンテンツとともに渡します。 - ブロックしているすべてのイベントが解決されると、セッションは
runningに戻ります。
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# Look up the custom tool use event and execute it
tool_event = events_by_id[event_id]
result = call_tool(tool_event.name, tool_event.input)
# Send the result back
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.custom_tool_result",
"custom_tool_use_id": event_id,
"content": [{"type": "text", "text": result}],
},
],
)
case "end_turn":
breakツールの確認
ツール呼び出しは、always_askのパーミッションポリシーの下、またはサーバーが判定に至らなかった場合のautoの下で、確認を待ちます。その場合、次のようになります。
- セッションは
agent.tool_useまたはagent.mcp_tool_useイベントを発行します。 - セッションは、
stop_reason.typeがrequires_actionであるsession.status_idleイベントで一時停止します。ブロックしているイベントIDはstop_reason.event_ids配列に含まれます。 - それぞれについて
user.tool_confirmationイベントを送信し、tool_use_idパラメータにイベントIDを渡します。resultを"allow"または"deny"に設定します。拒否の理由を説明するにはdeny_messageを使用します。 - ブロックしているすべてのイベントが解決されると、セッションは
runningに戻ります。
各agent.tool_useおよびagent.mcp_tool_useイベントにはevaluated_permission(allow、ask、またはdeny)が含まれ、evaluated_permissionが"ask"であるイベントのみが確認を待ちます。ほとんどのイベントには、どのポリシーがその結果を生んだかを記録するevaluationオブジェクトも含まれます。これについては各呼び出しがどのように評価されたかを確認するで説明しています。たとえば、always_askポリシーの下で一時停止したbash呼び出しは、ストリーム上で次のように表示されます。
{
"type": "agent.tool_use",
"id": "sevt_01def...",
"name": "bash",
"input": {
"command": "pip install -r requirements.txt"
},
"evaluated_permission": "ask",
"evaluation": {
"type": "always_ask"
},
"processed_at": "2026-03-25T14:01:45Z"
}with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# Approve the pending tool call
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
},
],
)
case "end_turn":
breakアイドルセッションの再開
セッションはインタラクション間で永続化されます。会話履歴は、セッションが明示的に削除されない限り保持されます。セッションがアイドルになると、そのサンドボックスはチェックポイント化され、ファイルシステム、インストール済みパッケージ、エージェントが作成したファイルを含むサンドボックスの完全な状態が保持されます。これにより、非アクティブ状態からクリーンに再開できます。
セッションを再開するには、通常どおり user.message イベントを送信します。
# Resume a previously created session by sending it a new user.message event.
# In production, pass the stored ID of the session you want to resume.
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Now run the tests against the changes you made earlier.",
},
],
},
],
)セッション予算への到達
予算付きで作成されたセッションは、超過支出する代わりに一時停止します。セッションの追跡対象リストコストが上限に達すると、プラットフォームは各スレッドを次のモデルリクエストの前に一時停止し、セッションは終了するのではなく stop_reason が budget_reached のアイドル状態になります。合計を上限を超えて押し上げたリクエストは完了まで実行されるため、session.usage スナップショットが報告する list_cost は上限ちょうど、または上限をわずかに超えた値になることがあります。ストリーム上では、一時停止は次の3つのイベントとして順に到着します。
- 各スレッドが一時停止するたびに、
stop_reason: budget_reachedを持つsession.thread_status_idle。 - セッションの累積使用量と追跡対象リストコストのスナップショットである
session.usage。 stop_reason: budget_reachedを持つsession.status_idle。session.usageイベントは常にこのアイドルの直前に来ます。
最後のリクエストが上限を超えると同時にターンを完了したスレッドは、自身の session.thread_status_idle イベントで end_turn を報告しますが、セッションは依然として budget_reached を報告します。一時停止を検出するには、セッションレベルの stop_reason をキーにしてください。
セッションが上限に達している間は、すでに進行中の作業を決着させるイベントのみを受け付けます。user.tool_confirmation、user.tool_result、user.custom_tool_result、user.interrupt です。user.message を含め、新しい作業を開始するイベントはすべて、そのリストを示す 400 エラーで拒否されます。セッションにツールの問い合わせを待っているスレッドと上限で一時停止しているスレッドの両方がある場合、セッションレベルの stop_reason は budget_reached ではなく requires_action です。問い合わせを決着させてもモデルリクエストはトリガーされないため、通常どおり応答してください。
上限で一時停止したセッションを再開するイベントはありません。代わりに、セッションの予算を更新してください。上限を消費済みリストコストより大きい任意の値に変更するか、"budget": null でセッションを更新して予算を削除すると、一時停止した作業が自動的に再開されます。リストコストの追跡方法と予算更新の完全なセマンティクスについては、セッション予算を参照してください。
システムメッセージの送信
付随するターンとそれ以降のすべてのターンに適用される特権的なシステムレベルのコンテキストをエージェントに与えるには、system.message イベントを送信します。エージェント定義の system フィールド(トップレベルのシステムプロンプトを設定するもの)とは異なり、system.message のコンテンツはそのプロンプトを置き換えるのではなく、role: "system" のターンとしてセッションのシステムコンテキストに追加されます。セッションの途中でエージェントに更新されたシステムレベルのガイダンスが必要な場合に使用してください。異なるペルソナ、改訂された制約、または今後のモデルの動作を形作るべき実行時に取得したコンテキストなどです。
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "system.message",
"content": [
{
"type": "text",
"text": "The user's current timezone is America/New_York.",
},
],
},
],
)セッションが stop_reason: requires_action でアイドル状態の間、system.message は同じリクエスト内でツール結果イベントの後に続く場合にのみ受け付けられます。単独で、または user.message とともに送信された場合は、保留中のツールイベントが解決されるまで拒否されます。content は 1~1000 個のテキスト項目を受け付けます。
使用量の追跡
セッションオブジェクトには、セッションの累積使用量を示す usage フィールドが含まれています。トークン数、サーバーツール使用、アクティブ時間、および追跡された定価コストです。最新の合計値を読み取るには、セッションがアイドル状態になった後にセッションを取得してください。
{
"id": "sesn_01...",
"status": "idle",
"usage": {
"input_tokens": 5000,
"output_tokens": 3200,
"cache_read_input_tokens": 20000,
"cache_creation": {
"ephemeral_5m_input_tokens": 2000,
"ephemeral_1h_input_tokens": 0
},
"list_cost": {
"amount": "187",
"currency": "USD"
},
"active_seconds": 342.5,
"server_tool_use": {
"web_search_requests": 3,
"web_fetch_requests": 0
}
}
}input_tokens はキャッシュされていない入力トークンを報告し、output_tokens はセッション内のすべてのモデル呼び出しにわたる出力トークンの合計を報告します。cache_read_input_tokens フィールドはプロンプトキャッシュから読み取られたトークンを報告し、cache_creation オブジェクトはキャッシュ作成トークンをキャッシュの有効期間別(ephemeral_5m_input_tokens と ephemeral_1h_input_tokens)に分類します。キャッシュエントリはデフォルトで5分間のTTLを使用するため、その時間枠内で連続して行われるターンはキャッシュ読み取りの恩恵を受け、トークンあたりのコストが削減されます。
list_cost は、公開されている定価レートで価格設定されたセッションの累積消費量であり、文字列形式のセント単位の整数と通貨コードで表されます。active_seconds は、セッションで少なくとも1つのスレッドが実行されていた累積時間です。並行スレッドによる重複するアクティビティは1回だけカウントされます。これは、各スレッド自身のアクティブ時間を合計するセッションの stats オブジェクト内の active_seconds とは異なります。この重複排除された数値が、セッションのランタイムコストの価格設定の基準となる期間です。server_tool_use は、価格設定のためにサーバーで実行されたツールリクエストをカウントします。Web検索リクエストはリクエストごとに定価コストに計上され、Webフェッチリクエストにはリクエストごとの料金がなく計測もされないため、web_fetch_requests は 0 と表示されます。各セッションスレッド自身の usage にも list_cost と active_seconds が含まれます。スレッドごとの数値は個別に丸められ、セッションの実行時間コストを含まないため、合計してもセッションの list_cost と正確には一致しません。セッションの数値が正式な値です。
これらの合計値を確認するためにセッションをポーリングする必要はありません。session.usage イベントは、同じ累積スナップショット(usage オブジェクトに加えて、セッションの budget。セッションに予算がない場合は null)をセッションストリームおよびイベント履歴で伝達します。このイベントはタイマーではなくアイドル状態への遷移時に発行されます。セッションは、停止理由にかかわらずアイドル状態になる直前に1回、そしてスレッドがセッション予算で一時停止したときに1回発行します。したがって、ストリームの読み取り側は、追加の取得を行うことなく、ターンの最終コスト、または予算に達した作業の最終コストを確認できます。
支出上限を適用するには、使用量をポーリングして自分でセッションを停止するのではなく、セッション予算を設定してください。プラットフォームはセッションの消費量を継続的に価格計算し、セッションの定価コストが上限に達すると、各スレッドを次のモデルリクエストの前に一時停止します。ストリーム上でどのように見えるかについては、セッション予算への到達を参照してください。
Consoleでのオブザーバビリティ
Claude Consoleには、コードを書かずにエージェントが何を行ったかを調査するためのセッションビューアーが含まれています。Consoleのサイドバーで、Managed Agents の下にある Sessions を選択すると、ワークスペース内のすべてのセッションがステータス、エージェント、トークン使用量、コスト、作成時刻とともに表示されます。セッションを選択して開きます。セッションビューアーは開発者と管理者のみがアクセスできます。以下の内容が表示されます。
- タイムラインミニマップ: セッションのアクティビティを時系列で表示するズーム可能な概要で、マルチエージェントセッションではスレッドごとに1つのレーンが表示されます。レーンを選択するとそのスレッドが表示され、マークを選択するとそのイベントにジャンプします。
- トランスクリプト: モデルリクエストごとにグループ化された会話で、思考、入力と結果を含むツール呼び出し、ストリーミング中のメッセージテキストが含まれます。イベントをフィルタリングしたり、JSONとしてコピーまたはダウンロードしたりできます。
- インスペクター: セッションに関する詳細を5つのタブで表示する、サイズ変更可能なサイドパネルです。
- Session には、セッションの詳細とメタデータ、時間経過に伴う累積コスト、および予算が設定されている場合はセッションの予算に対する支出が表示されます。
- Events には、現在のスレッド上のすべての生イベントがサーバーから送信された順に一覧表示されます。イベントを選択するとそのJSONが表示されます。ページを開いている間にストリーミングされたメッセージには、そのイベントデルタの Deltas ビューもあります。
- Tools には、セッションのエージェントに設定されているツールが、呼び出し回数、失敗数、所要時間の中央値とともに一覧表示されます。ツールを選択するとその呼び出しが表示され、トランスクリプト内の該当箇所にジャンプできます。
- Resources には、マウントされたファイル、リポジトリ、メモリストアがコンテナパスとともに一覧表示されます。各ストア内のメモリとこのセッションがそれらに加えた変更、さらにエージェントが
/mnt/session/outputsに書き込んだファイル、およびセッションのエージェントにアタッチされたスキルも含まれます。 - Threads には、すべてのスレッドがステータス、コンテキストサイズ、コストとともに一覧表示されます。スレッドを選択すると、エージェント、モデル、コンテキスト使用量、コストなどの詳細が表示されます。
セッションURLに ?event={event_id} を追加すると、特定のイベントの位置でセッションを開くことができます。
ant beta:sessions connect を使用すると、ant CLI から同じビューアを開いたり、ターミナルでセッションを追跡したりできます。詳しくは、ターミナルから Managed Agents セッションに接続するを参照してください。
デバッグのヒント
- セッションイベントを確認する: セッションエラーは
session.errorイベントを通じて伝達されます - ツール結果を確認する: ツール実行の失敗は、エージェントの予期しない動作の原因を説明することがよくあります
- トークン使用量を追跡する: トークン消費量を監視して、プロンプトを最適化しコストを削減します
- システムプロンプトを使用する: システムプロンプトにログ記録の指示を追加して、エージェントに推論を説明させます
- プレビューのトラブルシューティング: イベントデルタをオプトインしたストリームが期待どおりに動作しない場合は、プレビューのトラブルシューティングを参照してください
Was this page helpful?