Anthropic Messages
Usa Claude a mitad de precio con tu código actual del SDK de Anthropic. Cambia la URL base; streaming, thinking, uso de funciones, caché y conteo siguen igual.
Si tu código ya habla con Claude mediante el SDK de Anthropic, pasarlo a Half Off Dev son dos ajustes: la URL base https://halfoff.dev y tu clave de Half Off Dev. POST /v1/messages y POST /v1/messages/count_tokens se comportan como Anthropic especifica y el cuerpo de la petición se reenvía sin tocar, así que la referencia de la API de Anthropic sigue siendo tu manual para cada campo. Cada token se cobra a mitad del precio de lista.
Apunta el SDK a Half Off Dev#
El SDK de Anthropic envía la clave en x-api-key; también se acepta como Authorization: Bearer.
curl https://halfoff.dev/v1/messages \
-H "x-api-key: $HALFOFF_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5.5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Propón tres nombres para un bot que revisa código."}]
}'Si tu código crea un cliente por defecto, ni siquiera hay que editarlo: los SDK leen ANTHROPIC_BASE_URL y ANTHROPIC_API_KEY del entorno, así que basta con export ANTHROPIC_BASE_URL=https://halfoff.dev y tu clave.
La gama actual de Claude incluye claude-fable-5.1, claude-opus-5.5, claude-sonnet-5.5 y claude-haiku-5.5, y las versiones anteriores siguen disponibles. La lista de referencia, con precios, está en GET /v1/models.
Recibe los tokens según se generan#
Envía stream: true o usa el helper de streaming del SDK. Los eventos siguen la secuencia de Anthropic: message_start, content_block_start, content_block_delta, content_block_stop, message_delta, message_stop.
with client.messages.stream(
model="claude-sonnet-5.5",
max_tokens=2048,
messages=[{"role": "user", "content": "Redacta una nota de versión breve para una versión de corrección de errores."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
final = stream.get_final_message()
print("\n", final.usage)Hasta que llega el primer token, el gateway se guarda el stream; si el canal falla en ese intervalo, otro toma el relevo y tú no ves el fallo. Los detalles están en Streaming.
Deja que Claude llame a tus funciones#
Describe cada función con un input_schema en JSON Schema. Una respuesta con stop_reason: "tool_use" te pide que la ejecutes; contesta con un bloque tool_result.
tools = [{
"name": "convert_currency",
"description": "Convierte un importe entre dos monedas.",
"input_schema": {
"type": "object",
"properties": {
"amount": {"type": "number"},
"from_currency": {"type": "string"},
"to_currency": {"type": "string"},
},
"required": ["amount", "from_currency", "to_currency"],
},
}]
messages = [{"role": "user", "content": "¿Cuánto son 250 EUR en JPY?"}]
response = client.messages.create(
model="claude-sonnet-5.5", max_tokens=1024, tools=tools, messages=messages,
)
if response.stop_reason == "tool_use":
call = next(b for b in response.content if b.type == "tool_use")
result = {"converted": 40125.0, "currency": call.input["to_currency"]} # tu código aquí
messages += [
{"role": "assistant", "content": response.content},
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": call.id, "content": str(result)},
]},
]
response = client.messages.create(
model="claude-sonnet-5.5", max_tokens=1024, tools=tools, messages=messages,
)
print(response.content[0].text)tool_choice, strict y el resto de opciones de Anthropic se reenvían tal cual; la guía de uso de funciones las documenta.
Activa el pensamiento extendido#
Envía thinking y output_config con la forma que Anthropic define para el modelo que llamas. Los modelos recientes piensan de forma adaptativa y reciben un nivel de esfuerzo; Claude 4.5 y anteriores esperan un budget_tokens fijo. Las reglas de cada modelo están en la guía de thinking de Anthropic.
reply = client.messages.create(
model="claude-opus-5.5",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
output_config={"effort": "high"},
messages=[{"role": "user", "content": "Un tren sale a las 09:40 y llega a las 14:05. ¿Cuántos minutos dura el viaje?"}],
)
for block in reply.content:
if block.type == "thinking":
print("Razonamiento:", block.thinking)
elif block.type == "text":
print("Resultado:", block.text)El pensamiento cuenta dentro de usage.output_tokens, así que se cobra a la tarifa de salida (a mitad de precio). Si la conversación continúa tras una llamada a función, devuelve los bloques de thinking exactamente como los recibiste.
Guarda en caché el prefijo que reenvías#
Pon cache_control en el último bloque de la parte que no cambia entre llamadas. La primera llamada escribe la caché; cualquier llamada posterior que empiece con el mismo prefijo la lee por una pequeña fracción de la tarifa de entrada.
response = client.messages.create(
model="claude-sonnet-5.5",
max_tokens=1024,
system=[{
"type": "text",
"text": STYLE_GUIDE,
"cache_control": {"type": "ephemeral"},
}],
messages=[{"role": "user", "content": "Reescribe este titular según la guía: 'Ya están los números del T3'"}],
)
u = response.usage
print(u.cache_creation_input_tokens, u.cache_read_input_tokens, u.input_tokens)Lo que pagas en claude-sonnet-5.5, por millón de tokens: $1.00 por la entrada sin caché, $1.25 por escritura en caché y $0.05 por lectura de caché. Un prefijo por debajo del mínimo del modelo no se guarda, y ambos campos de caché vuelven a cero. El gateway devuelve cada conversación al canal que tiene su caché; en Caché de prompts tienes el panorama completo.
Cuenta los tokens antes de enviar#
POST /v1/messages/count_tokens acepta el cuerpo de un mensaje sin max_tokens y responde con input_tokens. No cuesta nada y funciona aunque tu saldo sea cero.
curl https://halfoff.dev/v1/messages/count_tokens \
-H "x-api-key: $HALFOFF_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model": "claude-sonnet-5.5",
"messages": [{"role": "user", "content": "¿Cuánto mide este prompt?"}]}'Una estimación, no la factura
El recuento sirve para comprobar un prompt frente a la ventana de contexto o para presupuestar. Lo que se te cobra sale siempre del bloque usage de la respuesta real del modelo.
Claude Code#
Claude Code usa esta misma API. Exporta ANTHROPIC_BASE_URL=https://halfoff.dev y pon tu clave en ANTHROPIC_AUTH_TOKEN; cada sesión se mantiene en un canal para que su caché siga caliente. La configuración paso a paso, incluidos los ajustes de modelo, está en Claude Code.
Cabeceras de la petición#
| Cabecera | Comportamiento |
|---|---|
x-api-key o Authorization: Bearer | Tu clave de Half Off Dev. Obligatoria. |
anthropic-version | Se reenvía; 2023-06-01 si la omites. |
anthropic-beta | Se reenvía sin cambios. |
x-halfoff-group | Opcional. Elige el grupo de canales para esta petición, salvo que la clave ya esté vinculada a uno. |
x-session-id | Opcional. Marca peticiones como una misma conversación para el enrutamiento según caché. metadata.user_id en el cuerpo tiene el mismo efecto. |
Las demás cabeceras se descartan. Los errores mantienen la forma de Anthropic, {"type": "error", "error": {"type": "...", "message": "..."}}; los códigos están en Errores.