obsidian/wiki/agent-sdk/streaming-input.md
2026-04-17 13:15:24 +01:00

149 lines
4.8 KiB
Markdown

---
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