Streaming considerations
When using streaming, stop_reason is:
nullin the initialmessage_starteventProvided in the
message_deltaeventNot provided in any other events
bash# The message_delta event in the SSE stream carries stop_reason. curl --no-buffer https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-5", "max_tokens": 1024, "stream": true, "messages": [{"role": "user", "content": "Hello!"}] }'bash# stop_reason appears in the message_delta event. ant messages create --stream --format jsonl \ --model claude-opus-5 \ --max-tokens 1024 \ --message '{role: user, content: "Hello!"}' | jq -c 'select(.type == "message_delta") | .delta.stop_reason'pythonclient = anthropic.Anthropic() with client.messages.stream( model="claude-opus-5", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}], ) as stream: for event in stream: if event.type == "message_delta": stop_reason = event.delta.stop_reason if stop_reason: print(f"Stream ended with: {stop_reason}")typescriptconst client = new Anthropic(); const stream = client.messages.stream({ model: "claude-opus-5", max_tokens: 1024, messages: [{ role: "user", content: "Hello!" }] }); for await (const event of stream) { if (event.type === "message_delta" && event.delta.stop_reason) { console.log(`Stream ended with: ${event.delta.stop_reason}`); } }csharpAnthropicClient client = new(); var parameters = new MessageCreateParams { Model = Model.ClaudeOpus5, MaxTokens = 1024, Messages = [new() { Role = Role.User, Content = "Hello!" }] }; await foreach (var streamEvent in client.Messages.CreateStreaming(parameters)) { switch (streamEvent.Value) { case RawMessageDeltaEvent deltaEvent when deltaEvent.Delta.StopReason is not null: Console.WriteLine($"Stream ended with: {deltaEvent.Delta.StopReason}"); break; } }goclient := anthropic.NewClient() stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{ Model: anthropic.ModelClaudeOpus5, MaxTokens: 1024, Messages: []anthropic.MessageParam{ anthropic.NewUserMessage(anthropic.NewTextBlock("Hello!")), }, }) // Accumulate events into the final Message, which carries stop_reason. message := anthropic.Message{} for stream.Next() { if err := message.Accumulate(stream.Current()); err != nil { log.Fatal(err) } } if err := stream.Err(); err != nil { log.Fatal(err) } if message.StopReason != "" { fmt.Printf("Stream ended with: %s\n", message.StopReason) }javaAnthropicClient client = AnthropicOkHttpClient.fromEnv(); MessageCreateParams params = MessageCreateParams.builder() .model(Model.CLAUDE_OPUS_5) .maxTokens(1024L) .addUserMessage("Hello!") .build(); // Accumulate events into the final Message, which carries stop_reason. MessageAccumulator accumulator = MessageAccumulator.create(); try (StreamResponse<RawMessageStreamEvent> streamResponse = client.messages().createStreaming(params)) { streamResponse.stream().forEach(accumulator::accumulate); } accumulator.message().stopReason().ifPresent(stopReason -> IO.println("Stream ended with: " + stopReason) );php$client = new Client(); $stream = $client->messages->createStream( maxTokens: 1024, messages: [['role' => 'user', 'content' => 'Hello!']], model: 'claude-opus-5', ); foreach ($stream as $event) { if ($event instanceof RawMessageDeltaEvent && $event->delta->stopReason !== null) { echo "Stream ended with: {$event->delta->stopReason}", PHP_EOL; } }rubyclient = Anthropic::Client.new stream = client.messages.stream( model: "claude-opus-5", max_tokens: 1024, messages: [{ role: "user", content: "Hello!" }] ) stream.each do |event| next unless event.type == :message_delta stop_reason = event.delta.stop_reason puts "Stream ended with: #{stop_reason}" if stop_reason end