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