---
name: stream_anthropic_messages
kind: function
lang: py
domain: core
version: "1.0.0"
purity: impure
signature: "def stream_anthropic_messages(messages: list, model: str = \"claude-opus-4-8\", system: str = \"\", tools: list = None, max_tokens: int = 4096, token: str = \"\") -> Iterator[dict]"
description: "Llama a https://api.anthropic.com/v1/messages con stream:true usando el token OAuth de Claude Code y hace yield de eventos normalizados: text, tool_use_start, tool_input_delta, done, error. Parsea el SSE en tiempo real. Si token vacio llama load_claude_oauth_token automaticamente."
tags: [claude-direct, anthropic, streaming, sse, llm, tools, http]
uses_functions: [load_claude_oauth_token_py_core]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [json, sys, typing.Iterator, httpx]
params:
  - name: messages
    desc: "lista de mensajes Anthropic [{role: user|assistant, content: ...}]"
  - name: model
    desc: "ID del modelo Anthropic. Default: claude-opus-4-8"
  - name: system
    desc: "system prompt opcional. Si vacio no se incluye en el body"
  - name: tools
    desc: "lista de tool definitions [{name, description, input_schema}]. None para no usar tools"
  - name: max_tokens
    desc: "maximo de tokens en la respuesta. Default 4096"
  - name: token
    desc: "access token OAuth. Si vacio se carga automaticamente desde ~/.claude/.credentials.json"
output: "Iterator[dict] — eventos normalizados: {type:text,text}, {type:tool_use_start,id,name,index}, {type:tool_input_delta,index,partial_json}, {type:done,stop_reason}, {type:error,message}"
tested: true
tests:
  - "parse_sse_chunk text delta emite evento text"
  - "parse_sse_chunk tool_use_start emite evento tool_use_start con id y name"
  - "parse_sse_chunk tool_input_delta emite evento tool_input_delta con partial_json"
  - "parse_sse_chunk message_delta con stop_reason emite done"
  - "parse_sse_chunk secuencia completa text PONG reconstruye el texto"
  - "parse_sse_chunk secuencia completa tool_use reconstruye el input JSON"
test_file_path: "python/functions/core/stream_anthropic_messages_test.py"
file_path: "python/functions/core/stream_anthropic_messages.py"
---

## Ejemplo

```python
import sys
sys.path.insert(0, "python/functions/core")
from stream_anthropic_messages import stream_anthropic_messages

text = ""
for event in stream_anthropic_messages(
    messages=[{"role": "user", "content": "di solo PONG"}],
    model="claude-haiku-4-5-20251001",
    max_tokens=32,
):
    if event["type"] == "text":
        text += event["text"]
        print(event["text"], end="", flush=True)
    elif event["type"] == "done":
        print(f"\n[stop_reason={event['stop_reason']}]")
    elif event["type"] == "error":
        print(f"ERROR: {event['message']}", file=sys.stderr)

print("respuesta completa:", text)
```

## Cuando usarla

Cuando necesites hablar directamente con la API de Anthropic desde Python
sin lanzar la CLI `claude`, especialmente cuando quieras streaming en tiempo
real del texto o necesites ejecutar tools propias via `run_claude_tool_loop`.
Tambien util para integrar Claude en scripts de analisis donde el bucle
de tools se gestiona en Python.

## Gotchas

- **El parser SSE es puro y testeable**: `parse_sse_chunk` no hace HTTP.
  Puedes testear el parseo completo sin mocks de red.
- **Eventos `raw` son pass-through**: `message_start`, `content_block_stop`,
  `ping` y otros eventos no mapeados se emiten como `{type: raw, event: ..., data: ...}`.
  El consumidor los puede ignorar o inspeccionar.
- **Reconstruccion de tool input**: los `partial_json` de un mismo `index`
  deben concatenarse hasta el evento `done`. `run_claude_tool_loop` hace esto
  automaticamente.
- **Timeout 120s**: configurable en el codigo si necesitas respuestas muy largas.
- La funcion `parse_sse_chunk` es pure (importable y testeable por separado).
