Serie: Sistemas Multi-Agente en tu Homelab — Post 5 de 8
Una de las preguntas más frecuentes cuando presentamos este sistema es: ¿cuál es la diferencia entre un skill, un tool y un agente? Los tres términos se usan en la literatura de LLMs pero con significados que varían por framework. Este post explica cómo funcionan en OpenClaw con ejemplos concretos de lo que tenemos en producción.
Los tres conceptos
flowchart TB
subgraph AG["AGENTE — LLM con memoria y contexto de conversación"]
subgraph SK["SKILL — Módulo especializado · instrucciones · personalidad · dominio"]
TO["TOOL\nFunción ejecutable: script Python · shell · API call"]
end
end
En términos simples: - Tool = un verbo. Algo que se puede hacer. - Skill = un rol. La configuración de quién eres cuando haces ese trabajo. - Agente = el actor. El LLM que decide cuándo usar qué y cómo presentar el resultado.
Los 6 skills en producción
Cada skill vive en ~/.openclaw/workspace/skills/<nombre>/SKILL.md y define:
- Cuándo activarse (descripción semántica para el router)
- Qué comandos ejecutar y cómo
- Reglas de formato de respuesta
- Qué NO hacer
mexico-noticias — Noticias de México
Propósito: Resumen imparcial del día combinando 6 medios mexicanos con distintas líneas editoriales.
Fuentes: | Medio | Línea editorial | |-------|----------------| | Animal Político | Independiente | | La Jornada | Izquierda | | El Universal | Centro | | Milenio | Centro | | El Financiero | Centro-derecha | | Proceso | Independiente |
Cómo funciona: El skill invoca mexico_noticias.py report, que hace scraping CDP de
cada sitio (son todos JavaScript-heavy), agrega los titulares, y los pasa a gemma4:26b
para generar el resumen. El modelo más grande (26B) aquí no es accidental: la tarea requiere
síntesis de múltiples perspectivas editoriales con criterio.
Triggers: "noticias", "qué pasó hoy", "resumen del día", "qué está pasando"
Caché: 2 horas (ventanas de reloj par)
intl-noticias — Noticias internacionales
Propósito: Perspectiva global con representación geográfica balanceada. El diseño intencional con medios de distintas regiones reduce el sesgo de una sola visión del mundo.
Fuentes: | Medio | Región / perspectiva | |-------|---------------------| | Reuters | Global, neutral | | BBC | UK, centro | | Al Jazeera | Sur global, Qatar | | DW / Deutsche Welle | Alemania, centro | | France 24 | Francia, centro | | The Guardian | UK, centro-izquierda | | AP News | Global, neutral | | El País English | España, centro |
Cómo funciona: Similar a mexico-noticias pero con CDP en perfiles separados
("intl") para mantener cookies de cada sitio aisladas. Usa gemma4:e4b (más rápido,
suficiente para este nivel de síntesis).
Triggers: "noticias internacionales", "qué pasa en el mundo", "world news"
maker-noticias — Noticias maker, hardware y hacking
Propósito: Feed curado para la comunidad maker: proyectos de hardware, hacks, nuevos microcontroladores, tutoriales de electrónica.
Fuentes: | Medio | Especialidad | |-------|-------------| | Hackaday | Hacks y proyectos de ingeniería | | Hackster.io | Proyectos maker de comunidad | | Make Magazine | DIY y maker culture | | Adafruit Blog | Electrónica y componentes | | Arduino Blog | Arduino y sistemas embebidos | | Tom's Hardware | Hardware de PC y chips |
Diferencia técnica clave: Este skill usa RSS en lugar de CDP. Los sitios de comunidad
maker publican feeds RSS bien mantenidos con contenido completo. Adafruit en particular
incluye el artículo completo en <content:encoded>, lo que evita el scraping del sitio
(que usa Cloudflare).
Caché: 4 horas
cdmx-tcg-events — Eventos Pokémon TCG en CDMX
Propósito: El skill más interactivo: no solo reporta, también responde preguntas específicas sobre tiendas, fechas, tipos de torneo y puede corregir datos manualmente.
Fuentes de datos:
| Fuente | Método | Información |
|--------|--------|-------------|
| pokemon.com | CDP (browser automation) | Torneos premier, dirección exacta, hora |
| pokedata.ovh | HTTP API REST | Ligas, amistosos, cobertura más amplia |
Comandos que el agente puede invocar:
# Semana completa
cdmx_events_combined.py report
# Filtros
cdmx_events_combined.py report --hoy
cdmx_events_combined.py report --fecha 2026-05-10
cdmx_events_combined.py report --type challenge # solo torneos serios
# Info de una tienda
cdmx_events_combined.py lookup "tao games"
# Corregir mapa erróneo (override persistente)
cdmx_events_combined.py venues fix "Thunder Empire" "https://maps.app.goo.gl/..."
Lo que lo hace especial: El agente puede corregir datos via venues fix. Cuando
un usuario dice "el mapa de Thunder Empire está mal", el skill ejecuta el override y
persiste el cambio en venue_overrides.json. Los fetches futuros respetan el override.
Esto es un patrón de aprendizaje activo via feedback del usuario sin reentrenamiento.
Triggers: "eventos en CDMX", "torneos esta semana", "dónde queda [tienda]",
"hay cups pronto", "eventos del sábado"
pokemon-dia — Pokémon del día
Propósito: El skill más liviano y el más querido por los usuarios. Envía la imagen oficial de un Pokémon junto con su tipo, número y entrada de Pokédex.
Cómo funciona: Llama a pokemon-dia-skill.sh, que consulta PokeAPI para obtener
datos y la imagen oficial, luego usa la función de envío de imágenes de OpenClaw para
mandarla directamente al chat. El skill rastrilla en la DB los Pokémon ya mostrados
para no repetir.
Modos:
# Random (sin repetir los ya vistos)
pokemon-dia-skill.sh random
# Pokémon específico
pokemon-dia-skill.sh get pikachu
pokemon-dia-skill.sh get 006 # por número
Nota arquitectónica importante: La respuesta del agente en este skill es solo el
output del script (✅). El script es el que envía el mensaje con imagen — no el LLM.
Este es un patrón donde el tool hace el trabajo real y el LLM solo orquesta.
Triggers: "pokémon del día", "sorpréndeme", "háblame de Charizard", cualquier
nombre de Pokémon solo
tcg-deck-analyst — Meta de Pokémon TCG
Propósito: Análisis del meta competitivo global: top 10 decks del formato Standard y City Leagues de Japón en los últimos 30 días.
Fuentes de datos:
| Fuente | Método | Datos |
|--------|--------|-------|
| play.limitlesstcg.com | API REST | Torneos Standard, decklists |
| limitlesstcg.com | Scraping | City League JP |
Diferencia con cdmx-tcg-events: Este skill responde qué decks ganan, el otro
responde dónde jugar. La descripción semántica de cada skill define explícitamente
a quién no debe enrutar:
# tcg-deck-analyst
description: "ONLY for deck meta analysis: top decks, what's winning...
NOT for: finding events, schedules, tournaments to attend"
# cdmx-tcg-events
description: "Use for ANY question about Pokémon TCG in CDMX: events, tournaments...
NOT for: deck meta, top decks, or what decks are winning"
Esta separación explícita en las descripciones es lo que permite al router del agente hacer la distinción correcta entre dos skills del mismo dominio (Pokémon TCG).
Triggers: "meta", "top decks", "qué decks ganan", "reporte de meta"
El mapa completo: un usuario, seis especialistas
flowchart TD
U["Usuario — WhatsApp"]
GW["Gateway — Router semántico\nanaliza descripción de cada skill"]
MX["mexico-noticias\nCDP · 6 medios\ngemma4:26b"]
IN["intl-noticias\nCDP · 8 medios\ngemma4:e4b"]
MA["maker-noticias\nRSS · 6 blogs\ngemma4:e4b"]
TC["cdmx-tcg-events\nCDP + API\nqwen3.5:9b"]
PK["pokemon-dia\nPokeAPI REST\nsin LLM"]
DA["tcg-deck-analyst\nlimitlesstcg\nqwen3.5:9b"]
U --> GW
GW --> MX
GW --> IN
GW --> MA
GW --> TC
GW --> PK
GW --> DA
Tabla comparativa de los 6 skills
| Skill | Dominio | Fuente de datos | Método fetch | LLM usado | Interactividad |
|---|---|---|---|---|---|
mexico-noticias |
Noticias MX | 6 medios web | CDP (JS) | gemma4:26b | Solo reporte |
intl-noticias |
Noticias intl | 8 medios web | CDP (JS) | gemma4:e4b | Solo reporte |
maker-noticias |
Maker/hardware | 6 blogs | RSS | gemma4:e4b | Solo reporte |
cdmx-tcg-events |
Eventos TCG | pokemon.com + API | CDP + HTTP | router (qwen3.5) | Alta — filtros, lookup, fix |
pokemon-dia |
Info Pokémon | PokeAPI | HTTP REST | ninguno | Media — por nombre/número |
tcg-deck-analyst |
Meta competitivo | limitlesstcg | HTTP + scraping | router (qwen3.5) | Solo reporte |
Cuándo el LLM es el worker vs. cuándo es el orquestador
Esta distinción es una de las más importantes del diseño:
LLM como worker (genera el output final):
- mexico-noticias, intl-noticias, maker-noticias: el LLM recibe los titulares
y produce el resumen. El output del agente es la generación del modelo.
LLM como orquestador (decide qué ejecutar, pasa el output):
- cdmx-tcg-events, tcg-deck-analyst, pokemon-dia: el LLM decide qué comando
correr y en qué formato presentar el resultado. El output viene del script, no del modelo.
La regla crítica en todos los skills de reporte es:
"Devuelve el stdout completo. Sin texto adicional."
Esto evita que el LLM "mejore" creativamente el output del script con información que no está en los datos (alucinación). Cuando el script es la fuente de verdad, el LLM es un passthrough.
La capa de tools: los scripts Python
Debajo de los skills hay 10+ scripts Python en ~/scripts/tools/. Estos son los
"tools" que el agente puede invocar — funciones ejecutables que hacen el trabajo real:
| Script | Qué hace | Método principal |
|---|---|---|
mexico_noticias.py |
Scraping + resumen noticias MX | CDP, Ollama |
intl_noticias.py |
Scraping + resumen noticias intl | CDP, Ollama |
maker_noticias.py |
Scraping + resumen maker | RSS, Ollama |
gaming_noticias.py |
Scraping + resumen gaming | RSS, Ollama |
cdmx_events_combined.py |
Eventos TCG CDMX (combinado) | CDP + HTTP API |
pokemon_events_browser.py |
Scraper pokemon.com | CDP |
cdmx_events.py |
Scraper pokedata.ovh | HTTP API |
pokemon_dia.py |
Info y foto de Pokémon | PokeAPI HTTP |
tcg-tournament-report-print.py |
Meta TCG report | limitlesstcg API |
sync_all_to_pg.py |
Sync SQLite → Postgres | psycopg2 |
db.py |
Utilidades SQLite compartidas | sqlite3 |
Cada script tiene un CLI con subcomandos estándar: fetch, report, headlines.
Esto permite llamarlos tanto desde el agente (via exec) como desde cron directamente,
sin cambiar el código.
Los crons como agentes sin conversación
Una pieza que a veces se pasa por alto: los crons son agentes también, pero sin interfaz conversacional. Son pipelines que corren automáticamente en horarios fijos:
7:00 AM → noticias-fetch-all.sh (fetcha las 4 fuentes)
8:00 AM → noticias-send-all.sh (envía todo + fetch articles + sync PG)
5:00 PM → noticias-fetch-all.sh (segundo ciclo)
6:00 PM → noticias-send-all.sh
La diferencia con un skill interactivo: - No hay usuario que dispare la acción — el reloj es el trigger - No hay LLM decidiendo qué hacer — el script sabe exactamente qué ejecutar - El "output" no es una respuesta en chat — son mensajes enviados proactivamente a grupos de WhatsApp
Esto es el patrón push vs. el patrón pull de los skills interactivos.
Resumen del ecosistema completo
flowchart TD
subgraph RE["MODO REACTIVO — pull · responde cuando el usuario pregunta"]
U["Usuario"] --> GW["Gateway · Router"]
GW --> SK["Skill · Tool(s)"]
SK --> RS["Respuesta en chat"]
end
subgraph PR["MODO PROACTIVO — push · envía sin que nadie lo pida"]
CR["Cron"] --> SC["Script · Ollama opcional"]
SC --> WA["WhatsApp group"]
end
subgraph DA["CAPA DE DATOS — estado compartido"]
SQ[("SQLite\nfuente de verdad local")]
PG[("Postgres Docker\nanalítica · BI")]
SQ -->|"sync incremental post-send"| PG
end
RE --> DA
PR --> DA
La riqueza del sistema no está en ningún componente individual sino en la combinación: skills especializados que saben exactamente qué hacer en su dominio, tools que encapsulan la lógica de datos, y un agente central que sabe a quién preguntar.
← OpenClaw: el framework | Inicio de la serie | Agentes de noticias →