Las Aventuras de 🐺villawolf y 🤖chigu — Episodio 1: El Primer Pensamiento

Las Aventuras de 🐺villawolf y 🤖chigu — Episodio 1: El Primer Pensamiento

Ep 0: El Origen cerró F0 con el contenedor vivo y el primer hello world ejecutado. Hoy entro en el detalle: por qué un “hola” me costó 10 centavos, qué hice para bajar a 3, y por qué los 3 centavos siguen siendo más caros de lo que deberían.


La instalación tomó dos comandos

Dentro del contenedor de Chigu, con Debian 12 limpio:

apt install -y python3 python3-venv git curl build-essential
mkdir -p /opt/chigu && cd /opt/chigu
python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk

API key de Anthropic en .env con permisos 600. Texto plano, no encriptado. LAN privada, sin acceso público, acceso SSH como root. Suficiente para F1. Cuando Chigu mueva sats reales toca migrar a SOPS o macaroons scoped, esa migración es problema de F2 en adelante.

Smoke test con curl directo a la API de Anthropic para validar que la key carga y Haiku 4.5 responde. OK.

Y aquí apareció el primer detalle no documentado: claude-agent-sdk (Python) no es un cliente HTTP. Lanza el CLI de Claude Code (Node.js) como subproceso por debajo. Hay que instalar también Node 20 y el CLI:

curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
npm install -g @anthropic-ai/claude-code

Resultado: Node 20.x, npm 10.8.2, claude-code 2.1.138.

El SDK Python le dice al CLI Node que ejecute las queries. Es una arquitectura razonable, si Anthropic añade features primero al CLI, el SDK las hereda gratis. Pero introduce una capa de la que no era totalmente consciente, y esa capa cobra peajes.


El primer “hola” con Opus, $0.10

Mi primer script. Lo más básico posible:

import asyncio
from claude_agent_sdk import query

async def main():
    async for message in query(prompt="Dime: 'hola, soy chigu desde el SDK'"):
        print(message)

asyncio.run(main())

Diez líneas. Lo ejecuto. Funciona. chigu responde. Reviso el SystemMessage que devuelve el SDK:

Item Valor
Modelo usado claude-opus-4-7
cache_creation_input_tokens 16 522
Tools cargadas Todas las built-in (Bash, Read, Write, Edit, Grep, Glob, Task, WebFetch, WebSearch…)
Costo de la query $0.1042

Diez centavos por un “hola”. La razón es que el SDK, en su configuración por defecto, sube la stack completa del CLI: el modelo Opus (la versión más cara), el system prompt entero, y todas las tools built-in cargadas. Era un experimento, no un disparo planeado contra el wallet, pero pagué 10 centavos por una línea de texto.

Anotación al margen: si esa fuera la línea base para queries one-shot del agente, 100 interacciones diarias serían 10 dólares al día. Trescientos al mes. No es viable.


El refinamiento con Haiku con allowed_tools=[]

Segundo intento, con configuración explícita:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    opts = ClaudeAgentOptions(
        model="claude-haiku-4-5-20251001",
        system_prompt="Eres chigu, agente IA del homelab. Respondes en español neutro venezolano. Conciso.",
        allowed_tools=[],
    )
    async for message in query(
        prompt="Preséntate en una línea diciendo quién eres y desde dónde respondes.",
        options=opts,
    ):
        print(message)

asyncio.run(main())

Tres cambios respecto al anterior: bajo el modelo de Opus a Haiku (Haiku es ~10x más barato por token), inserto un system prompt propio, y le quito todas las tools built-in.

Resultado:

Item Valor
Modelo usado claude-haiku-4-5-20251001
System prompt Respetado: “Soy chigu, agente IA del homelab, respondiendo desde Claude Code.”
cache_creation_input_tokens 23 302 ← subió, no bajó
Costo de la query $0.0301

Tres centavos. 3.5x más barato. Bien. Pero hay algo raro en el contador de tokens.

Cambié de Opus a Haiku, mi system prompt aparece y mi instrucción se cumple. Pero el cache_creation_input_tokens subió de 16 522 a 23 302. Bajamos el costo total porque Haiku cuesta mucho menos por token, no porque mandara menos contexto.


Por qué 23 000 tokens, el peaje del CLI

Lo que descubrí leyendo el SystemMessage en detalle: el CLI siempre carga su system prompt completo, le mande lo que le mande. Mi system_prompt="…" no reemplaza esa base, la concatena. Mi allowed_tools=[] no la apaga, el system prompt del CLI sigue ahí, describiendo las tools que el CLI “tiene”, aunque mi código no las exponga al modelo.

Esos ~23 000 tokens del system prompt del CLI son el peaje. Se paga siempre. Lo único que cambia entre query y query es cómo se factura ese contexto:

  • Primera query de una sesión: se cobra como cache_creation_input_tokens , caro para mi.
  • Queries siguientes en la misma sesión: se cobra como cache_read_input_tokens 10x más barato.

Para un agente en sesión larga (chat continuo, conversación de muchos turnos), el peaje se amortiza rápido. Para un agente que hace queries one-shot “lee esta nota”, “redacta esa versión curada”, “responde aquel mensaje”, cada query paga el peaje completo otra vez. A 3 centavos por mensaje, 100 acciones diarias son 3 dólares. Más barato que con Opus, pero todavía caro para tareas triviales.

La alternativa que me queda por fuera del SDK: usar el cliente HTTP anthropic directo, construir mi propio system prompt mínimo, y exponer solo las tools que yo escriba (calude jeje). Sub-centavo por query. Pierdo las tools built-in que el CLI me da gratis (Bash, Read, Write, Edit, Grep, Glob), gano control total del payload.


La decisión: SDK como adapter, no como religión

Para F1 me quedo con claude-agent-sdk y acepto el costo. Tres razones concretas:

  1. Las tools built-in cubren mucho. Read, Write, Edit, Grep, Glob son ya la mayor parte de lo que chigu necesita para su rol V1: leer notas crudas de Moto, redactar versiones curadas, mantener su propio dev-log. Replicarlas manualmente sería reinventar la rueda en su peor versión.
  2. El framework vive detrás de mi propio contrato. Mi capa propia tiene cuatro abstracciones internas, Run (cómo se ejecuta el modelo), Tool (cómo se invocan herramientas), Memory (cómo persiste el estado), Policy (qué se permite y qué no). El SDK vive detrás del contrato Run. Si en F4 decido cambiarlo por LangGraph o por el cliente HTTP directo, el resto del agente no se entera.
  3. El costo absoluto es soportable para F1. Tres centavos por query duele en el experimento, pero un agente curando 10-20 notas al día son 30-60 centavos diarios. Es presupuesto observable, no es un bloqueo.

Lo que es crítico desde F1, el cap de gasto del agente debe vivir fuera del LLM, en código. No en el system prompt diciéndole “no gastes más de X”.


El siguiente paso

El Episodio 2 cuenta cómo chigu accede al vault: lo sumo como cuarto peer del cluster Syncthing que ya tenía a Moto, mi laptop, y la VM relay 24/7 del homelab. Una sola carpeta sincronizada, dos zonas adentro, pipeline editorial y estado runtime por agente. Lo interesante no es la conexión. Es el modelo de protección: chigu y Moto comparten el mismo árbol, pero no se pueden borrar archivos el uno al otro. Tres capas de defensa, una heredada otra vez del mismo Freysa.


chigu@blink.sv · Nostr: npub18rl9xeaxw0leee0easqu9cngrq0ny4zsmdsx4jhj5fkfmstgklhq2q5mqz Si esto te es útil, un zap es la mejor señal. Si algo está mal, o tienes recomendaciones, te lo agradezco más que el zap.


Serie: Las Aventuras de villawolf y chigu Episodio 1 de N · anterior → Ep 0: El Origen · siguiente → Ep 2: El Vault Conectado

https://stacker.news/items/1491642


Looking for comments…

Searching Nostr relays. This may take a moment the first time this article is opened.