--- title: "Streaming vs Single Message Input" aliases: [streaming-input, input-modes, single-message-input] tags: [agent-sdk, streaming, input, typescript, session-management] sources: [raw/Streaming Input.md] created: 2026-04-17 updated: 2026-04-17 --- ## Overview The Claude Agent SDK supports two distinct input modes for `query()`: | Mode | Type | Use case | |------|------|----------| | **Streaming Input** | `AsyncGenerator` of messages | Long-lived sessions, multi-turn, images, hooks | | **Single Message** | `string` | One-shot queries, stateless environments | Streaming input is the **default and recommended** approach. ## Streaming Input Mode Pass an `AsyncGenerator` as the `prompt`. The agent runs as a long-lived process that consumes messages as they are yielded, handling tool execution and session state between turns. ### Capabilities (streaming only) - **Image uploads** — attach `base64` images directly in message content - **Queued messages** — yield multiple messages; they process sequentially - **Interruption** — send an interrupt/cancel mid-session - **Hook integration** — lifecycle hooks fire normally - **Real-time feedback** — responses stream back as tokens are generated - **Context persistence** — conversation context maintained across all turns automatically ### How it works ``` App yields Message 1 → Agent executes tools → Streams partial response back App yields Message 2 + Image → Agent processes → Streams response 2 App queues Message 3 → App sends Interrupt → Agent handles interruption ↕ Session stays alive; file system state persists ``` ### TypeScript example ```typescript import { query } from "@anthropic-ai/claude-agent-sdk"; import { readFile } from "fs/promises"; async function* generateMessages() { yield { type: "user" as const, message: { role: "user" as const, content: "Analyze this codebase for security issues" } }; await new Promise((resolve) => setTimeout(resolve, 2000)); // Follow-up with image attachment yield { type: "user" as const, message: { role: "user" as const, content: [ { type: "text", text: "Review this architecture diagram" }, { type: "image", source: { type: "base64", media_type: "image/png", data: await readFile("diagram.png", "base64") } } ] } }; } for await (const message of query({ prompt: generateMessages(), options: { maxTurns: 10, allowedTools: ["Read", "Grep"] } })) { if (message.type === "result") console.log(message.result); } ``` ## Single Message Input Pass a plain `string` as `prompt`. Best for simple one-shot tasks or stateless environments (e.g. Lambda functions). ### Limitations (single message) - No direct image attachments - No dynamic message queueing - No real-time interruption - No hook integration - No natural multi-turn conversations ### Session resuming with single message Use `continue: true` to resume a previous session: ```typescript import { query } from "@anthropic-ai/claude-agent-sdk"; // First query for await (const message of query({ prompt: "Explain the authentication flow", options: { maxTurns: 1, allowedTools: ["Read", "Grep"] } })) { if (message.type === "result") console.log(message.result); } // Resume same session for await (const message of query({ prompt: "Now explain the authorization process", options: { continue: true, maxTurns: 1 } })) { if (message.type === "result") console.log(message.result); } ``` ## Choosing the Right Mode | Requirement | Use | |-------------|-----| | Multi-turn conversation | Streaming | | Image attachments | Streaming | | Hooks / lifecycle events | Streaming | | Real-time token streaming | Streaming | | Lambda / stateless function | Single message | | Simple one-shot query | Single message | | Session resume across calls | Single message + `continue: true` | ## Key Takeaways - **Streaming input = `AsyncGenerator` prompt** — yield messages as needed; the session stays alive between them - **Single message = `string` prompt** — simpler API but loses images, hooks, interrupts, and natural multi-turn - Streaming is the default; single message is the escape hatch for stateless environments - `continue: true` lets single-message mode resume a prior session without rebuilding the generator - Real-time token streaming (output side) works independently of which input mode you choose — see [[wiki/agent-sdk/streaming-output|streaming-output]] - Hooks only fire in streaming input mode; see [[wiki/agent-sdk/sdk-hooks|sdk-hooks]] for hook setup - For approval/interruption patterns see [[wiki/agent-sdk/user-input-approvals|user-input-approvals]] ## Sources - `raw/Streaming Input.md` — source: https://code.claude.com/docs/en/agent-sdk/streaming-vs-single-mode