Configuración completa de pi + OpenRouter (modelos gratis con tooling)

Fecha: 21/9/2026 · PC: GTX 1050 2GB, lenta para LLMs locales → se usan modelos remotos gratis de OpenRouter. Estado: ✅ FUNCIONANDO — pi corre con default qwen/qwen3.8-27b:free y ejecuta tools (bash, write, curl, ls).


1. Por qué esto

El camino empezó buscando cómputo de IA “tipo torrent” (como Petals o AI Horde), pero esas redes:

  • Petals → el cliente se conecta, pero el swarm público está vacío de seeders (0 servidores sirviendo bloques).
  • AI Horde → tiene swarm vivo (36+ workers) pero no emite tool_calls: los modelos solo responden texto plano, sin JSON estructurado de herramientas. Un agente de código no puede ejecutar tareas.

Solución final: OpenRouter → gateway de modelos con capa gratis (:free) que sí emiten tool_calls de verdad. Todo el cómputo pesado corre en servidores de OpenRouter; tu PC solo corre pi + sus herramientas locales (read/bash/edit/write).


2. Estado inicial

  • pi ya instalado: /home/esotericwarfare/.local/bin/pi → symlink a /mnt/linux2/pi/bin/pi (v0.85.1).
  • Config en ~/.pi/agent/:
    • auth.json{} (sin credenciales).
    • models.json → solo provider local (Qwen3 0.6B/1.7B vía llama.cpp en localhost:8001).
    • settings.json → solo theme dark.
  • OPENROUTER_API_KEY="sk-or-v1-..." ya estaba exportada en ~/.bashrc (línea 106).
  • Herramientas de red: openrouter.ai responde 200 OK (0.29s) desde esta máquina. github.com y health.petals.dev NO responden (curl 000).

3. Configuración final (los 3 archivos)

3.1 ~/.pi/agent/auth.json → dejado en {}

{}

⚠️ Importante: pi (provider openrouter) NO lee la key de auth.json. La lee de la variable de entorno OPENROUTER_API_KEY (verificado en pi-ai/dist/env-api-keys.js, línea 87: openrouter: "OPENROUTER_API_KEY"). Un JSON con formato raro en auth.json hace que pi diga Provider is not configured: openrouter — por eso se dejó vacío.

3.2 ~/.bashrc (ya tenía la key)

export OPENROUTER_API_KEY="XXX"

3.3 ~/.pi/agent/settings.json — EL ARCHIVO CLAVE

{
  "lastChangelogVersion": "0.85.1",
  "theme": "dark",
  "defaultModel": "qwen/qwen3.8-27b:free",
  "defaultProvider": "openrouter"
}

⚠️ El campo correcto es defaultModel + defaultProvider, NO "model". Un "model" ahí no surte efecto y pi cae al catálogo embebido del último provider. (Le pregunté a pi mismo y confirmó: “El campo es defaultModel (junto con defaultProvider)… ~/.pi/agent/settings.json.)


4. Por qué Qwen 3.8-27b y no Nemotron (los errores 402/429)

Esto costó descubrirlo. Los 21 modelos :free de OpenRouter tienen límite de ~4K tokens de salida por request gratis. Pero los modelos vienen de un catálogo embebido en pi con su propio maxTokens:

Modelo max_out según catálogo de pi Resultado
nvidia/nemotron-3-super-120b-a12b:free 235.9K 402 “requested up to 234K tokens, can only afford 3593”
google/gemma-4-31b-it:free 4.1K ⚠️ 429 rate-limited upstream (temporal)
qwen/qwen3.8-27b:free 4.1K ✅ funciona
  • Cuando pi usa el default desde el catálogo embebido, manda max_tokens gigante → OpenRouter rechaza con 402 (sin crédito suficiente).
  • Cuando pasás --model xxx:free explícito por CLI, pi a veces usa el id propio y manda max_tokens chico → entra.
  • Remedio elegido: default = qwen/qwen3.8-27b:free, cuyo catálogo ya pide 4.1K, cabe en el free-tier y soporta tools.

Nota: Verificar el max-out de un modelo con:

pi --list-models openrouter | grep <modelo>

La 2ª columna numérica (context) y 3ª (max-out) indican qué pedirá pi. Si max-out > ~8K en un modelo :free, esperate un 402.


5. Comandos útiles

# verificar credenciales
pi auth check --provider openrouter --json
# → {"status":"ready","provider":"openrouter","authType":"api_key"}

# listar modelos (catálogo con context/max-out)
pi --list-models openrouter
pi --list-models

# correr pi interactivo (usa el default de settings.json)
pi

# correr pi con un modelo específico
pi --provider openrouter --model "qwen/qwen3.8-27b:free"

# modo no interactivo (un solo mensaje)
pi --print "ejecuta ls y decime que ves"

# ver el estado de TODOS los providers
pi auth

6. Pruebas realizadas (todo verificado ✅)

Prueba Comando Resultado
date vía bash pi --provider openrouter --model "nvidia/...:free" --print "ejecuta date" ✅ respondió día real
Crear archivo --print "crea /tmp/opencode/prueba_pi.txt con 'hola desde openrouter'" ✅ contenido exacto
Acceder a web --print "curl opencode.ai/docs y resume" ✅ “OpenCode es un agente de code de IA para terminal”
ls --print "ejecuta ls en /tmp/opencode y cuenta" ✅ 38 archivos + 6 dirs
Default sin flags pi --print "ejecuta ls..." (sin --model) ✅ usa qwen y ejecuta tools

El loop de agente (modelo emite tool_calls → pi ejecuta la herramienta → devuelve resultado → el modelo continúa) funciona end-to-end.


7. Modelos :free disponibles con tools (OpenRouter)

Verificados via API (21 gratis; todos con tools=True salvo 2):

google/gemma-4-31b-it:free                 google/gemma-4-26b-a4b-it:free
qwen/qwen3.8-27b:free                     
nvidia/nemotron-3-ultra-550b-a55b:free      (potente, pero max-out gigante → 402 sin créditos)
nvidia/nemotron-3-super-120b-a12b:free      (idem, 235.9K → 402)
nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free
thinkingmachines/inkling:free / inkling-small:free
poolside/laguna-s-2.1:free / laguna-xs-2.1:free
cohere/north-mini-code:free
minimax/minimax-m2.7:free  minimax/minimax-m3:free
dots-studio/dots-3-note-preview:free
liquid/lfm-2.5-2.6b:free
inclusionai/ling-3.0-flash-*:free
z-ai/glm-5.2:free (sin tools)

Criterio de elección para que funcione gratis:

  1. Que aparezca en pi --list-models openrouter con max-out ≤ ~8K.
  2. Que tenga tools (la columna de thinking/images no importa, esto sí).
  3. Para coding, los mejores de esta lista: qwen/qwen3.8-27b:free, gemma-4-*/:free, cohere/north-mini-code:free, poolside/laguna-*:free.

8. Cómo cambiar de modelo

# 1. ver ids
pi --list-models openrouter | grep ":free"

# 2. probar en una llamada (sin tocar config)
OPENROUTER_API_KEY="sk-or-v1-..." pi --provider openrouter --model "google/gemma-4-31b-it:free" --print "hola"

# 3. si anda, fijarlo como default
#    editar ~/.pi/agent/settings.json:
#      "defaultModel": "google/gemma-4-31b-it:free"
#      "defaultProvider": "openrouter"

9. Limitaciones y troubleshooting

  • 402 “requires more credits / fewer max_tokens” → el maxTokens del catálogo excede el free-tier. Usá un modelo con max-out ≤8K (o cargá credits en https://openrouter.ai/settings/credits).
  • 429 “temporarily rate-limited” → el proveedor upstream (p. ej. Google AI Studio) está saturado en su pool compartido; esperá unos minutos o cambiá de modelo. (“add your own key” en OpenRouter te da tu propio pool).
  • “Provider is not configured” → revisá que auth.json esté en {} y que OPENROUTER_API_KEY esté exportada (o export en la shell).
  • Free tier no es para producción → límite de tasa. Para uso fluido, los modelos de pago por uso de OpenRouter son muy baratos (~USD 0.01–0.06 / M tokens).

10. Archivos tocados

Archivo Estado Uso
~/.pi/agent/auth.json {} (limpio) la key NO va acá para openrouter
~/.pi/agent/settings.json defaultModel + defaultProvider el archivo clave
~/.pi/agent/models.json sin cambios provider local (Qwen3) intacto
~/.pi/agent/models.json.bak backup del models.json original
~/.bashrc (línea 106) export OPENROUTER_API_KEY ya existía

11. Resumen del recorrido (qué se probó antes)

  1. Petals (P2P real tipo torrent): setup completo en /mnt/linux2/petals-client/.venv (Python 3.11, hivemind parcheado). Conectó al bootstrap, cargó el modelo del swarm, pero MissingBlocksError: no servers holding blocks online → swarm sin seeders. (Archivo: dht_check.py)
  2. AI Horde (swarm de voluntarios): horde.py funcional para generar texto/imágenes con GPUs ajenas (sin tools). Verificado: worker Kobold-Scribe generó con un Llama-3.2-3B. Conclusión: no sirve para agentes (tools_test.py probó los 5 models aphrodite — ninguno emite tool_calls).
  3. OpenRouter + pi: ✅ la solución final, documentada arriba.
  4. pi + tinygrad local: tu GTX 1050 con Qwen3-0.6B sigue disponible como provider local en models.json (para cuando quieras cero dependencia de red).

Anexo — evidencia de que AI Horde no emite tool_calls

Con aphrodite/TheDrummer/Cydonia-24B-v4.3 (backend que debería soportar function calling):

User:  "Llama la herramienta get_weather('Buenos Aires')"
Model: "Let me check the current weather for Buenos Aires... I don't have r..."  ← texto, no JSON

(Hasta Skyfall-31B-v4.2 — el flagship RP — “imita” la llamada escribiéndola como texto plano, sin tool_calls estructurado.)