תיעוד 135
הזרמת תגובות בזמן אמת
קבל תגובות בזמן אמת מ-Agent SDK כאשר טקסט וקריאות לכלים מוזרמים פנימה
כברירת מחדל, ה-Agent SDK מניב אובייקטי AssistantMessage מלאים לאחר ש-Claude מסיים ליצור כל תגובה. כדי לקבל עדכונים הדרגתיים כשטקסט וקריאות לכלים נוצרים, הפעל הזרמת הודעות חלקיות.
טיפ: דף זה מכסה הזרמת פלט (קבלת טוקנים בזמן אמת). לגבי מצבי קלט (כיצד אתה שולח הודעות), ראה שליחת הודעות לסוכנים. באפשרותך גם להזרים תגובות באמצעות ה-Agent SDK דרך ה-CLI.
#הפעלת הזרמת פלט
כדי להפעיל הזרמה, הגדר את include_partial_messages (ב-Python) או includePartialMessages (ב-TypeScript) ל-true באפשרויות שלך. הדבר גורם ל-SDK להניב הודעות StreamEvent המכילות אירועי API גולמיים כשהם מגיעים, בנוסף ל-AssistantMessage ול-ResultMessage הרגילים.
לאחר מכן הקוד שלך צריך:
- לבדוק את הסוג של כל הודעה כדי להבדיל בין
StreamEventלסוגי הודעות אחרים - עבור
StreamEvent, לחלץ את השדהeventולבדוק את ה-typeשלו - לחפש אירועי
content_block_deltaשבהםdelta.typeהואtext_delta, המכילים את מקטעי הטקסט בפועל
הדוגמה להלן מפעילה הזרמה ומדפיסה מקטעי טקסט כשהם מגיעים. שים לב לבדיקות הסוג המקוננות: תחילה עבור StreamEvent, לאחר מכן עבור content_block_delta, ולאחר מכן עבור text_delta:
Python:
from claude_agent_sdk import query, ClaudeAgentOptions
from claude_agent_sdk.types import StreamEvent
import asyncio
async def stream_response():
options = ClaudeAgentOptions(
include_partial_messages=True,
allowed_tools=["Bash", "Read"],
)
async for message in query(prompt="List the files in my project", options=options):
if isinstance(message, StreamEvent):
event = message.event
if event.get("type") == "content_block_delta":
delta = event.get("delta", {})
if delta.get("type") == "text_delta":
print(delta.get("text", ""), end="", flush=True)
asyncio.run(stream_response())TypeScript:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "List the files in my project",
options: {
includePartialMessages: true,
allowedTools: ["Bash", "Read"]
}
})) {
if (message.type === "stream_event") {
const event = message.event;
if (event.type === "content_block_delta") {
if (event.delta.type === "text_delta") {
process.stdout.write(event.delta.text);
}
}
}
}#תיעוד StreamEvent
כאשר הודעות חלקיות מופעלות, אתה מקבל אירועי הזרמה גולמיים של Claude API עטופים באובייקט. לסוג זה יש שמות שונים בכל SDK:
- Python:
StreamEvent(ייבוא מתוךclaude_agent_sdk.types) - TypeScript:
SDKPartialAssistantMessageעםtype: 'stream_event'
שניהם מכילים אירועי Claude API גולמיים, ולא טקסט מצטבר. עליך לחלץ ולצבור מקטעי טקסט (deltas) בעצמך. הנה המבנה של כל סוג:
Python:
@dataclass
class StreamEvent:
uuid: str
# Unique identifier for this event
session_id: str
# Session identifier
event: dict[str, Any]
# The raw Claude API stream event
parent_tool_use_id: str | None
# Always NoneTypeScript:
type SDKPartialAssistantMessage = {
type: "stream_event";
event: BetaRawMessageStreamEvent; // From Anthropic SDK
parent_tool_use_id: string | null;
uuid: UUID;
session_id: string;
ttft_ms?: number; // Time to first token in ms, present only on message_start events
};השדה parent_tool_use_id הוא תמיד None ב-Python ו-null ב-TypeScript. אירועי הזרמה נשלחים עבור הפעלת השיחה הראשית בלבד, ושינויים ברמת הטוקן מסוכני משנה אינם מועברים הלאה. כדי לייחס פלט לסוכן משנה, השתמש בהודעות מלאות, אשר נושאות את parent_tool_use_id. ראה זיהוי הפעלת סוכני משנה.
השדה event מכיל את אירוע ההזרמה הגולמי מתוך Claude API. סוגי אירועים נפוצים כוללים:
| סוג אירוע | תיאור |
|---|---|
message_start | תחילתה של הודעה חדשה |
content_block_start | תחילתו של בלוק תוכן חדש (טקסט או שימוש בכלי) |
content_block_delta | עדכון הדרגתי לתוכן |
content_block_stop | סיומו של בלוק תוכן |
message_delta | עדכונים ברמת ההודעה (סיבת עצירה, שימוש) |
message_stop | סיום ההודעה |
#זרימת הודעות
כאשר הודעות חלקיות מופעלות, אתה מקבל הודעות בסדר הבא:
StreamEvent (message_start)
StreamEvent (content_block_start) - text block
StreamEvent (content_block_delta) - text chunks...
StreamEvent (content_block_stop)
StreamEvent (content_block_start) - tool_use block
StreamEvent (content_block_delta) - tool input chunks...
StreamEvent (content_block_stop)
StreamEvent (message_delta)
StreamEvent (message_stop)
AssistantMessage - complete message with all content
... tool executes ...
... more streaming events for next turn ...
ResultMessage - final resultללא הפעלת הודעות חלקיות, אתה מקבל את כל סוגי ההודעות למעט StreamEvent. סוגים נפוצים כוללים את SystemMessage (אתחול הפעלה), AssistantMessage (תגובות מלאות), ResultMessage (תוצאה סופית), והודעת גבול דחיסה המציינת מתי היסטוריית השיחה נדחסה (SDKCompactBoundaryMessage ב-TypeScript, או SystemMessage עם תת-סוג "compact_boundary" ב-Python).
#הזרמת קריאות לכלים
קריאות לכלים מוזרמות גם הן באופן הדרגתי. באפשרותך לעקוב מתי כלים מתחילים לפעול, לקבל את הקלט שלהם בזמן שהוא נוצר, ולראות מתי הם מסתיימים. הדוגמה להלן עוקבת אחר הכלי הנוכחי שמופעל וצוברת את קלט ה-JSON כשהוא מוזרם פנימה. היא משתמשת בשלושה סוגי אירועים:
content_block_start: הכלי מתחילcontent_block_deltaעםinput_json_delta: מקטעי קלט מגיעיםcontent_block_stop: קריאת הכלי הושלמה
Python:
from claude_agent_sdk import query, ClaudeAgentOptions
from claude_agent_sdk.types import StreamEvent
import asyncio
async def stream_tool_calls():
options = ClaudeAgentOptions(
include_partial_messages=True,
allowed_tools=["Read", "Bash"],
)
# Track the current tool and accumulate its input JSON
current_tool = None
tool_input = ""
async for message in query(prompt="Read the README.md file", options=options):
if isinstance(message, StreamEvent):
event = message.event
event_type = event.get("type")
if event_type == "content_block_start":
# New tool call is starting
content_block = event.get("content_block", {})
if content_block.get("type") == "tool_use":
current_tool = content_block.get("name")
tool_input = ""
print(f"Starting tool: {current_tool}")
elif event_type == "content_block_delta":
delta = event.get("delta", {})
if delta.get("type") == "input_json_delta":
# Accumulate JSON input as it streams in
chunk = delta.get("partial_json", "")
tool_input += chunk
print(f" Input chunk: {chunk}")
elif event_type == "content_block_stop":
# Tool call complete - show final input
if current_tool:
print(f"Tool {current_tool} called with: {tool_input}")
current_tool = None
asyncio.run(stream_tool_calls())TypeScript:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Track the current tool and accumulate its input JSON
let currentTool: string | null = null;
let toolInput = "";
for await (const message of query({
prompt: "Read the README.md file",
options: {
includePartialMessages: true,
allowedTools: ["Read", "Bash"]
}
})) {
if (message.type === "stream_event") {
const event = message.event;
if (event.type === "content_block_start") {
// New tool call is starting
if (event.content_block.type === "tool_use") {
currentTool = event.content_block.name;
toolInput = "";
console.log(`Starting tool: ${currentTool}`);
}
} else if (event.type === "content_block_delta") {
if (event.delta.type === "input_json_delta") {
// Accumulate JSON input as it streams in
const chunk = event.delta.partial_json;
toolInput += chunk;
console.log(` Input chunk: ${chunk}`);
}
} else if (event.type === "content_block_stop") {
// Tool call complete - show final input
if (currentTool) {
console.log(`Tool ${currentTool} called with: ${toolInput}`);
currentTool = null;
}
}
}
}#בניית ממשק משתמש להזרמה
דוגמה זו משלבת הזרמת טקסט והזרמת כלים לממשק משתמש מגובש. היא עוקבת אם הסוכן מבצע כלי ברגע נתון (באמצעות דגל in_tool), כדי להציג מחווני סטטוס כגון [Using Read...] בזמן שהכלים פועלים. טקסט מוזרם כרגיל כאשר לא נמצאים בתוך כלי, וסיום הכלי מפעיל הודעת "done". דפוס זה שימושי לממשקי שיחה שצריכים להציג התקדמות במהלך משימות סוכן מרובות שלבים.
Python:
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
from claude_agent_sdk.types import StreamEvent
import asyncio
import sys
async def streaming_ui():
options = ClaudeAgentOptions(
include_partial_messages=True,
allowed_tools=["Read", "Bash", "Grep"],
)
# Track whether we're currently in a tool call
in_tool = False
async for message in query(
prompt="Find all TODO comments in the codebase", options=options
):
if isinstance(message, StreamEvent):
event = message.event
event_type = event.get("type")
if event_type == "content_block_start":
content_block = event.get("content_block", {})
if content_block.get("type") == "tool_use":
# Tool call is starting - show status indicator
tool_name = content_block.get("name")
print(f"\n[Using {tool_name}...]", end="", flush=True)
in_tool = True
elif event_type == "content_block_delta":
delta = event.get("delta", {})
# Only stream text when not executing a tool
if delta.get("type") == "text_delta" and not in_tool:
sys.stdout.write(delta.get("text", ""))
sys.stdout.flush()
elif event_type == "content_block_stop":
if in_tool:
# Tool call finished
print(" done", flush=True)
in_tool = False
elif isinstance(message, ResultMessage):
# Agent finished all work
print(f"\n\n--- Complete ---")
asyncio.run(streaming_ui())TypeScript:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Track whether we're currently in a tool call
let inTool = false;
for await (const message of query({
prompt: "Find all TODO comments in the codebase",
options: {
includePartialMessages: true,
allowedTools: ["Read", "Bash", "Grep"]
}
})) {
if (message.type === "stream_event") {
const event = message.event;
if (event.type === "content_block_start") {
if (event.content_block.type === "tool_use") {
// Tool call is starting - show status indicator
process.stdout.write(`\n[Using ${event.content_block.name}...]`);
inTool = true;
}
} else if (event.type === "content_block_delta") {
// Only stream text when not executing a tool
if (event.delta.type === "text_delta" and !inTool) {
process.stdout.write(event.delta.text);
}
} else if (event.type === "content_block_stop") {
if (inTool) {
// Tool call finished
console.log(" done");
inTool = false;
}
}
} else if (message.type === "result") {
// Agent finished all work
console.log("\n\n--- Complete ---");
}
}#מגבלות ידועות
- פלט מובנה: תוצאת ה-JSON מופיעה רק ב-
ResultMessage.structured_outputהסופי, ולא כמקטעי שינוי מוזרמים. ראה פלטים מובנים לפרטים.
#השלבים הבאים
כעת, כשבאפשרותך להזרים טקסט וקריאות לכלים בזמן אמת, תוכל לבחון נושאים קשורים אלה:
- שאילתות אינטראקטיביות מול שאילתות חד פעמיות: בחר בין מצבי קלט עבור תרחיש השימוש שלך
- פלטים מובנים: קבל תגובות JSON מוגדרות טיפוסים מהסוכן
- הרשאות: שלוט באילו כלים הסוכן רשאי להשתמש