# Useful but Little-Known Features of Claude Agent SDK
🌍 Want to send messages while the agent is working? Streaming input mode enables interactive sessions!
With streaming input mode, you can add messages, interrupt execution, and send images during an active session.
📌 Title: Streaming Input Mode
🔗 URL:
🧩 Overview
Streaming input mode (the recommended, preferred mode) provides a persistent, interactive session using `AsyncGenerator`. Unlike single message input (one-shot), it supports message queueing, image attachments, and mid-execution interruption during a session. Messages are sent sequentially via `yield`, and follow-up messages can be dynamically generated based on conditions — ideal for chat interfaces and complex workflows.
🛠 How to Use
```python
# Python - Interactive session with streaming input
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, TextBlock
import base64
async def message_generator():
yield {
"type": "user",
"message": {"role": "user", "content": "Analyze for security issues"},
}
# Follow-up with image
with open("diagram.png", "rb") as f:
image_data = base64.b64encode(
yield {
"type": "user",
"message": {
"role": "user",
"content": [
{"type": "text", "text": "Also review this architecture diagram"},
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": image_data}},
],
},
}
options = ClaudeAgentOptions(max_turns=10, allowed_tools=["Read", "Grep"])
async with ClaudeSDKClient(options) as client:
await client.query(message_generator())
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
```
```typescript
// TypeScript - Send messages sequentially via AsyncGenerator
import { query, type SDKUserMessage } from "
@anthropic-ai/claude-agent-sdk";
async function* generateMessages(): AsyncGenerator
{
yield {
type: "user",
message: { role: "user", content: "Analyze this codebase for security issues" },
parent_tool_use_id: null,
};
// Dynamic follow-up based on conditions
await new Promise((resolve) => setTimeout(resolve, 2000));
yield {
type: "user",
message: { role: "user", content: "Now focus on authentication" },
parent_tool_use_id: null,
};
}
for await (const message of query({
prompt: generateMessages(),
options: { maxTurns: 10, allowedTools: ["Read", "Grep"] }
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
```
🏗 Integration into Production Systems
- Wire chat UI message sends to the generator's `yield` to pass user input to the agent in real time
- Include `base64`-encoded image uploads in messages for visual analysis capabilities
- Send interrupt signals to redirect the agent, enabling control over long-running tasks
- Context is naturally maintained within the session, eliminating multi-turn conversation management overhead
💡 Use Cases
💬 Build interactive sessions between users and agents in custom chatbots
🖼 Dynamically send screenshots or diagrams during code review for analysis
🔄 Send additional instructions or shift focus areas during long-running code analysis
⚠️ Caveats
- Single message input does not support image attachments, dynamic message queueing, or real-time interruption
- For stateless environments (Lambda functions, etc.), use single message input instead
- In Python, streaming input requires the `ClaudeSDKClient` context manager
✨ The real power of AI agents goes beyond one-shot queries. Build rich interactive experiences with streaming input!
#ClaudeAgentSDK# #AIAgent#