Fecha: 21/9/2026 · PC: GTX 1050 2GB, lenta para LLMs locales → se usan modelos remotos gratis de OpenRouter. Estado: ✅ FUNCIONANDO —
picorre con defaultqwen/qwen3.8-27b:freey ejecuta tools (bash, write, curl, ls).
El camino empezó buscando cómputo de IA “tipo torrent” (como Petals o AI Horde), pero esas redes:
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).
pi ya instalado: /home/esotericwarfare/.local/bin/pi → symlink a /mnt/linux2/pi/bin/pi (v0.85.1).~/.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).openrouter.ai responde 200 OK (0.29s) desde esta máquina. github.com y health.petals.dev NO responden (curl 000).~/.pi/agent/auth.json → dejado en {}{}
⚠️ Importante: pi (provider
openrouter) NO lee la key de auth.json. La lee de la variable de entornoOPENROUTER_API_KEY(verificado enpi-ai/dist/env-api-keys.js, línea 87:openrouter: "OPENROUTER_API_KEY"). Un JSON con formato raro enauth.jsonhace que pi digaProvider is not configured: openrouter— por eso se dejó vacío.
~/.bashrc (ya tenía la key)export OPENROUTER_API_KEY="XXX"
~/.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 esdefaultModel(junto condefaultProvider)…~/.pi/agent/settings.json”.)
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 |
max_tokens gigante → OpenRouter rechaza con 402 (sin crédito suficiente).--model xxx:free explícito por CLI, pi a veces usa el id propio y manda max_tokens chico → entra.qwen/qwen3.8-27b:free, cuyo catálogo ya pide 4.1K, cabe en el free-tier y soporta tools.Nota: Verificar el
max-outde 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.
# 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
| 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.
: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:
pi --list-models openrouter con max-out ≤ ~8K.tools (la columna de thinking/images no importa, esto sí).qwen/qwen3.8-27b:free, gemma-4-*/:free, cohere/north-mini-code:free, poolside/laguna-*:free.# 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"
maxTokens del catálogo excede el free-tier. Usá un modelo con max-out ≤8K (o cargá credits en https://openrouter.ai/settings/credits).auth.json esté en {} y que OPENROUTER_API_KEY esté exportada (o export en la shell).| 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 |
/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)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).local en models.json (para cuando quieras cero dependencia de red).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.)