Core Messages and Streaming Cookbook
Purpose and Scope
This cookbook is for developers who already have an Anthropic client and want small, reusable patterns for core Claude message generation. The focus is the stable messages resource, the streaming helpers exposed through that resource, message batches for asynchronous work, and the streaming compatibility layer used by provider packages. The examples are intentionally compact: each one can be pasted into a TypeScript server project, then expanded with your application’s own logging, persistence, retry policy, or user-interface updates.
The repository source shows that core message functionality is exposed from src/resources/messages/index.ts through the generated Messages resource, Batches resource, and many public request, response, content, delta, and stop-reason types. The beta message surface in src/resources/beta/messages/index.ts mirrors this general shape while adding beta-only concepts such as fallback, context management, compaction, and expanded thinking-related types. For cookbook usage, treat the stable resource as the default entry point and reach for the beta namespace only when your selected API feature requires beta parameters or beta response types.
Sources: src/resources/messages/index.ts, src/resources/beta/messages/index.ts
Relevant Source Files
src/resources/messages/index.ts— generated export barrel for the stable Messages API, includingMessages,Batches,Message,MessageParam, stream event types, content block types, token counting types,StopReason, and refusal-related details.src/resources/beta/messages/index.ts— generated export barrel for beta Messages features, including beta batches plus beta fallback, compaction, context-management, thinking, tool, citation, and diagnostic types.packages/aws-sdk/src/core/streaming.ts— provider package streaming entry point that re-exports the shared core streaming implementation from the main SDK package.packages/bedrock-sdk/src/core/streaming.ts— Bedrock-specific streaming adapter that re-exports SDK streaming helpers and converts AWS binary event stream frames into Anthropic-style server-sent events.packages/foundry-sdk/src/core/streaming.ts— Foundry provider streaming entry point that re-exports the shared core streaming implementation.packages/vertex-sdk/src/core/streaming.ts— Vertex provider streaming entry point that re-exports the shared core streaming implementation.
Core Primitives
A message request is the basic Claude interaction: you send a model, a maximum output token budget, and an ordered list of user or assistant messages. The stable generated exports name the public vocabulary used throughout these examples: MessageParam represents an input turn, Message represents the final response, ContentBlock and TextBlock describe returned content, and StopReason tells you why generation ended. Because these names are exported from the resource index, application code can type helper functions without reaching into internal implementation files.
Streaming is the incremental version of the same workflow. Instead of waiting for a complete Message, the SDK exposes stream helpers that emit server-sent-event shaped updates such as raw message events, raw content block deltas, text deltas, input JSON deltas, and message delta usage. This matters for chat interfaces, command-line tools, and agent loops because each partial update can be rendered or accumulated immediately. The official Claude docs describe streaming as SSE-based and show the TypeScript SDK’s client.messages.stream() helper with a text event callback.
Sources: src/resources/messages/index.ts
Recipe: Create a Basic Message
Use client.messages.create() when you want the simplest request-response flow. This is the right default for backend endpoints, scripts, and jobs where latency is less important than a single complete response object. Keep the message list explicit, even for one-turn prompts, because the same shape naturally grows into a conversation history. When you pass the returned message.content to another layer, inspect the content block type instead of assuming every response is plain text; the exported type list includes many block kinds beyond text.
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const message = await client.messages.create({
model: 'claude-opus-4-6',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Write a two-sentence release note.' }],
});
for (const block of message.content) {
if (block.type === 'text') console.log(block.text);
}This pattern is also the baseline for fallback and cancellation wrappers. Put the request parameters in a plain object before calling the SDK, then reuse that object when you need to retry with a different model, attach request options, or log a sanitized copy for debugging. The stable resource exports include StopReason and RefusalStopDetails, so production code should branch on completion metadata rather than scraping generated text for policy or truncation signals.
Sources: src/resources/messages/index.ts
Recipe: Stream Text to a UI or CLI
Use client.messages.stream() when the caller benefits from partial output. The SDK helper shown in the official Claude docs emits text fragments through a text event, which keeps a terminal or web socket responsive while the model continues generating. A common pattern is to write each fragment to the user immediately and separately await the completed message if your application needs final usage, stop reason, or full content blocks for storage.
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
await client.messages
.stream({
model: 'claude-opus-4-8',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello' }],
})
.on('text', (text) => {
process.stdout.write(text);
});For richer interfaces, listen to lower-level raw stream events and accumulate them into your own state model. The stable export barrel includes RawMessageStreamEvent, RawContentBlockDeltaEvent, TextDelta, InputJSONDelta, MessageDeltaEvent, and related start and stop event types. Those names are a signal that stream handling should be written as an event reducer: message start initializes state, content block starts allocate block buffers, deltas append fragments, and stop events finalize the response.
Sources: src/resources/messages/index.ts
Recipe: Handle Streaming Refusals and Fallbacks
Streaming applications need an explicit ending policy because a stream can end successfully, stop at max_tokens, stop for a tool call, or stop with a refusal. Claude’s official guidance says Claude 4 streaming responses can return stop_reason: 'refusal' when streaming classifiers intervene, and that no additional refusal message is guaranteed. In that case, reset or rephrase the conversation context before continuing; do not blindly append the refused turn and continue the same transcript.
const primary = await client.messages.create({
model: 'claude-opus-4-6',
max_tokens: 512,
messages,
});
if (primary.stop_reason === 'refusal') {
const fallback = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 512,
messages: resetOrRephrasedMessages,
});
console.log(fallback.content);
}The beta message exports make fallback a first-class typed concept for users working on beta surfaces: the barrel includes beta fallback blocks, fallback info, fallback params, and fallback iteration usage types. Stable cookbook code can still implement manual fallback as shown above, but beta integrations should prefer the beta resource shapes when the API feature they are using returns structured fallback metadata. Either way, keep the refusal path separate from ordinary retries such as rate-limit or network retries, because refusal recovery changes conversation context rather than only transport behavior.
Sources: src/resources/messages/index.ts, src/resources/beta/messages/index.ts
Recipe: Run Message Batches
Use the Batches resource when you have many independent message requests and do not need each answer synchronously. The stable index exports Batches, MessageBatch, individual batch response result types, request count types, and batch parameter types. That public surface is designed for workflows such as offline evaluation, summarizing many records, or processing a queue where the application can create a batch, poll or retrieve it later, and then handle succeeded, errored, canceled, or expired results individually.
const batch = await client.messages.batches.create({
requests: [
{
custom_id: 'release-note-1',
params: {
model: 'claude-opus-4-6',
max_tokens: 200,
messages: [{ role: 'user', content: 'Summarize this changelog.' }],
},
},
],
});
console.log(batch.id);Batch result handling should be defensive. The exported result names distinguish succeeded, errored, canceled, and expired individual responses, which means downstream code should switch on each result variant rather than assuming every custom ID produced a message. For operational jobs, store the batch ID and each custom_id in your database before waiting for completion. That gives you an audit trail and lets you resume result collection if the worker process exits midway through a long batch.
Sources: src/resources/messages/index.ts
Provider Streaming Notes
The same cookbook patterns apply across the main Claude API package and provider SDK packages, but the transport layer can differ. The AWS, Foundry, and Vertex provider packages expose their streaming entry points by re-exporting the shared core streaming module. That keeps the application-facing stream model aligned with the main SDK: your code should still think in terms of Anthropic message events, text deltas, and final message metadata rather than provider-specific frame formats.
Bedrock is the notable adapter in the supplied source. Its streaming module converts AWS binary EventStream responses into the SSE format used by the Anthropic API. Chunk frames are parsed as JSON, frames with a type become named SSE events, AWS exception frames become SSE error events with an Anthropic-shaped error body, and the normalized response sets content-type to text/event-stream; charset=utf-8 while removing content-length. This is why application code can consume Bedrock streaming through the SDK’s Anthropic-style stream helpers instead of writing an AWS event-stream parser.
Sources: packages/aws-sdk/src/core/streaming.ts, packages/bedrock-sdk/src/core/streaming.ts, packages/foundry-sdk/src/core/streaming.ts, packages/vertex-sdk/src/core/streaming.ts
Next Steps
Start with the basic messages.create() recipe, then move to messages.stream() when the user experience needs incremental output. Add explicit stop-reason handling before shipping a streaming UI, especially for refusal and truncation cases. For high-volume offline work, wrap message parameters in batch requests and persist batch IDs. If you are deploying on Bedrock, Vertex, Foundry, or the Anthropic AWS package, keep your application logic provider-neutral and let the package streaming adapters normalize the wire format.
Related pages: messages-api, streaming-responses, message-batches, thinking-and-effort, request-options-errors-retries