Tag: Agentes IA

  • Cómo construir un agente de IA y su MCP server paso a paso

    Cómo construir un agente de IA y su MCP server paso a paso

    Hace tres semanas un dev me escribió por Telegram con un MCP server funcionando. Lo había construido siguiendo un tutorial. Arrancaba, registraba sus tools, Claude Code lo detectaba. Todo perfecto.

    Su pregunta era: "¿y ahora cómo hago que mi agente lo use?".

    No supo responderse porque el tutorial terminaba justo ahí. Y ese es el problema con casi todo el material que hay sobre MCP: te enseñan a construir el enchufe, pero nunca el aparato que se enchufa. O al revés — te enseñan a montar un agente con tools locales y jamás mencionan por qué querrías sacarlas a un servidor.

    Son dos mitades de la misma pieza. Y separadas no sirven de mucho.

    Este post construye las dos. Un MCP server real en TypeScript, un agente que lo consume, y el puente entre ambos. Código verificado contra el SDK, no de memoria. Al final sabrás también cuándo no deberías montar un MCP server, que es una decisión que mucha gente se salta.


    Las dos mitades: quién expone y quién consume

    Un MCP server expone capacidades: tools, resources y prompts. No tiene inteligencia. No decide nada. Es un catálogo de funciones con un contrato estándar delante. Si no tienes claro el concepto de fondo, este post explica qué es Model Context Protocol antes de meterte en código.

    Un agente es lo contrario: tiene el modelo, tiene el bucle, y decide qué llamar y cuándo. Lo que no tiene es acceso a tu mundo — a tu base de datos, a tu API interna, a tus postmortems.

    MCP es el estándar que une las dos cosas sin que se conozcan entre sí. Escribes el server una vez, y lo consumen Claude Code, Claude Desktop, tu agente propio y el agente que escriba tu compañero el mes que viene.

    Esa reutilización es todo el valor de MCP. Recuérdalo, porque en la última sección lo usaremos para decidir si te hace falta.

    Vamos a construir un server sobre un caso que a cualquiera con sistemas en producción le suena: un histórico de incidencias. Datos internos, API que nadie más va a integrar, y consultas que un modelo puede hacer mucho mejor que un dashboard.


    Paso 1: el MCP server en TypeScript

    Construir un MCP server en TypeScript requiere tres piezas: el paquete @modelcontextprotocol/sdk con zod como peer dependency, una instancia de McpServer, y un transporte stdio. Este paso monta las tres sobre un caso real.

    Primero, versiones. Y aquí hay que ser preciso porque el ecosistema está en transición.

    La versión de producción hoy es la v1, en el paquete @modelcontextprotocol/sdk (última: 1.29.0). Es sobre la que vas a construir. Hay una v2 en beta que lo cambia bastante, y le dedico una sección entera más abajo — pero no construyas sobre ella todavía.

    mkdir mcp-incidencias && cd mcp-incidencias
    npm init -y
    npm install @modelcontextprotocol/sdk zod
    npm install -D typescript @types/node tsx
    

    zod es peer dependency obligatoria del SDK v1, no es opcional.

    En tu package.json añade "type": "module", y en el tsconfig.json usa "module": "NodeNext" y "target": "ES2022". Sin eso los imports con extensión .js te van a dar guerra.

    Ahora el servidor. Archivo src/server.ts:

    import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
    import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
    import { z } from 'zod';
    
    type Severidad = 'baja' | 'media' | 'alta';
    
    interface Incidencia {
      id: string;
      servicio: string;
      fecha: string;
      severidad: Severidad;
      titulo: string;
      causaRaiz: string;
    }
    
    // En producción esto sale de tu base de datos.
    const INCIDENCIAS: Incidencia[] = [
      {
        id: 'INC-101',
        servicio: 'checkout-api',
        fecha: '2026-05-14',
        severidad: 'alta',
        titulo: 'Timeouts masivos en pasarela de pago',
        causaRaiz: 'Pool de conexiones agotado tras un deploy sin migrar el límite.'
      },
      {
        id: 'INC-118',
        servicio: 'checkout-api',
        fecha: '2026-06-02',
        severidad: 'media',
        titulo: 'Latencia elevada en cálculo de impuestos',
        causaRaiz: 'Consulta N+1 introducida al añadir el desglose por región.'
      },
      {
        id: 'INC-124',
        servicio: 'auth-service',
        fecha: '2026-06-21',
        severidad: 'alta',
        titulo: 'Sesiones invalidadas de forma masiva',
        causaRaiz: 'Rotación de claves JWT desplegada sin periodo de solapamiento.'
      }
    ];
    
    const server = new McpServer({ name: 'incidencias', version: '1.0.0' });
    

    Fíjate en los imports: llevan la extensión .js y la ruta interna del paquete (/server/mcp.js). No es @modelcontextprotocol/sdk a secas. Es el error más habitual al empezar.

    Ahora registramos la primera tool:

    const ORDEN: Record<Severidad, number> = { baja: 0, media: 1, alta: 2 };
    
    server.registerTool(
      'buscar_incidencias',
      {
        title: 'Buscar incidencias',
        description:
          'Busca incidencias de producción de un servicio, filtrando por severidad mínima. ' +
          'Úsala cuando necesites el histórico de fallos de un servicio concreto.',
        inputSchema: {
          servicio: z.string().describe('Nombre del servicio, por ejemplo: checkout-api'),
          severidadMinima: z.enum(['baja', 'media', 'alta']).default('baja')
        },
        outputSchema: {
          total: z.number(),
          incidencias: z.array(
            z.object({
              id: z.string(),
              fecha: z.string(),
              severidad: z.string(),
              titulo: z.string()
            })
          )
        }
      },
      async ({ servicio, severidadMinima }) => {
        const encontradas = INCIDENCIAS.filter(
          (i) => i.servicio === servicio && ORDEN[i.severidad] >= ORDEN[severidadMinima]
        ).map(({ id, fecha, severidad, titulo }) => ({ id, fecha, severidad, titulo }));
    
        const output = { total: encontradas.length, incidencias: encontradas };
    
        return {
          content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
          structuredContent: output
        };
      }
    );
    

    Un detalle que ahorra tardes: inputSchema acepta tanto la forma en crudo ({ servicio: z.string() }) como un z.object() completo. El SDK normaliza las dos por dentro y el JSON Schema que acaba llegando al modelo es idéntico. Uso la forma cruda porque es menos ruido, pero si vienes de otra librería y te sale envolver, no rompes nada.

    Guárdalo, porque dentro de un momento vamos a ver otra librería donde esa flexibilidad no existe.

    Lo segundo: la description no es documentación, es prompt. Es literalmente lo único que el modelo lee para decidir si usa esta tool. Una descripción vaga es una tool que nunca se llama, o que se llama cuando no toca. Escríbela pensando en el modelo, incluyendo cuándo usarla.

    Segunda tool, con manejo de errores:

    server.registerTool(
      'detalle_incidencia',
      {
        title: 'Detalle de incidencia',
        description: 'Devuelve la causa raíz completa de una incidencia por su ID (formato INC-XXX).',
        inputSchema: {
          id: z.string().describe('Identificador, por ejemplo: INC-101')
        }
      },
      async ({ id }) => {
        const incidencia = INCIDENCIAS.find((i) => i.id === id);
    
        if (!incidencia) {
          return {
            content: [{ type: 'text', text: `No existe ninguna incidencia con ID ${id}.` }],
            isError: true
          };
        }
    
        return {
          content: [
            {
              type: 'text',
              text: `${incidencia.id} — ${incidencia.titulo}\nServicio: ${incidencia.servicio}\nFecha: ${incidencia.fecha}\nSeveridad: ${incidencia.severidad}\nCausa raíz: ${incidencia.causaRaiz}`
            }
          ]
        };
      }
    );
    

    isError: true en lugar de lanzar una excepción. La diferencia importa: con isError el modelo recibe el mensaje y puede corregirse solo — reintentar con otro ID, o decirle al usuario que no existe. Si lanzas, revientas la conexión y el agente se queda ciego.

    Y el arranque:

    const transport = new StdioServerTransport();
    await server.connect(transport);
    
    console.error('MCP server de incidencias escuchando en stdio');
    

    console.error, nunca console.log. En transporte stdio, stdout es el canal JSON-RPC. Un solo console.log mete texto suelto en la tubería y rompe el protocolo con un error de parseo que no dice nada útil. Todo tu logging va a stderr.

    Ya tienes la mitad de la pieza. Si quieres comprobar que funciona antes de seguir, no hace falta registrarlo en ningún cliente: npx @modelcontextprotocol/inspector npx tsx src/server.ts levanta MCP Inspector, la herramienta oficial, y te deja ver las tools registradas e invocarlas a mano desde el navegador.

    Si además quieres usarlo desde Claude Code, tengo aparte las notas sobre registrar un MCP server en Claude Code — es el complemento natural de esta sección, no un camino alternativo.


    Paso 2: el agente que consume las tools

    El agente se construye con el Tool Runner del SDK de Anthropic (client.beta.messages.toolRunner), que ejecuta por ti el bucle completo: llama al modelo, ejecuta la tool que pida, le devuelve el resultado, y repite hasta obtener una respuesta final.

    Aquí hay una confusión que veo constantemente y conviene despejarla antes de escribir una línea, porque son dos productos distintos de Anthropic:

    • Tool Runner (client.beta.messages.toolRunner, dentro del SDK normal @anthropic-ai/sdk): automatiza el bucle sobre las tools que defines. Sin tools integradas, sin sandbox. Tú pones todo.
    • Claude Agent SDK (@anthropic-ai/claude-agent-sdk): es Claude Code empaquetado como librería, con tools integradas de serie — leer y escribir ficheros, bash, grep.

    No son versiones distintas de lo mismo. Para este caso queremos el Tool Runner, porque lo que nos interesa es controlar exactamente qué tools existen.

    npm install @anthropic-ai/sdk
    

    Un agente mínimo con una tool local:

    import Anthropic from '@anthropic-ai/sdk';
    import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
    import { z } from 'zod';
    
    const client = new Anthropic(); // lee ANTHROPIC_API_KEY del entorno
    
    const buscarIncidencias = betaZodTool({
      name: 'buscar_incidencias',
      description: 'Busca incidencias de producción de un servicio por severidad mínima.',
      inputSchema: z.object({
        servicio: z.string().describe('Nombre del servicio, por ejemplo: checkout-api'),
        severidadMinima: z.enum(['baja', 'media', 'alta']).default('baja')
      }),
      run: async (input) => {
        // aquí llamarías a tu API real
        return JSON.stringify({ servicio: input.servicio, total: 0, incidencias: [] });
      }
    });
    
    const respuesta = await client.beta.messages.toolRunner({
      model: 'claude-opus-4-8',
      max_tokens: 16000,
      thinking: { type: 'adaptive' },
      messages: [
        {
          role: 'user',
          content: '¿Qué incidencias graves ha tenido checkout-api? Resume el patrón que veas.'
        }
      ],
      tools: [buscarIncidencias]
    });
    
    console.log(respuesta.content);
    

    Fíjate en la diferencia con el server: en betaZodTool el inputSchema tiene que ser un z.object() completo. Aquí no hay normalización que te salve — pasarle la forma en crudo no funciona.

    Las tres convenciones de schema que se confunden entre sí

    El mismo concepto cambia de formato según la librería. Es la causa más frecuente de tools que se registran pero nunca se llaman bien:

    Librería y función Propiedad Formato esperado
    MCP SDK v1 — registerTool inputSchema Forma cruda o z.object(); el SDK normaliza las dos
    Anthropic SDK — betaZodTool inputSchema z.object() completo, obligatorio
    Anthropic SDK — betaTool inputSchema JSON Schema plano (el que devuelve listTools())

    Las tres reciben inputSchema en camelCase. El input_schema en snake_case que quizá tengas visto es lo que viaja por la red hacia la API, no lo que le pasas al helper. Escribir snake_case en cualquiera de los tres revienta con un TypeError.

    Tres cosas más sobre los parámetros, que están cambiadas respecto a lo que quizá tengas memorizado:

    • El modelo es claude-opus-4-8. Sin sufijo de fecha.
    • thinking va con { type: 'adaptive' }. budget_tokens está eliminado en Opus 4.8 y devuelve un 400.
    • temperature, top_p y top_k rechazan cualquier valor que no sea el por defecto y devuelven 400. Si arrastras un temperature: 0 de un proyecto viejo, esa llamada falla. Se dirige el comportamiento por prompt, no por sampling.

    max_tokens alrededor de 16000 para peticiones normales, hasta ~64000 si haces streaming.

    El Tool Runner ejecuta el bucle completo por ti: llama al modelo, si pide una tool la ejecuta, le devuelve el resultado, y repite hasta que el modelo da una respuesta final. Ese bucle es el corazón de cualquier agente — y si quieres entender por qué la calidad del bucle importa más que el modelo que metas dentro, lo desarrollo aquí. Para los fundamentos de la API, este crash course te cubre.


    Paso 3: conectar las dos mitades

    Conectar el agente con el MCP server consiste en levantar un cliente MCP, pedirle sus tools con listTools() y traducirlas al formato del Tool Runner con betaTool. Así el agente ejecuta las tools reales del server en vez de copias locales.

    Ahora lo que casi nadie enseña. El agente del paso anterior tiene la tool duplicada en local. Queremos que consuma las tools reales del MCP server, sin reescribirlas.

    Para eso montamos un cliente MCP, le preguntamos qué tools tiene, y las traducimos al formato del Tool Runner:

    import Anthropic from '@anthropic-ai/sdk';
    import { betaTool } from '@anthropic-ai/sdk/helpers/beta/json-schema';
    import { Client } from '@modelcontextprotocol/sdk/client/index.js';
    import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
    
    const transport = new StdioClientTransport({
      command: 'npx',
      args: ['tsx', 'src/server.ts']
    });
    
    const mcp = new Client({ name: 'agente-incidencias', version: '1.0.0' });
    await mcp.connect(transport);
    
    // 1. Descubrimos las tools que expone el server
    const { tools } = await mcp.listTools();
    
    // 2. Las convertimos en tools ejecutables para el Tool Runner
    const puente = tools.map((tool) =>
      betaTool({
        name: tool.name,
        description: tool.description ?? '',
        inputSchema: tool.inputSchema as any,
        run: async (input) => {
          const resultado = await mcp.callTool({
            name: tool.name,
            arguments: input as Record<string, unknown>
          });
          return JSON.stringify(resultado.content);
        }
      })
    );
    
    // 3. El agente ya usa las tools reales del server
    const respuesta = await new Anthropic().beta.messages.toolRunner({
      model: 'claude-opus-4-8',
      max_tokens: 16000,
      thinking: { type: 'adaptive' },
      messages: [
        {
          role: 'user',
          content:
            'Revisa las incidencias graves de checkout-api, mira el detalle de cada una ' +
            'y dime si hay un patrón común en las causas raíz.'
        }
      ],
      tools: puente
    });
    
    console.log(respuesta.content);
    await mcp.close();
    

    Eso es el circuito completo. Aquí usamos betaTool en lugar de betaZodTool porque listTools() devuelve JSON Schema, no Zod. Encaja directo: le pasas el inputSchema tal cual llega del server.

    Y ojo con el detalle que más despista de todo el post: los helpers reciben inputSchema en camelCase, pero lo que viaja a la API es input_schema en snake_case. Si escribes tools a mano contra la API cruda usas snake_case; con los helpers, siempre camelCase. Escribir input_schema: dentro de betaTool no da un error de validación bonito — revienta con un TypeError antes de tocar la red.

    Cuando entiendas el mecanismo, el SDK ya trae ese puente hecho:

    import { mcpTools } from '@anthropic-ai/sdk/helpers/beta/mcp';
    
    const puente = mcpTools(tools, mcp);
    

    Merece la pena haber escrito el map a mano una vez: cuando el helper falle, sabrás qué está haciendo por dentro.

    Lo potente es que ese map no sabe nada de tus tools. Añade una tercera tool al server y el agente la tiene disponible en el siguiente arranque, sin tocar el código del agente. Ahí es donde MCP paga lo que cuesta.

    Al ejecutarlo verás al agente encadenar solo: llama a buscar_incidencias, recibe dos IDs, llama a detalle_incidencia con cada uno, y razona sobre las causas raíz. Nadie le dijo el orden.

    La otra vía: el conector MCP remoto

    Si en vez de stdio despliegas el server sobre HTTP, la API de Claude puede conectarse a él directamente, sin cliente MCP en tu código:

    const message = await client.beta.messages.create({
      model: 'claude-opus-4-8',
      max_tokens: 16000,
      betas: ['mcp-client-2025-11-20'],
      mcp_servers: [
        {
          type: 'url',
          url: 'https://incidencias.tudominio.com/mcp',
          name: 'incidencias'
        }
      ],
      tools: [{ type: 'mcp_toolset', mcp_server_name: 'incidencias' }],
      messages: [{ role: 'user', content: '¿Qué incidencias graves tuvo checkout-api?' }]
    });
    

    El conector MCP remoto exige declarar mcp_servers y tools a la vez. Declarar solo mcp_servers hace que la petición se rechace con un error de validación, aunque parezca redundante — ya has dicho dónde está el server, ¿para qué repetirlo? Cada server declarado en mcp_servers necesita su entrada { type: 'mcp_toolset', mcp_server_name: '<nombre>' } dentro de tools, y el mcp_server_name debe coincidir exactamente con el name del server.

    Ojo también: esta vía requiere un server con URL pública. Un server stdio no sirve aquí, para eso está el puente de arriba. La documentación del conector MCP de la API de Anthropic detalla el resto de campos disponibles.


    MCP v2 y la spec 2026-07-28: qué cambia y por qué no tienes que migrar

    El 28 de julio de 2026 salen la spec MCP 2026-07-28 y las SDK estables de la v2. Vas a ver posts en tono de urgencia. Ignóralos.

    La documentación oficial es explícita en dos puntos. Sobre las versiones, la v1.x sigue siendo "the supported release for production" y mantiene bugfixes y parches de seguridad al menos 6 meses después de que v2 sea estable. Y sobre el protocolo, la guía de la revisión lo cierra: "Nothing in v2 puts a 2026-07-28 byte on the wire by default" — hablar la revisión nueva es siempre un opt-in explícito. Migrar a v2 es opcional y va separado de la fecha del protocolo.

    Puedes seguir las dos fuentes de primera mano: la especificación del protocolo y el SDK de TypeScript en GitHub.

    El servidor que acabas de construir sigue funcionando. No hay nada que correr a arreglar.

    Dicho eso, la v2 no es un cambio cosmético y merece que sepas qué trae, porque cambia decisiones de arquitectura:

    Se parte el paquete. El monolítico @modelcontextprotocol/sdk desaparece en favor de @modelcontextprotocol/server, @modelcontextprotocol/client y @modelcontextprotocol/core. La v2 no sale como versión nueva del paquete viejo: son paquetes distintos. Por eso no hay riesgo de que te llegue sola en un npm update.

    Protocolo stateless. Cuando activas la revisión nueva, desaparecen el handshake initialize y la gestión de sesión. Traducido a infraestructura: escalas con un round-robin normal, sin sticky sessions. Si has sufrido balanceo con sesiones MCP, esta es la razón para migrar. Ojo: en la v2 el modo de 2025 sigue siendo el por defecto; la revisión 2026-07-28 se activa explícitamente.

    Multi Round-Trip Requests. Una tool puede pedir input al usuario a mitad de llamada, sin mantener un stream abierto — con inputRequired() y acceptedContent(). Confirmaciones y flujos de autorización dejan de ser un apaño.

    Cabeceras enrutables Mcp-Method y Mcp-Name, para que gateways y rate limiters enruten sin parsear el body. Si expones MCP detrás de un API gateway, esto te ahorra trabajo.

    Bring-your-own-schema. inputSchema y outputSchema aceptan cualquier Standard Schema: Zod v4 y ArkType directos, Valibot vía adaptador, o JSON Schema plano con fromJsonSchema. Se acabó estar atado a Zod. El registro pasa a server.registerTool(name, config, handler).

    Si vas a experimentar con la beta, el consejo oficial es fijar versiones exactas y poner cotas superiores en las dependencias, para no comerte un major por sorpresa.

    Mi recomendación: construye en v1, lee la guía de v2, y migra cuando tengas un motivo concreto — escalado horizontal o flujos que necesiten input a media llamada. No antes.


    Cuándo NO necesitas un MCP server

    Esta sección te puede ahorrar una semana.

    Si tu agente va a usar solo tus propias tools, dentro de tu propio proceso, no montes un MCP server. El Tool Runner con tools locales (betaZodTool y punto) es más simple, más rápido de depurar y no añade un proceso extra ni serialización por medio. Todo el paso 1 de este post sobra en ese escenario.

    MCP gana cuando aparece la palabra reutilización:

    • Quieres las mismas tools en Claude Code, en Claude Desktop y en tu agente.
    • Varios equipos van a consumir la misma capacidad y no quieres que cada uno la reimplemente.
    • Quieres una frontera de permisos clara: el server decide qué se puede hacer, el agente solo pide.
    • Necesitas versionar y desplegar las capacidades por separado del agente.

    Si no marcas ninguna, tu MCP server es una capa de indirección que no compra nada.

    Y una consecuencia que se ve poco: en cuanto varios clientes consumen tus tools, las descripciones dejan de ser tuyas y pasan a ser una API pública. Cambiar una description puede romper el comportamiento del agente de otro equipo sin que nada falle en rojo. Trátalas con el mismo cuidado que un contrato.


    Qué hacer con esto hoy

    Coge el código del paso 1, cámbiale el array INCIDENCIAS por una consulta real a tu base de datos, y ejecuta el puente del paso 3. En una tarde tienes un agente hablando con tus datos internos.

    Y cuando lo tengas funcionando, la parte difícil no será el código. Será decidir qué tools expones y cómo las describes — porque ahí es donde un agente pasa de demo a herramienta que usas todos los días.

    Ese salto, el de convertir una prueba de concepto en producto, es justo lo que trabajamos en el curso Construye con IA: De la Idea al Producto con Claude Code, con este mismo flujo de specs, tools y agentes. Si prefieres el método antes que la herramienta, en el libro Spec-Driven Development está el sistema completo para definir qué construyes antes de escribir la primera línea.

    Y si quieres los proyectos completos y las versiones de esto que corren en producción, están en Dominicode Labs.


    FAQ

    ¿Puedo usar el mismo MCP server con Claude Code y con mi agente propio a la vez?

    Sí, y es exactamente para lo que sirve MCP. El server no sabe quién le llama. Claude Code lo lanza como proceso hijo por stdio, y tu agente hace lo mismo con StdioClientTransport. Mismo binario, dos consumidores, cero código duplicado.

    ¿Tengo que migrar mi server a la v2 el 28 de julio?

    No. La v2 llega en paquetes nuevos (@modelcontextprotocol/server, /client y /core), no como actualización del paquete actual, así que no te va a llegar por un npm update. La v1.x sigue siendo la versión soportada para producción y mantiene bugfixes y parches de seguridad al menos 6 meses tras la salida de v2. Además, hablar la revisión 2026-07-28 es siempre un opt-in explícito: nada la pone en el cable por defecto.

    ¿Cuál es la diferencia real entre el Tool Runner y el Claude Agent SDK?

    El Tool Runner automatiza el bucle sobre tools que defines tú, y nada más: sin tools integradas, sin sandbox. El Claude Agent SDK es Claude Code como librería, y viene con tools de ficheros, bash y grep de serie. Si quieres control total sobre qué puede hacer el agente, Tool Runner. Si quieres un agente que opere sobre un repositorio desde el minuto uno, Agent SDK.

    Mi server arranca pero el cliente da error de parseo JSON. ¿Qué pasa?

    Casi seguro tienes un console.log en algún sitio. En stdio, stdout es el canal JSON-RPC exclusivo del protocolo. Cualquier texto que escribas ahí corrompe el flujo. Cambia todos los console.log por console.error y vuelve a probar.

    ¿Por qué mi tool aparece registrada pero el modelo nunca la llama?

    Dos causas, por frecuencia. La primera es la description: si es vaga, el modelo no sabe cuándo aplica. Escríbela diciendo explícitamente en qué situación usarla. La segunda es que el schema no describa bien los campos — añade .describe() a cada uno, porque el modelo los lee para saber con qué rellenarlos.

    ¿Cómo pruebo mi MCP server sin registrarlo en un cliente?

    Con MCP Inspector, la herramienta oficial: npx @modelcontextprotocol/inspector npx tsx src/server.ts. Abre una interfaz web donde ves las tools registradas, su schema, y puedes invocarlas con argumentos a mano. Es la forma más rápida de saber si el fallo está en el server o en cómo lo consume el cliente.

    ¿Puedo usar temperature para que el agente sea más determinista?

    No con Opus 4.8. temperature, top_p y top_k rechazan cualquier valor que no sea el por defecto y devuelven un 400. Tampoco existe ya budget_tokens para thinking — se usa thinking: { type: 'adaptive' }. Si migras código de modelos anteriores, revisa esos parámetros primero. El comportamiento se dirige por prompt.

    ¿El conector MCP de la API sirve para un server local por stdio?

    No. mcp_servers con type: 'url' necesita un endpoint HTTP accesible desde la API de Anthropic. Para un server local usas el puente del paso 3: cliente MCP por stdio y las tools traducidas al Tool Runner.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

    Más contenido sobre agentes e IA aplicada al desarrollo en el canal de YouTube de Dominicode. Y si estás empezando con agentes, esta guía es el punto de partida.

  • Cómo meter Hermes Agent en tu flujo de trabajo diario

    Cómo meter Hermes Agent en tu flujo de trabajo diario

    Llevo meses metiendo Hermes Agent en mi flujo de trabajo diario, y el momento en que decidí hacerlo en serio no fue leyendo la documentación. Fue una noche en la que tenía Claude Code abierto en una terminal, revisando un PR que no avanzaba. Slack abierto en otra pestaña, esperando una respuesta que tardaba. Y un cron corriendo a las 3am que revisaba PRs pendientes en tres repos con un script de bash que yo mismo mantenía a mano.

    Me detuve a mirar ese script y vi algo incómodo: acababa de reinventar, con cron y bash, exactamente lo que Hermes Agent hace nativo. Desde ese día dejó de ser un experimento de fin de semana — pasó a ser la pieza que corre en segundo plano mientras yo hago otra cosa.

    Para quien no lo tenga fresco: Hermes Agent es el framework open source de agentes autónomos de Nous Research — sandbox Docker, memoria persistente y soporte multicanal (CLI, Telegram, Discord, Slack, WhatsApp, Signal). Dicho eso, este post no es una intro de "qué es Hermes Agent". Es cómo lo uso yo: cuándo lo disparo desde el móvil en vez de abrir la laptop, dónde le doy acceso real a mi código sin miedo a que rompa nada, y qué reviso antes de conectarlo a un VPS con datos reales.


    Claude Code y Hermes Agent no compiten — resuelven turnos distintos

    La primera pregunta que me hacen es la obvia: ¿esto reemplaza a Claude Code? No. Si alguien te dice que sí, no lo ha usado en serio.

    Claude Code vive en tu editor. Es una sesión interactiva: tú escribes, el agente responde, revisas el diff, iteras. Pair programming con alguien que no se cansa. La sesión termina cuando cierras la terminal.

    Hermes Agent vive en otro sitio: en background, disparado por un evento — un mensaje, un cron, un webhook — y sigue corriendo aunque cierres la laptop.

    La regla que uso: si estoy decidiendo diseño en tiempo real, Claude Code. Si la tarea es "revisa esto, hazlo, y avísame" — y puedo estar en el metro sin laptop — es trabajo para Hermes Agent.


    Instalar Hermes Agent en menos de un minuto

    En Linux, macOS, WSL2 o Termux:

    curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
    

    En Windows nativo, sin WSL, desde PowerShell:

    iex (irm https://hermes-agent.nousresearch.com/install.ps1)
    

    El instalador de Windows resuelve solo uv, Python 3.11, Node.js, ripgrep, ffmpeg y un Git Bash portable — sin pedirte permisos de administrador. Esperaba instalar media docena de dependencias a mano. No hizo falta.


    Los comandos que necesitas el primer día

    Después de instalar, el wizard completo:

    hermes setup
    

    Si prefieres ir pieza por pieza:

    • hermes — abre el chat interactivo, punto de arranque de cualquier sesión
    • hermes model — elige proveedor y modelo LLM
    • hermes tools — configura qué herramientas están habilitadas
    • hermes gateway — levanta el gateway de mensajería (Telegram, Discord, Slack…)
    • hermes doctor — diagnostica problemas de configuración antes de que te den una sorpresa
    • hermes update — mantiene el binario en la última versión

    Si no quieres juntar API keys de cada proveedor por separado, hermes setup --portal hace login OAuth contra el Nous Portal: más de 300 modelos, web search, imágenes, TTS y browser en la nube bajo una sola suscripción. Es el atajo para no tener seis .env con llaves sueltas.


    Sacarlo de la terminal: dispararlo desde el móvil

    Aquí está el cambio real de flujo de trabajo. Antes de Hermes, "revisar algo desde el móvil" era abrir una app de VNC o SSH y sufrir un teclado táctil. Con el gateway de mensajería, no:

    hermes gateway setup    # Configura Telegram, Discord, Slack, WhatsApp, Signal
    hermes gateway start
    hermes gateway status
    

    El mismo agente que usas en la CLI responde en Telegram, Discord, Slack, WhatsApp o Signal, con los mismos slash commands:

    • /new o /reset — arrancar de cero
    • /model — cambiar de modelo
    • /personality — cambiar de contexto/personalidad
    • /retry y /undo — cuando algo sale mal
    • /compress — cuando la conversación se alarga
    • /usage — ver el gasto
    • /insights --days 7 — resumen semanal
    • /stop (o Ctrl+C en la CLI) — interrumpirlo

    En la práctica: voy caminando, me acuerdo de que quiero que revise un PR, le escribo por Telegram, y sigo caminando. Eso es lo que cambió — no la inteligencia del modelo, la fricción de acceder a él.


    El sandbox: que toque código real sin que te dé miedo

    La parte que a cualquier developer con experiencia le genera desconfianza, con razón: darle a un agente acceso de ejecución en tu máquina o servidor.

    Hermes soporta seis backends — local, Docker, SSH, Singularity, Modal, Daytona. Para cualquier cosa que toque un repo real, uso Docker (aquí entré en más detalle sobre por qué en la guía completa de Docker sandboxing en Hermes Agent):

    hermes config set terminal.backend docker
    

    No es un sandbox decorativo. El hardening por defecto elimina todas las capabilities de Linux y solo re-agrega tres: DAC_OVERRIDE, CHOWN, FOWNER. Límite de 256 procesos. /tmp como tmpfs de 512MB nosuid. /var/tmp con noexec y nosuid a 256MB. Bloqueo de escalación de privilegios (no-new-privileges). Límites de CPU, memoria (5GB por defecto) y disco (50GB por defecto).

    La diferencia práctica: si el agente ejecuta un comando destructivo dentro del sandbox, se lleva el contenedor, no tu servidor. Es la diferencia entre "cometí un error" y "cometí un error y ahora restauro un backup".


    Conectar las herramientas que ya usas: MCP

    Lo que hace que Hermes valga la pena en tu día a día no es que chatee bien — es que puede tocar las herramientas que ya usas. Los servidores MCP se declaran en ~/.hermes/config.yaml:

    mcp_servers:
      github:
        command: npx
        args: ["-y", "@modelcontextprotocol/server-github"]
        env:
          GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxx"
    

    Con eso conectado, el agente revisa issues, comenta PRs o abre ramas sin que tú abras GitHub. Si ya construyes servidores MCP para Claude Code, funcionan igual aquí — el protocolo es el mismo, el cliente cambia (si quieres el detalle completo de cómo montar un servidor MCP propio, lo cubrí en Model Context Protocol: conecta tu base de datos a la IA). Es la misma lógica de interoperabilidad que trabajamos en el curso Construye con IA al conectar agentes a herramientas reales de producción.


    El checklist antes de darle acceso a algo real (VPS, producción)

    Esto diferencia un despliegue de fin de semana de uno que no te explota en la cara. Antes de conectar Hermes a un VPS, reviso la lista completa, no las tres primeras líneas:

    1. Nunca actives GATEWAY_ALLOW_ALL_USERS=true — define allowlists explícitos por plataforma
    2. Usa el backend de contenedor (terminal.backend: docker) para aislar la ejecución
    3. Configura límites de recursos en ~/.hermes/config.yaml
    4. Guarda secretos en ~/.hermes/.env con permisos restringidos — nunca en config.yaml
    5. Usa códigos de DM pairing en vez de IDs de usuario hardcodeados
    6. Audita el command_allowlist con regularidad, no solo la primera vez
    7. Define terminal.cwd para limitar el directorio de trabajo del agente
    8. Corre el gateway como usuario no-root
    9. Monitorea ~/.hermes/logs/ — que no falle no significa que hizo lo correcto
    10. Mantente actualizado con hermes update

    Si quieres esta lista y la chuleta completa de comandos en una sola hoja para imprimir, la armé gratis aquí: dominicode.com/hermes-agent. Y si tu siguiente paso es un VPS propio, el paso a paso completo está en cómo desplegar Hermes Agent en tu propio VPS con Docker.


    El modo YOLO no es tan yolo como suena

    Hay un modo --yolo (también /yolo, o HERMES_YOLO_MODE=1) que salta las confirmaciones de comandos. Lo uso cuando confío en la tarea y no quiero aprobar cada paso — casi siempre dentro del sandbox de Docker, nunca contra mi máquina local sin aislar.

    Incluso en YOLO hay un blocklist permanente que no se salta nunca: rm -rf /, fork bombs, escritura directa a dispositivos. No es marketing, es una capa que existe pase lo que pase.

    De fábrica también trae:

    • Protección SSRF — bloquea IPs privadas, loopback, link-local, CGNAT y metadata de nube antes de cualquier fetch
    • Filtrado de credenciales en subprocesos MCP — solo pasa variables seguras como PATH, HOME, USER, LANG
    • Escaneo de context files contra prompt injection
    • Advisories de supply-chainhermes doctor te avisa directo si algo tiene una vulnerabilidad conocida

    Qué hacer hoy

    No necesitas resolver todo esto en una tarde. Esto es lo que haría en tu lugar.

    Instala Hermes hoy y corre hermes setup. No conectes nada todavía — úsalo desde la CLI un par de días, como probarías cualquier herramienta nueva.

    Cuando le confíes algo real, cambia el backend a Docker antes de darle acceso a un repo que te importe. Es un comando, no una migración.

    Y antes de conectarlo a un VPS o a mensajería pública, pasa por el checklist completo de arriba. Es la diferencia entre automatizar tu flujo de trabajo y crear un incidente de seguridad con tu nombre encima.

    Si estás diseñando cómo encajan Claude Code, Hermes y el resto de tu stack de IA — no solo conectando un agente suelto — es el tipo de conversación que tenemos cada semana en Dominicode Labs con developers que ya tienen esto en producción. (Ya estamos preparando, además, un curso completo dedicado solo a esto — sin fecha todavía, pero viene.)


    FAQ — Preguntas frecuentes sobre Hermes Agent

    ¿Hermes Agent es lo mismo que Claude Code?

    No. Claude Code es una sesión interactiva en tu editor para pair programming en tiempo real: tú decides, el agente ejecuta, revisas el diff al instante. Hermes Agent corre en background, disparado por mensajería o eventos, y sigue trabajando aunque cierres la laptop. Son complementarios, no competidores.

    ¿Necesito un servidor o VPS para usarlo?

    No para empezar. hermes corre local desde tu CLI en Linux, macOS, WSL2, Termux o Windows nativo. Un VPS se vuelve necesario cuando quieres el gateway de mensajería disponible 24/7 sin depender de que tu laptop esté encendida — ahí entra el checklist de seguridad de este post.

    ¿Es gratis?

    El framework es open source. Lo que cuesta es el consumo de tokens del proveedor que elijas con hermes model, o la suscripción del Nous Portal si usas hermes setup --portal para acceder a los 300+ modelos sin gestionar API keys sueltas.

    ¿Qué tan seguro es darle acceso a mi terminal?

    Depende del backend. Correr hermes directo contra tu máquina local sin sandbox es la opción de mayor riesgo. Cambiar a terminal.backend: docker te da capabilities reducidas, límites de proceso, memoria y disco, y contención real. Sumado al checklist de este post, es un nivel razonable para producción.

    ¿Puedo usarlo con modelos locales?

    Sí, vía Ollama, con su endpoint compatible con la API de OpenAI en localhost:11434/v1 — cualquier modelo con tool calling funciona. La restricción real es de contexto: el agente necesita al menos 64.000 tokens disponibles para el system prompt, los esquemas de herramientas y la conversación, así que un modelo local con ventana pequeña queda descartado desde el arranque. Prueba primero con un modelo mediano (14B-32B) que soporte tool calling y esa ventana de contexto antes de comprometerte a un flujo 100% local.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Servidor de herramientas para tu agente de IA (sin MCP)

    Servidor de herramientas para tu agente de IA (sin MCP)

    Un cliente me escribió en enero. Llevaba tres semanas intentando montar un servidor de herramientas para que un agente consultara el stock de su ecommerce.

    Tenía la API montada desde 2021. Endpoints limpios, autenticación, tests. Todo funcionando en producción con miles de peticiones al día. Pero estaba convencido de que para "conectarle IA" necesitaba reescribirlo todo como servidor de herramientas para agentes.

    No necesitaba reescribir nada. Necesitaba un archivo de 40 líneas.

    Ese es el malentendido más caro que veo ahora mismo entre developers senior: creer que las herramientas de un agente son una infraestructura nueva. No lo son. Tu API de negocio ya es el servidor de herramientas. Lo que falta es un adaptador delgado que traduzca entre el modelo y tus endpoints.

    Y sí, existe MCP: un estándar para exponer herramientas de forma interoperable. Aquí vamos por debajo, a la mecánica cruda, para que veas exactamente qué pasa entre el modelo y tu servidor. Si después quieres estandarizar y exponer estas mismas herramientas para cualquier cliente, eso ya lo cubrí aquí.

    Paso 1: el servidor de herramientas que no sabe nada de IA

    Un servidor de herramientas para agentes de IA es una API HTTP normal cuyos endpoints se exponen al modelo mediante un adaptador que declara, para cada operación, su schema de entrada y cuándo debe invocarse. No es infraestructura nueva: es tu API de negocio más una capa de traducción.

    Esta es la parte que la gente complica sin motivo. El servidor es una API HTTP normal. Sin SDK de IA. Sin dependencias raras. Sin una sola línea que mencione un modelo.

    Un catálogo de productos con Hono:

    npm install hono @hono/node-server
    
    // server/index.ts
    import { Hono } from "hono";
    import { serve } from "@hono/node-server";
    
    type Producto = {
      sku: string;
      nombre: string;
      categoria: "perifericos" | "monitores" | "audio";
      precio: number;
      stock: number;
    };
    
    const catalogo: Producto[] = [
      { sku: "TEC-65", nombre: "Teclado mecánico 65%", categoria: "perifericos", precio: 89.9, stock: 12 },
      { sku: "MON-27", nombre: "Monitor 27\" 144Hz", categoria: "monitores", precio: 279.0, stock: 3 },
      { sku: "AUD-XM", nombre: "Auriculares ANC", categoria: "audio", precio: 199.0, stock: 0 },
    ];
    
    const app = new Hono();
    
    app.get("/productos", (c) => {
      const categoria = c.req.query("categoria");
      const items = categoria
        ? catalogo.filter((p) => p.categoria === categoria)
        : catalogo;
      return c.json({ items });
    });
    
    app.get("/stock/:sku", (c) => {
      const producto = catalogo.find((p) => p.sku === c.req.param("sku"));
      if (!producto) return c.json({ error: "SKU no encontrado" }, 404);
      return c.json({ sku: producto.sku, stock: producto.stock, precio: producto.precio });
    });
    
    app.post("/pedido", async (c) => {
      const { sku, unidades } = await c.req.json<{ sku: string; unidades: number }>();
      const producto = catalogo.find((p) => p.sku === sku);
      if (!producto) return c.json({ error: "SKU no encontrado" }, 404);
      if (producto.stock < unidades) return c.json({ error: "Stock insuficiente" }, 409);
    
      producto.stock -= unidades;
      return c.json({ pedidoId: crypto.randomUUID(), sku, unidades, total: producto.precio * unidades });
    });
    
    serve({ fetch: app.fetch, port: 3000 });
    

    Léelo otra vez y busca la palabra "IA". No está.

    Esto importa más de lo que parece. Cuando mezclas la lógica de negocio con la capa del modelo, acabas con endpoints que solo sirven para el agente, imposibles de testear en aislamiento y que se rompen cada vez que cambias de proveedor.

    Manteniendo la separación, tu API sigue sirviendo a tu web, a tu app móvil y al agente. Tres consumidores, una fuente de verdad.

    Paso 2: el adaptador que convierte tu API en servidor de herramientas

    Ahora sí, la capa que traduce. Instalas el SDK:

    npm install @anthropic-ai/sdk zod
    

    Y defines las herramientas con betaZodTool, que te deja declarar el schema de entrada con Zod y la función que se ejecuta cuando el modelo pide esa herramienta:

    // agent/tools.ts
    import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
    import { z } from "zod";
    
    const API = "http://localhost:3000";
    
    export const buscarProductos = betaZodTool({
      name: "buscar_productos",
      description:
        "Devuelve el catálogo de productos, opcionalmente filtrado por categoría. " +
        "Llama a esto cuando el usuario pregunte qué productos hay disponibles, " +
        "pida recomendaciones o mencione una categoría concreta.",
      inputSchema: z.object({
        categoria: z
          .enum(["perifericos", "monitores", "audio"])
          .optional()
          .describe("Categoría por la que filtrar. Omítela para ver el catálogo completo."),
      }),
      run: async ({ categoria }) => {
        const url = categoria ? `${API}/productos?categoria=${categoria}` : `${API}/productos`;
        const res = await fetch(url);
        return JSON.stringify(await res.json());
      },
    });
    
    export const consultarStock = betaZodTool({
      name: "consultar_stock",
      description:
        "Devuelve stock y precio actuales de un SKU. " +
        "Llama a esto SIEMPRE antes de confirmar disponibilidad o precio a un usuario. " +
        "Nunca respondas de memoria sobre stock o precios.",
      inputSchema: z.object({
        sku: z.string().describe("Identificador del producto, por ejemplo TEC-65"),
      }),
      run: async ({ sku }) => {
        const res = await fetch(`${API}/stock/${sku}`);
        if (!res.ok) return `No existe ningún producto con SKU ${sku}`;
        return JSON.stringify(await res.json());
      },
    });
    

    Fíjate en las descripciones. No dicen solo qué hace la herramienta: dicen cuándo llamarla.

    Esto no es cosmética. Los modelos Opus recientes son conservadores pidiendo herramientas — si dudan, prefieren responder ellos. Una descripción prescriptiva del tipo "llama a esto siempre antes de confirmar precios" convierte una llamada probable en una llamada determinista. Una descripción como "consulta el stock" la deja al azar.

    Y el enum en categoria hace algo que nadie agradece hasta que falla: elimina de raíz que el modelo invente "periféricos" con tilde, "peripherals" o "teclados". Si un parámetro tiene un conjunto cerrado de valores, dilo en el schema. Aquí es donde Zod deja de ser una librería de validación y se convierte en el contrato entre el modelo y tu API — si quieres exprimir esa parte, la trabajo a fondo en el curso de Zod.

    Paso 3: el agente

    Aquí viene lo que te ahorra casi todo el código que la gente escribe a mano.

    crearPedido es la tercera herramienta y la dejo para el siguiente apartado, porque tiene truco:

    // agent/index.ts
    import Anthropic from "@anthropic-ai/sdk";
    import { buscarProductos, consultarStock, crearPedido } from "./tools";
    
    const client = new Anthropic(); // lee ANTHROPIC_API_KEY del entorno
    
    const finalMessage = await client.beta.messages.toolRunner({
      model: "claude-opus-4-8",
      max_tokens: 16000,
      tools: [buscarProductos, consultarStock, crearPedido],
      messages: [
        {
          role: "user",
          content: "¿Qué monitores tenéis? Si hay stock del de 27 pulgadas, pídeme dos.",
        },
      ],
    });
    
    console.log(finalMessage.content.find((b) => b.type === "text")?.text);
    

    Eso es el agente entero.

    toolRunner ejecuta el bucle agéntico completo: llama a la API, detecta que la respuesta trae bloques tool_use, ejecuta tu función run, devuelve el resultado como tool_result, y repite hasta que el modelo deja de pedir herramientas. Es beta y vive bajo client.beta.messages. El comportamiento completo está documentado en la guía oficial de tool use.

    Un detalle que se come a mucha gente: ese archivo usa await en el nivel superior, así que necesitas "type": "module" en tu package.json o no compila.

    Y tres cambios de la API actual que rompen código copiado de tutoriales viejos:

    Parámetro Estado en Opus 4.8 Qué usar
    temperature, top_p, top_k Eliminados — devuelven 400 Nada. Quítalos
    budget_tokens Ya no existe thinking: { type: "adaptive" }
    Control de esfuerzo output_config: { effort: "high" } (low a max)

    Si arrastras un temperature: 0 de un proyecto de 2024, tu agente no arranca. Y con thinking: adaptive el modelo decide cuánto piensa según la dificultad, en lugar de gastarte un presupuesto fijo en preguntas triviales.

    Si prefieres el bucle manual, puedes escribirlo, pero recuerda volcar el response.content completo al historial para preservar los bloques tool_use, y devolver cada tool_result con su tool_use_id. Los stop_reason que verás son end_turn, tool_use, max_tokens, pause_turn y refusal.

    Las herramientas destructivas van gateadas

    Una herramienta destructiva se gatea devolviendo el control al usuario dentro de la propia función run, antes del efecto secundario. No requiere bajar al bucle manual.

    Esto es lo que separa una demo de algo que puedes poner delante de un usuario.

    Tu herramienta crear_pedido cobra dinero. Enviar un email, borrar un registro o lanzar un despliegue son irreversibles. El error más común que veo es asumir que para meter aprobación humana hay que bajar al bucle manual.

    No hace falta. El gate vive dentro de la propia función run:

    // agent/tools.ts — mismo archivo, mismos imports
    export const crearPedido = betaZodTool({
      name: "crear_pedido",
      description:
        "Crea un pedido real y descuenta stock. Llama a esto solo cuando el usuario " +
        "haya confirmado explícitamente sku y cantidad.",
      inputSchema: z.object({
        sku: z.string().describe("SKU del producto"),
        unidades: z.number().int().positive().describe("Número de unidades"),
      }),
      run: async ({ sku, unidades }) => {
        const aprobado = await pedirConfirmacion(
          `¿Confirmas el pedido de ${unidades} x ${sku}?`
        );
        if (!aprobado) return "El usuario canceló el pedido. No se ha creado nada.";
    
        const res = await fetch(`${API}/pedido`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ sku, unidades }),
        });
        return JSON.stringify(await res.json());
      },
    });
    

    pedirConfirmacion es tuya. En un CLI son cinco líneas:

    import { createInterface } from "node:readline/promises";
    
    async function pedirConfirmacion(pregunta: string): Promise<boolean> {
      const rl = createInterface({ input: process.stdin, output: process.stdout });
      const respuesta = await rl.question(`${pregunta} (s/n) `);
      rl.close();
      return respuesta.trim().toLowerCase().startsWith("s");
    }
    

    En una app real es un modal, un mensaje de Slack o una fila en una tabla de aprobaciones pendientes. Da igual cuál: el contrato es el mismo, la función run se queda esperando.

    Y devolver "El usuario canceló el pedido" es una respuesta perfectamente válida para el modelo. La entiende, se detiene y se lo explica al usuario. No hace falta arquitectura extra.

    Dos cosas más que conviene saber. El modelo puede pedir varias herramientas en el mismo turno, y sus resultados vuelven todos juntos en un único mensaje de usuario — así que tus funciones run deben ser seguras ejecutándose en paralelo.

    Y si necesitas que el input valide exactamente contra tu schema, sin campos de más, existe strict: true a nivel de definición de herramienta. Ojo: opera sobre el JSON Schema final, que debe llevar additionalProperties: false y required bien puestos — si defines con Zod, revisa el schema que genera antes de activarlo.

    Menos herramientas, mejor descritas

    Cuando pasas de cinco herramientas, la calidad se desploma antes por descripciones vagas que por número.

    Un agente con tres herramientas que dicen con precisión cuándo usarse rinde mejor que uno con quince que dicen qué hacen. Si tienes cuatro endpoints que devuelven variantes de lo mismo, agrúpalos en una herramienta con un parámetro enum. El modelo elige mucho mejor entre valores de un enum que entre nombres de herramientas parecidos.

    Esto es diseño de interfaz, no prompting. Y como cualquier diseño de interfaz, se define antes de escribir el código — es exactamente el trabajo que describo en el libro de Spec-Driven Development: decidir el contrato antes que la implementación.

    Qué hacer hoy

    Abre tu API de siempre. Elige los tres endpoints que más consultas de usuario resolverían. Escribe un archivo tools.ts que los envuelva, con descripciones que digan cuándo llamarlos. Conéctalo al toolRunner.

    Tienes un agente funcionando esta tarde, sin tocar una línea de tu backend.

    Ese es el punto entero de este post: no construyes herramientas para IA, construyes una API normal y le pones un adaptador. Todo lo demás — el estándar, el transporte, el registro de herramientas — son decisiones que vienen después, cuando ya sabes qué herramientas necesitas de verdad.

    Si aún estás decidiendo qué piezas montar alrededor del agente, el stack de IA agéntica que uso en 2026 cubre las decisiones de infraestructura que vienen justo después de este archivo.

    Y si prefieres trabajarlo con otros developers que están en el mismo punto, en Dominicode Labs tenemos los proyectos y los patrones que usamos en producción.


    Preguntas frecuentes

    ¿Necesito MCP para conectar un agente a mi API?
    No. MCP es un estándar de interoperabilidad, útil cuando quieres que varios clientes distintos consuman tus mismas herramientas. Para un agente propio consumiendo tu propia API, un adaptador con betaZodTool y el tool runner del SDK es suficiente y tiene mucha menos superficie que mantener. Si tu caso sí es ese —varios clientes distintos consumiendo las mismas herramientas—, el montaje completo está en MCP Server en TypeScript.

    ¿Qué modelo debo usar para un agente con herramientas?
    claude-opus-4-8 es el modelo actual y más capaz de la familia Opus. Evita los identificadores con sufijo de fecha de generaciones anteriores: están retirados o desactualizados y el código que los usa deja de funcionar.

    ¿Por qué me da error 400 al enviar temperature?
    Porque en Opus 4.8 temperature, top_p y top_k están eliminados. Enviarlos devuelve un error. Para controlar el razonamiento usa thinking: { type: "adaptive" } y, si necesitas más esfuerzo, output_config: { effort: "high" }.

    ¿Cómo evito que el agente ejecute acciones destructivas sin permiso?
    Metiendo el gate dentro de la función run de la herramienta: pides confirmación y, si el usuario dice que no, devuelves un string tipo "el usuario canceló". No necesitas bajar al bucle manual para tener aprobación humana, que es el error habitual.

    ¿El modelo puede llamar a varias herramientas a la vez?
    Sí. Puede pedir varias en un mismo turno y sus resultados vuelven juntos en un único mensaje de usuario. Diseña tus funciones run para que sean seguras ejecutándose en paralelo.

    ¿Debo montar el servidor de herramientas aparte de mi API?
    No hace falta. Tu API de negocio ya es el servidor; la capa de tools es un cliente HTTP delgado que vive en el proceso del agente. Mantener esa separación te permite servir a tu web, tu app y tu agente desde la misma fuente de verdad.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Cómo configurar un webhook en Hermes Agent paso a paso

    Cómo configurar un webhook en Hermes Agent paso a paso

    Un compañero me enseñó, orgulloso, su automatización de code review: un cron cada cinco minutos que llamaba a la API de GitHub y, si aparecía un PR nuevo, lanzaba el agente.

    Funcionaba. Más o menos.

    Cuando GitHub tardaba, se duplicaban las revisiones. Cuando el proceso moría de madrugada, nadie se enteraba hasta el lunes.

    El problema no era el agente. Era que estaba preguntando en lugar de escuchar.

    Un webhook en Hermes Agent invierte esa relación: en vez de sondear, dejas que GitHub, GitLab o cualquier servicio que hable HTTP llamen a tu puerta con la firma criptográfica verificada, y el agente reacciona solo cuando de verdad ha pasado algo.

    Una aclaración antes de seguir, porque me lo preguntáis mucho: Hermes Agent es el agente autónomo open source de Nous Research, no un producto mío. Yo hago contenido sobre él porque me parece una de las piezas más interesantes del ecosistema agéntico actual.

    Todo lo que sigue está verificado contra la documentación oficial de Hermes Agent en julio de 2026. El adaptador webhook sigue evolucionando, así que contrasta con la doc si tu instalación es posterior.

    Los 7 pasos para configurar un webhook en Hermes Agent

    1. Activa el adaptador con hermes gateway setup o las variables WEBHOOK_* en ~/.hermes/.env.
    2. Comprueba que el servidor responde en http://localhost:8644/health.
    3. Define la ruta dentro de platforms.webhook.extra.routes en ~/.hermes/config.yaml.
    4. Elige el esquema de firma del proveedor y valida el HMAC (usa el genérico V2).
    5. Dispara la ruta a mano con hermes webhook test antes de conectar el proveedor real.
    6. Marca con deliver_only: true las rutas que no necesitan que el agente razone.
    7. Ajusta y lista las rutas desde la CLI sin volver a editar YAML.

    Tiempo estimado: 15 minutos.
    Necesitas: Hermes Agent instalado, acceso a la configuración de webhooks del proveedor y una URL pública (o un túnel) que llegue a tu puerto.

    Vamos al lío.

    Qué es un webhook en Hermes Agent y qué hace el adaptador

    Un webhook en Hermes Agent es una ruta HTTP que recibe eventos POST de un servicio externo, valida su firma HMAC y los convierte en una ejecución del agente. Lo gestiona el adaptador webhook, que levanta un servidor HTTP y por cada petición hace cuatro cosas en orden:

    1. Valida la firma HMAC del emisor.
    2. Transforma el payload JSON en un prompt para el agente.
    3. Ejecuta el agente con ese prompt.
    4. Enruta la respuesta de vuelta al origen o a otra plataforma que hayas configurado.

    Ese paso 4 es el que la gente subestima. No es solo "recibir eventos": es cerrar el círculo. El PR entra por GitHub y el comentario sale por GitHub. O por Telegram. Tú decides.

    Paso 1: activa el webhook en Hermes Agent

    Puedes activar el adaptador de dos formas: con el asistente interactivo o declarando las variables de entorno. El asistente:

    hermes gateway setup
    

    O directamente las variables de entorno en ~/.hermes/.env:

    WEBHOOK_ENABLED=true
    WEBHOOK_PORT=8644
    WEBHOOK_SECRET=your-global-secret
    
    Variable Default Para qué sirve
    WEBHOOK_ENABLED false Activa el adaptador
    WEBHOOK_PORT 8644 Puerto del servidor HTTP
    WEBHOOK_SECRET (ninguno) HMAC global de fallback

    Respeta la separación: la configuración general vive en ~/.hermes/config.yaml y los secretos en ~/.hermes/.env. El día que compartas tu config con alguien lo vas a agradecer.

    Paso 2: comprueba que el servidor webhook responde

    El adaptador expone un endpoint /health en el puerto configurado. Si devuelve respuesta, está escuchando y puedes seguir:

    curl http://localhost:8644/health
    

    Si esto no responde, no sigas. Todo lo demás depende de que el servidor esté escuchando.

    Paso 3: define tu primera ruta de webhook en config.yaml

    Aquí está el núcleo de todo. Una ruta es un bloque dentro de platforms.webhook.extra.routes en tu config.yaml:

    platforms:
      webhook:
        enabled: true
        extra:
          port: 8644
          secret: "global-fallback-secret"
          rate_limit: 30
          max_body_bytes: 1048576
          routes:
            github-pr:
              events: ["pull_request"]
              secret: "github-webhook-secret"
              prompt: |
                Review this pull request:
                Repository: {repository.full_name}
                PR #{number}: {pull_request.title}
                Author: {pull_request.user.login}
                URL: {pull_request.html_url}
              skills: ["github-code-review"]
              deliver: "github_comment"
              deliver_extra:
                repo: "{repository.full_name}"
                pr_number: "{number}"
    

    Léelo de arriba abajo y tienes la historia completa: escucha eventos pull_request, valida con este secreto, construye este prompt, usa esta skill y devuelve la respuesta como comentario en el PR.

    Estas son las propiedades que puede llevar una ruta:

    Propiedad Obligatoria Para qué sirve
    events No Tipos de evento a aceptar; si lo dejas vacío, acepta todos
    secret Sí* Secreto HMAC de validación
    prompt No Plantilla con dot-notation; si se omite, vuelca el JSON completo
    skills No Skills que se cargan para esa ejecución del agente
    filters No Filtrado declarativo del payload
    script No Ruta a un script de filtro o transformación propio
    deliver No Destino: github_comment, telegram, discord, slack, log
    deliver_extra No Configuración del destino (chat_id, repo, pr_number…)
    deliver_only No Salta el agente y envía el prompt como mensaje literal

    *secret es obligatorio salvo que la ruta herede el secreto global.

    Sobre las plantillas de prompt, cuatro detalles que te van a morder si no los sabes:

    • La dot-notation resuelve rutas anidadas: {pull_request.title} equivale a payload["pull_request"]["title"].
    • Si una clave no existe, se renderiza literalmente como {clave}. No falla, no avisa. Tu prompt simplemente llega con basura dentro. Este es el error número uno.
    • {__raw__} vuelca el payload entero como JSON indentado, truncado a 4000 caracteres. Muy útil mientras exploras un proveedor nuevo, mala idea en producción.
    • Las estructuras anidadas se serializan a JSON y se truncan a 2000 caracteres. Si un prompt te llega cortado por la mitad, es esto.

    Paso 4: valida la firma HMAC del proveedor

    Hermes trae cuatro verificadores de firma. Dos específicos y dos genéricos para todo lo demás:

    • GitHub: cabecera X-Hub-Signature-256, formato sha256=<hex>, HMAC-SHA256 del body.
    • GitLab: cabecera X-Gitlab-Token, comparación literal del secreto.
    • Genérico V2 (el recomendado): cabeceras X-Webhook-Signature-V2 y X-Webhook-Timestamp. El HMAC-SHA256 se calcula sobre <timestamp>.<body> y el timestamp debe caer dentro de ±300 segundos.
    • Genérico V1 (legacy, deprecado): cabecera X-Webhook-Signature, HMAC solo del body y sin protección anti-replay.

    Usa V2. La diferencia no es cosmética: al meter el timestamp dentro del material firmado, una petición capturada deja de servir pasados cinco minutos. Con V1, un payload robado es válido para siempre.

    Y ahora el matiz que separa a quien ha metido esto en producción de quien no: validar el HMAC prueba la identidad del emisor, no que el contenido sea de fiar. Que GitHub firme el evento confirma que viene de GitHub, no que el título del PR no contenga una inyección de prompt escrita por un colaborador externo. Todo campo que venga de fuera se trata como no confiable, siempre. Es la misma disciplina de límites de confianza que aplico al conectar herramientas externas vía servidores MCP.

    Paso 5: prueba la ruta con hermes webhook test

    No configures una ruta y te quedes mirando GitHub a ver si pica. Hermes trae un comando para dispararla a mano:

    hermes webhook test github-issues
    hermes webhook test github-issues --payload '{"issue": {"number": 42}}'
    

    Con --payload controlas exactamente qué recibe la plantilla, así que puedes verificar que tu dot-notation resuelve bien antes de que el evento real llegue.

    Si el ciclo de "defino el comportamiento, lo pruebo, lo ajusto" te suena a especificar antes de implementar, es exactamente eso. Es el mismo enfoque que desarrollo en el libro de Spec-Driven Development: decide el contrato primero, verifica después.

    Paso 6: usa deliver_only para rutas sin coste de LLM

    Esta es mi parte favorita y la más ignorada. No todo evento necesita un LLM detrás.

    routes:
      antenna-matches:
        secret: "antenna-webhook-secret"
        deliver: "telegram"
        deliver_only: true
        prompt: "🎉 New match: {match.user_name} matched with you!"
        deliver_extra:
          chat_id: "{match.telegram_chat_id}"
    

    Con deliver_only: true el prompt renderizado se envía tal cual como mensaje y el agente nunca se invoca. Coste de inferencia: cero.

    Un despliegue terminado, un pago recibido, un test que falla: no necesitas que un modelo razone sobre eso, necesitas que llegue a tu Telegram. Reserva el agente para lo que exige criterio y usa deliver_only para el resto. Es la decisión que más reduce la factura de tu stack de IA agéntica.

    Paso 7: gestiona las rutas desde la CLI de Hermes

    La CLI crea, lista y elimina rutas sin tocar el YAML, que es lo cómodo para iterar:

    hermes webhook subscribe github-issues \
      --events "issues" \
      --prompt "New issue #{issue.number}: {issue.title}\nBy: {issue.user.login}" \
      --deliver telegram \
      --deliver-chat-id "-100123456789" \
      --description "Triage new GitHub issues"
    
    hermes webhook list
    hermes webhook remove github-issues
    

    Códigos de respuesta del webhook y qué significa cada uno

    El adaptador te dice con precisión qué ha pasado. Aprende esta tabla y te ahorras horas:

    Código Significado
    200 Entregado, o duplicado descartado por idempotencia
    401 Firma inválida o ausente
    400 JSON malformado
    404 Ruta desconocida
    413 El body supera max_body_bytes
    429 Rate limit superado
    502 El destino rechazó la entrega

    Dos protecciones que vienen puestas de serie y conviene conocer: el rate limit por defecto es de 30 peticiones por minuto y por ruta (ajustable con rate_limit), y hay una caché de idempotencia de una hora basada en las cabeceras de delivery ID. Ese reenvío duplicado que rompía el cron de mi compañero aquí devuelve 200 y no ejecuta nada.

    Una última nota de seguridad: toda ruta necesita un secreto, propio o heredado del global. INSECURE_NO_AUTH existe, pero solo funciona en loopback (127.0.0.1, localhost, ::1). Está bien pensado: no puedes dejarte una puerta abierta en producción por accidente.

    Empieza por lo pequeño

    Si vas a hacer una sola cosa hoy, que sea esta: activa el adaptador, crea una ruta con deliver_only: true que te avise por Telegram de algo que ahora mismo miras a mano, y déjala corriendo una semana.

    No montes el code review automático el primer día. Comprueba antes que los eventos llegan, que la firma valida y que tus plantillas resuelven. Cuando eso sea aburrido y predecible, le pones el agente detrás.

    La documentación de referencia está en la guía oficial de webhooks de Hermes Agent y el código en el repositorio de NousResearch.

    Y si lo que quieres es el marco completo —cómo pasar de una idea a un producto real apoyándote en agentes sin acabar con un montón de automatizaciones frágiles— eso es justo lo que enseño en el curso Construye con IA, y lo que practicamos cada semana dentro de Dominicode Labs.

    Preguntas frecuentes

    ¿Necesito exponer mi máquina a internet para usar un webhook en Hermes Agent?

    Sí, el proveedor externo tiene que poder alcanzar el puerto donde escucha el adaptador (8644 por defecto), así que necesitas una URL pública o un túnel hacia tu equipo. Para probar en local sin montar nada de eso puedes fijar el secreto de la ruta a INSECURE_NO_AUTH y saltarte la validación de firma, pero Hermes solo lo acepta cuando el gateway escucha en loopback (127.0.0.1, localhost, ::1), precisamente para que no puedas dejarte esa puerta abierta de cara a internet.

    ¿Qué diferencia hay entre la firma genérica V1 y la V2?

    La V2 incluye protección anti-replay y la V1 no. V2 usa las cabeceras X-Webhook-Signature-V2 y X-Webhook-Timestamp, calcula el HMAC-SHA256 sobre <timestamp>.<body> y rechaza cualquier petición cuyo timestamp se salga de ±300 segundos. V1 firma solo el body, está deprecada y una petición capturada sigue siendo válida indefinidamente.

    ¿Puedo recibir webhooks sin gastar tokens de LLM?

    Sí. Añade deliver_only: true a la ruta y Hermes renderiza la plantilla del prompt y la envía como mensaje literal al destino configurado, sin invocar nunca al agente. El coste de inferencia es cero. Es la opción correcta para notificaciones de despliegues, pagos o alertas donde no hace falta ningún razonamiento.

    ¿Qué pasa si el proveedor reenvía el mismo evento dos veces?

    Se descarta. Hermes mantiene una caché de idempotencia de una hora basada en las cabeceras de delivery ID del proveedor, y el duplicado recibe un 200 sin ejecutar el agente de nuevo. Es la protección que hace innecesario el típico registro manual de eventos ya procesados que se monta con sondeo por cron.

    ¿Es obligatorio poner un secreto en cada ruta?

    Sí. Toda ruta necesita un secreto para validar la firma HMAC, aunque puede heredar el valor global definido en WEBHOOK_SECRET o en platforms.webhook.extra.secret en lugar de declarar el suyo propio. Sin secreto válido, las peticiones se rechazan con 401. Lo recomendable es un secreto distinto por ruta.

    Mi webhook devuelve 401, ¿qué reviso?

    Un 401 significa firma inválida o ausente, casi siempre por desajuste entre el secreto configurado en Hermes y el que registraste en el proveedor. Verifica que coinciden exactamente, que el proveedor envía la cabecera esperada (X-Hub-Signature-256 en GitHub, X-Gitlab-Token en GitLab) y, si usas V2, que el reloj del emisor no se desvía más de 300 segundos.

    ¿Webhook o polling con cron para disparar un agente?

    Webhook, salvo que el proveedor no los ofrezca. El polling introduce latencia igual al intervalo del cron, duplica ejecuciones cuando la API tarda en responder y falla en silencio si el proceso muere. El adaptador webhook reacciona en el momento del evento, descarta reenvíos con su caché de idempotencia de una hora y devuelve un código HTTP que dice exactamente qué ha fallado. El cron solo gana cuando el sistema origen no emite eventos.

    ¿Por qué mi prompt llega con {algo} sin sustituir?

    Porque esa clave no existe en el payload. Hermes renderiza literalmente como {clave} cualquier ruta que no resuelva, sin lanzar error. Dispara la ruta con hermes webhook test <nombre> --payload '<json>' para inspeccionar la estructura real, o usa {__raw__} temporalmente para volcar el payload completo y localizar el nombre correcto del campo.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Kimi K3: el modelo “open source” que no vas a poder correr

    Kimi K3: el modelo “open source” que no vas a poder correr

    El 16 de julio de 2026, por la mañana, me llegaron cuatro mensajes casi idénticos. Todos decían alguna versión de lo mismo: "Bezael, ha salido Kimi K3, ¿esto lo puedo bajar y correrlo en local?".

    Entiendo la ilusión. Moonshot AI lo anunció como el mayor modelo open source del mundo. Y "open source" en la cabeza de cualquier developer significa una cosa muy concreta: lo descargo, lo pongo en mi máquina, dejo de pagar tokens.

    Con este no.

    Kimi K3 tiene 2.8 billones de parámetros. Los pesos son abiertos, sí. Pero abrir los pesos de un modelo de ese tamaño es como regalarte los planos de un portaaviones. Técnicamente lo tienes todo. Prácticamente no lo vas a construir en el garaje.

    Así que la pregunta interesante no es "¿supera a Fable 5?". Esa la contesta cualquier tabla de benchmarks y encima se queda obsoleta en tres semanas. La pregunta que sí te cambia el mes es: ¿me conviene mover mi agente de coding a K3, y a partir de cuándo?

    Vamos con eso.

    ¿Qué es Kimi K3?

    Kimi K3 es el modelo de lenguaje que Moonshot AI (Pekín) lanzó el 16 de julio de 2026. Tiene 2.8 billones de parámetros con pesos abiertos, entrada multimodal de imagen y una ventana de contexto de 1M tokens, con razonamiento siempre activo y sin modo rápido. Moonshot lo distribuye en dos variantes: K3 Max, orientada a chat y agentes, y K3 Swarm Max, para paralelismo a gran escala.

    En el índice independiente de Artificial Analysis, Kimi K3 puntúa 57 y ocupa el puesto #4 de 187 modelos evaluados en el corte de julio de 2026. Ese índice se recalcula cada pocas semanas y tanto la puntuación como el puesto se mueven, así que trata la cifra como una foto fechada, no como una constante. Su precio de API es de $3 por millón de tokens de entrada y $15 por millón de salida, con cache hit a $0.30.

    Hasta ahí la ficha. Lo interesante empieza cuando la cruzas con lo que necesitas tú.

    El "open source" de 2.8T no significa lo que crees

    Haz la cuenta conmigo, porque es aritmética de servilleta y te ahorra la tarde.

    2.8 billones de parámetros. Aun cuantizando agresivamente a 4 bits —medio byte por parámetro— necesitas del orden de 1,4 TB de memoria solo para tener los pesos residentes. Sin contar el KV cache, que con una ventana de 1M tokens no es precisamente pequeño.

    Tu Mac con 128 GB de RAM unificada no entra. Ni el doble. Ni el de tu amigo el del homelab con dos 4090.

    Estás hablando de un rack. De órdenes de magnitud por encima de lo que un dev individual —o una startup pequeña— monta para inferencia propia.

    Entonces, ¿qué gana el mundo con que los pesos sean abiertos? Gana algo real, pero indirecto: cualquier proveedor puede servirlo, nadie te encierra en una única API, y el precio tiende a bajar por competencia entre hosts. Eso es valioso. Pero no es soberanía local. Es no depender de un solo vendor.

    Si lo que buscabas era de verdad correr modelos en tu máquina, esa es otra conversación y la tengo escrita aparte: los mejores modelos de IA para ejecutar en local en 2026. Ahí sí hay opciones que caben en tu hardware.

    Para K3 vas a pagar tokens igual que con cualquier modelo cerrado. La forma más rápida de probarlo sin abrirte cuenta en Moonshot es a través de un router; te expliqué el mecanismo completo en qué es OpenRouter y para qué sirve.

    Kimi K3: qué está verificado y qué es marketing de Moonshot

    Aquí voy a ser quisquilloso a propósito, porque el 90% de lo que se ha publicado sobre él estos días mezcla las dos categorías sin avisarte.

    Lo verificado en fuentes independientes (ficha de Kimi K3 en OpenRouter y Artificial Analysis):

    • Kimi K3 se lanzó el 16 de julio de 2026, desarrollado por Moonshot AI (Pekín).
    • Kimi K3 tiene 2.8T parámetros con pesos abiertos y es multimodal con entrada de imagen.
    • Kimi K3 ofrece una ventana de contexto de 1M tokens.
    • Kimi K3 razona siempre: a día de hoy no existe una versión "rápida sin pensar".
    • El precio de Kimi K3 es de $3 por 1M de tokens de entrada y $15 por 1M de salida, con cache hit a $0.30 (un 90% menos).
    • Kimi K3 obtiene 57 en el Artificial Analysis Intelligence Index, puesto #4 de 187 modelos. La media de modelos comparables está en 31.
    • OpenRouter advierte en la ficha del modelo de que la capacidad upstream de Kimi K3 está limitada y son frecuentes los errores 429.

    Lo que dice el fabricante y no está auditado:

    • SWE-bench Verified 76.8%, Terminal-Bench 2.1 en 88.3, FrontierSWE 81.2.
    • Un Coding Index de 76.24 que lo pondría por encima de Fable 5 — dato que circula de terceros y que aún no aparece en la ficha oficial de Artificial Analysis.
    • Las dos variantes, K3 Max y K3 Swarm Max, las anuncia Moonshot y las recogen los medios, pero no aparecen diferenciadas en la ficha de OpenRouter.

    Y aquí una que no está sin confirmar, sino directamente refutada. Moonshot afirma que K3 compite con Fable 5 y supera a Opus 4.8 y a GPT-5.6. Coge el mismo índice independiente que la propia Moonshot cita y mira la tabla completa:

    Modelo Intelligence Index
    Claude Fable 5 59.9
    GPT-5.6 Sol 58.9
    Kimi K3 57
    Claude Opus 4.8 56

    Lo de superar a Opus 4.8 es cierto. Lo de superar a GPT-5.6 es falso: queda casi dos puntos por debajo de Sol. Y "competir con Fable 5" es defendible si por competir entendemos quedarse a tres puntos, que para un modelo de pesos abiertos es una noticia enorme — pero no es lo mismo que empatar.

    Que quede claro: puesto #4 de 187 no se regala y K3 no es humo. Lo que digo es que las cifras de coding, que son las que más te importan a ti, son hoy marketing sin auditar. Trátalas como hipótesis a validar en tu repo, no como hechos.

    El mercado, en cambio, se lo creyó de golpe: según la prensa financiera, el lanzamiento tumbó acciones de semiconductores y le valió el apodo de "segundo shock DeepSeek".

    El coste real de Kimi K3: el impuesto de la verbosidad

    Este es el dato que más me llamó la atención, y está publicado en la misma ficha de Artificial Analysis que todo el mundo cita para el ranking — pero que casi nadie lee hasta el final.

    Kimi K3 consumió 130 millones de tokens de salida para completar el Intelligence Index. La media de los modelos evaluados es de 63M. La propia ficha lo califica de "very verbose".

    Multiplica: 130M × $15 por millón. Son casi 2.000 dólares de output solo para pasar una batería de evaluación.

    Ahí está el punto. El precio de lista de un modelo no es su coste. Su coste es el precio de lista multiplicado por lo que le da la gana escribir.

    K3 razona siempre, y razona largo: algo más del doble que la media. Haz la traducción a dinero — un modelo de $15/1M que emite 2,06 veces los tokens de la media te sale, en la práctica, como uno de ~$31.

    Sigue estando por debajo de Fable 5 a ~$50. Pero la distancia real es la mitad de la que sugiere la tabla de precios:

    Modelo Output / 1M tokens
    Fable 5 ~$50
    Kimi K3 $15
    GLM-5.2 $3.52
    DeepSeek V4 Pro $0.87

    Parece que K3 está en un punto dulce. Y puede que lo esté. Pero esa tabla es engañosa mientras no le añadas la columna que casi nadie mira: tokens emitidos por tarea resuelta. Artificial Analysis publica el agregado de su índice; lo que ningún benchmark publica es ese número para tus tareas.

    Y ojo con el consuelo del cache: el descuento del 90% a $0.30 juega a favor de K3 en agentes, donde reenvías el mismo contexto una y otra vez. Pero aplica a la entrada, no a la salida. Y tu problema con este modelo es la salida.

    ¿Cuándo conviene migrar tu agente de coding a Kimi K3?

    Te conviene mirarlo en serio si:

    • Trabajas con repos grandes de verdad y el millón de tokens de contexto te ahorra la gimnasia de trocear y resumir. Ahí sí compensa.
    • Haces agentic de horizonte largo, con sesiones de muchos pasos, y el razonamiento permanente reduce las veces que el agente se descarrila a mitad de tarea.
    • Estás pagando facturas de cuatro cifras con un frontier caro, y una reducción de coste por token —aun con la verbosidad descontada— te sale a cuenta.
    • Te importa la portabilidad. Pesos abiertos significa que si mañana un proveedor sube precios, te llevas la carga a otro. Eso es apalancamiento real de negociación.

    No te molestes si:

    • Necesitas latencia estable en producción hoy. Los 429 que advierte OpenRouter no son teóricos: la demanda obligó a Moonshot a parar nuevas suscripciones por saturación de GPUs a los pocos días del lanzamiento. Un agente que falla una de cada siete llamadas no es un agente, es una lotería.
    • Tu caso son tareas cortas y bien acotadas. Vas a pagar razonamiento que no necesitas en cada llamada, sin opción de apagarlo.
    • Ya tienes un harness afinado alrededor de otro modelo.

    Y este último es el punto que más me duele repetir: cambiar de modelo casi nunca es donde está tu ganancia. Lo desarrollé entero en por qué el harness agéntico, no el LLM, es el producto. Tus prompts, tus herramientas, tu gestión de contexto y tus validaciones pesan más en el resultado final que dos puntos de diferencia en un índice.

    Si tu agente falla porque le das mal el contexto, K3 va a fallar igual. Solo que escribiendo más y cobrándotelo.

    Es exactamente lo que trabajamos en el curso de Construye con IA: de la idea al producto con Claude Code — montar el sistema alrededor del modelo, para que el día que salga el siguiente K3 puedas cambiarlo en una línea de configuración y seguir con tu vida.

    Veredicto: ¿merece la pena Kimi K3 hoy?

    Kimi K3 es genuinamente bueno. Puesto #4 de 187 en un índice independiente no se regala, y el precio frente a la gama alta occidental es agresivo de verdad.

    Pero no es el modelo que vas a correr en tu máquina, y su coste real está por encima de lo que sugiere su precio de lista. Dos cosas que el anuncio no te dice.

    Mi posición hoy: lo evalúo, no lo migro. Si dependes de coding en producción, espera a dos señales concretas antes de mover nada: que Artificial Analysis publique el Coding Index en su ficha oficial, y que la capacidad upstream se estabilice. Escribo esto la semana del lanzamiento (20 de julio de 2026); si llegas a este post más tarde, comprueba ambas antes de darlas por pendientes.

    Comparar contra la otra familia frontier también ayuda a calibrar: tienes los números de la de OpenAI en la guía práctica de GPT-5.6 vía API.

    Cómo decidirlo con tus propios datos en una hora

    No te fíes de mi veredicto ni del anuncio de Moonshot. Mide:

    1. Coge diez tareas reales de tu backlog — no de un benchmark. Tareas que ya sabes resolver, para poder juzgar el resultado.
    2. Pásalas por tu modelo actual y por K3, con el mismo harness y los mismos prompts.
    3. Apunta tres columnas por tarea: tokens de salida, coste total y si la tarea quedó resuelta o no.
    4. Compara coste por tarea resuelta, no precio por millón de tokens. Es la única cifra que decide.

    Ese número tuyo vale más que todos los benchmarks del anuncio juntos. Y va a haber sorpresas en las dos direcciones.

    Ese blindaje empieza incluso antes del harness: si escribes la especificación de lo que quieres construir, el modelo pasa a ser una pieza intercambiable. Es la tesis completa del libro de Spec-Driven Development.

    Si haces el experimento, comparte los resultados en Dominicode Labs — estamos juntando mediciones reales de la comunidad, que es exactamente el dato que ningún benchmark publica.

    Preguntas frecuentes sobre Kimi K3

    ¿Qué es Kimi K3?
    Kimi K3 es el modelo de lenguaje de Moonshot AI lanzado el 16 de julio de 2026. Tiene 2.8 billones de parámetros con pesos abiertos, ventana de contexto de 1M tokens, entrada multimodal de imagen y razonamiento permanente. Puntúa 57 en el Artificial Analysis Intelligence Index, puesto #4 de 187 modelos.

    ¿Kimi K3 es realmente open source?
    Los pesos de Kimi K3 son abiertos, pero eso no equivale a poder ejecutarlo. Con 2.8T parámetros, la barrera de hardware lo deja fuera del alcance de cualquier developer o startup pequeña. El beneficio real de esos pesos abiertos es que cualquier proveedor puede servir el modelo: evita el lock-in de vendor y presiona el precio a la baja, pero no da soberanía local.

    ¿Puedo ejecutar Kimi K3 en local?
    En la práctica, no. Con 2.8T parámetros necesitas del orden de 1,4 TB de memoria solo para los pesos, incluso cuantizando a 4 bits. Eso es infraestructura de datacenter, no de escritorio. Los pesos son abiertos, pero eso beneficia a quien pueda servirlos, no a tu portátil.

    ¿Cuánto cuesta Kimi K3?
    $3 por millón de tokens de entrada y $15 por millón de salida, con los cache hits a $0.30 (un 90% de descuento). Ojo: por su verbosidad, el coste efectivo por tarea suele quedar bastante por encima de lo que sugiere esa tarifa.

    ¿Kimi K3 es mejor que Fable 5 para programar?
    Moonshot lo afirma y circula un Coding Index de 76.24 que lo situaría por encima. Ese dato viene de terceros y todavía no aparece en la ficha oficial de Artificial Analysis. En inteligencia general sí hay dato auditado, y no respalda la afirmación: Fable 5 puntúa 59.9 y Kimi K3, 57. En coding concretamente, trátalo como hipótesis hasta que se confirme.

    ¿Cuál es la diferencia entre K3 Max y K3 Swarm Max?
    Según Moonshot, K3 Max está orientado a chat y flujos agénticos convencionales, mientras que K3 Swarm Max está pensado para ejecución paralela a gran escala. Para un agente de coding individual, tu variante es K3 Max.

    ¿Por qué Kimi K3 sale más caro de lo que dice su precio?
    Porque razona siempre y razona largo. Kimi K3 emitió 130M tokens de salida completando el Intelligence Index de Artificial Analysis, frente a una media de 63M — algo más del doble. A $15 por millón de salida, esa verbosidad sitúa el coste efectivo en torno a los $31 por millón. El precio de lista de un modelo no es su coste: su coste es el precio de lista por lo que decide escribir.

    ¿Por qué me devuelve errores 429?
    OpenRouter avisa en la propia ficha del modelo de que la capacidad upstream está limitada tras el lanzamiento. Si lo llevas a producción, necesitas reintentos con backoff y un modelo de fallback configurado.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

    Analizo lanzamientos como este en detalle en el canal de YouTube de Dominicode.

  • 5 agentes de IA que puedes construir con Hermes para tu negocio

    5 agentes de IA que puedes construir con Hermes para tu negocio

    Cuando hablo con fundadores de startups y desarrolladores sobre agentes de IA, casi todos se imaginan lo mismo: un chatbot de soporte básico en la esquina inferior de su web que responde preguntas frecuentes sacadas de un PDF de texto plano.

    Qué aburrimiento. Y qué desperdicio de tecnología.

    Los agentes de IA no están pensados para ser meros contestadores automáticos. Están diseñados para ejecutar flujos operativos complejos de tu negocio en segundo plano: monitorizar sistemas, calificar prospectos o conciliar facturas de forma 100% autónoma.

    Hoy te quiero enseñar 5 agentes que puedes construir con Hermes (el framework open-source de Nous Research) para delegar las tareas repetitivas de tu negocio y centrarte únicamente en la estrategia y la especificación.


    1. El Operador Autónomo de Comunidad (Soporte + Captación)

    Este es uno de los agentes más demandados. No se limita a responder dudas. Vive en tus canales de Slack, Telegram o Discord y atiende a los usuarios con memoria a largo plazo (recordando lo que habló con cada uno días atrás). Como vimos en nuestro post anterior, un agente de marketing con Notion puede calificar y almacenar leads de forma totalmente autónoma.

    • Cómo opera: Consulta la documentación de tu producto mediante MCP (Model Context Protocol), responde las dudas del usuario y, si detecta interés de compra, inicia una calificación conversacional natural.
    • Acción de negocio: Registra al prospecto en Notion y te envía un resumen por email al final del día con los leads calificados.

    2. El Agente DevOps de Auto-Sanación (Monitoreo + Reparación)

    Tener un desarrollador de guardia para resolver caídas sencillas del servidor a las 3:00 AM es ineficiente y costoso. Un agente de guardia DevOps puede encargarse de la primera línea de defensa.

    • Cómo opera: Monitorea logs y alertas en tu infraestructura en la nube (como Railway o un VPS). Al detectar un error de base de datos o puerto bloqueado, levanta un Sandbox seguro de Docker.
    • Acción de negocio: Ejecuta scripts de diagnóstico, soluciona el fallo de forma aislada y, si es un error inédito, te contacta por Telegram para pedirte instrucciones. Tras recibir la solución, genera una nueva Skill en Python para corregirlo solo la próxima vez.

    3. El Redactor y Programador de Contenidos (Blog + SEO)

    Mantener un blog técnico con posts semanales de alta calidad técnica requiere horas de redacción, auditoría de palabras clave y maquetación. Un agente de contenidos automatiza el pipeline entero.

    • Cómo opera: Dado un tema o palabra clave, redacta el borrador en markdown en estilo directo conversacional, realiza una auditoría SEO y de visibilidad en paralelo y genera una portada Open Graph (thumbnail) en base a tu sistema de diseño.
    • Acción de negocio: Conecta con la REST API de tu CMS (como WordPress) y sube el borrador completo listo para publicar.

    4. El Investigador de Leads y Clientes (Outbound + Ventas)

    El trabajo de buscar prospectos calificados en directorios, registrar sus datos de contacto en una hoja de cálculo y redactar propuestas personalizadas consume gran parte del tiempo de cualquier equipo de ventas.

    • Cómo opera: Scrapea listas de asistentes a eventos tecnológicos o directorios públicos, analiza las webs de las empresas y evalúa si encajan con tu Perfil de Cliente Ideal (ICP).
    • Acción de negocio: Extrae correos, nombres de fundadores y genera un dossier PDF detallado con un ángulo personalizado para realizar la propuesta.

    5. El Asistente de Finanzas y Conciliación Mensual

    Llevar la contabilidad de tu empresa a final de mes suele implicar descargar facturas de múltiples plataformas, buscar transacciones en el banco y meter datos manualmente en un Excel.

    • Cómo opera: Lee tus registros de cobros de plataformas de pago (como Stripe) mediante webhooks, descarga de forma autónoma los PDFs de gastos de tu correo o almacenamiento en la nube y asocia cada factura a su transacción correspondiente.
    • Acción de negocio: Actualiza tu hoja de cálculo mensual de pérdidas y ganancias (P&L) y te alerta si falta alguna factura de soporte de gasto.

    Diseña sistemas que operen, no simples prompts

    El verdadero valor de la IA en 2026 no está en el chat rápido que usas para resolver una duda de código. Está en diseñar agentes de larga duración que se ejecutan de forma de forma persistente e independiente 24/7.

    En el próximo [curso de Agentes IA Autónomos en Producción con Hermes Agent]([ENLACE PENDIENTE]) construimos de principio a fin las plantillas bases y repositorios del Operador de Comunidad y el Agente DevOps de Auto-Sanación.

    Si quieres debatir con otros ingenieros senior sobre cómo desplegar estos flujos operativos en tus propios proyectos, te espero en Dominicode Labs.


    Preguntas Frecuentes (FAQ)

    ¿Por qué usar Hermes Agent para construir estos sistemas?

    Hermes Agent (desarrollado por Nous Research) destaca por su arquitectura diseñada para tareas de largo recorrido. A diferencia de las llamadas a API simples, cuenta con persistencia de memoria SQLite local, soporte nativo de sandboxes de Docker para seguridad y un bucle de auto-mejora que permite que el agente genere sus propias capacidades sobre la marcha.

    ¿Qué nivel de seguridad tienen estos agentes en producción?

    El nivel de seguridad depende del diseño. Al utilizar Docker Sandboxes en Hermes, limitamos la ejecución de código generado por el LLM a contenedores cerrados y efímeros sin red, evitando que un script malicioso pueda borrar datos o comprometer tu servidor principal.

    ¿Se pueden conectar estos agentes a herramientas como Notion o Slack?

    Sí, gracias al Model Context Protocol (MCP). MCP proporciona un estándar abierto que permite conectar de forma directa e inmediata tu agente a Notion, Slack, GitHub, Postgres o Gmail simplemente añadiendo un archivo de configuración JSON.

    ¿Cómo puedo empezar a construir mi primer agente DevOps?

    Puedes empezar por automatizar lecturas de logs. Configura tu agente para que lea las respuestas de un endpoint de health check de tu aplicación y use integraciones de mensajería (Telegram o Slack) para alertarte con datos consolidados cuando detecte respuestas de error 500.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • El Agentic Harness: Por qué un LLM por sí solo no es un producto

    El Agentic Harness: Por qué un LLM por sí solo no es un producto

    Cuando ves la demostración de un brazo robótico industrial realizando una tarea de precisión milimétrica, te quedas maravillado con la tecnología. Sin embargo, ninguna fábrica en su sano juicio dejaría que ese brazo operase de forma autónoma en su línea de montaje si solo consistiera en el motor mecánico.

    Necesita sensores de proximidad, sistemas de parada de emergencia, un software de control de límites y un operario humano supervisando la consola.

    El brazo aporta la fuerza y el movimiento bruto; pero la seguridad, consistencia y utilidad real de la operación dependen del soporte que lo rodea.

    En la inteligencia artificial moderna ocurre exactamente lo mismo. Un modelo de lenguaje (como Claude 3.5 Sonnet o GPT-4o) por sí solo es como ese brazo sin sensores. Para que solucione problemas reales en tu empresa, necesitas envolverlo en un Agentic Harness (Arnés Agéntico).

    Hoy te quiero explicar en qué consiste este concepto arquitectónico y por qué el diseño del arnés es lo que realmente convierte a la IA en un producto de negocio viable.


    El modelo es solo la "inteligencia"

    Existe una falsa creencia de que para automatizar un proceso basta con comprar tokens de API del modelo más grande de la nube y empezar a enviarle instrucciones conversacionales.

    Los LLMs son motores de predicción de texto extraordinarios, pero sufren de carencias críticas que les impiden operar en producción de forma directa:

    1. Carecen de estado: No recuerdan lo que pasó hace cinco minutos a menos que les reenvíes todo el historial (lo que satura el contexto y encarece la consulta).
    2. No controlan su ejecución: Pueden proponer una consulta SQL brillante, pero no tienen la capacidad física de conectarse a tu base de datos para ejecutarla y leer los resultados.
    3. Alucinan bajo presión: Si una herramienta externa les devuelve un error inesperado, el modelo suele inventar un parche absurdo en lugar de detenerse y pedir ayuda.

    Aquí es donde entra el Agentic Harness. El arnés es la infraestructura de software que envuelve al modelo para convertirlo en un agente autónomo, seguro y con memoria persistente.


    Las 4 patas de un Agentic Harness de Producción

    Para que tu arnés agéntico sea robusto y scalables, debe estructurar cuatro capas de soporte bien definidas alrededor de la API del LLM:

    ┌────────────────────────────────────────────────────────┐
    │                    AGENTIC HARNESS                     │
    ├───────────────┬────────────────┬───────────────┬───────┤
    │ Orquestación  │  Persistencia  │  Sandboxing   │ Evals │
    │ y Flujo (Loop)│   y Memoria    │ de Ejecución  │   y   │
    │               │ (SQLite/FTS5)  │    (Docker)   │ Control│
    └───────────────┴────────────────┴───────────────┴───────┘
                                    ▲
                                    │ (Inferencia)
                         [ API de Inferencia LLM ]
    

    1. Orquestación y Control (El Bucle de Decisiones)

    Es el motor lógico que gestiona el ciclo de vida del agente. Se encarga de parsear las peticiones del usuario, construir el prompt de entrada estructurado, llamar al modelo y mapear las respuestas de este hacia herramientas ejecutables. Si la llamada de la herramienta devuelve un error, el loop se encarga de re-intentarlo o alterar el plan de forma autónoma.

    2. Persistencia y Memoria (El Almacén de Estado)

    Evita la amnesia del agente. El arnés debe persistir el estado de la conversación y las variables en una base de datos local (como SQLite con soporte WAL). Si el servidor se apaga o el contenedor de Railway se actualiza por Git-Ops, el agente puede recuperar su memoria y reanudar el flujo en el punto exacto donde se quedó.

    3. Sandboxing de Ejecución (La Seguridad Física)

    Un arnés seguro nunca permite que la IA ejecute código de forma directa en el servidor principal. Como vimos en nuestro post sobre Docker Sandboxing en producción, el aislamiento es la clave. El arnés debe levantar contenedores efímeros cerrados de Docker para que el agente pruebe sus scripts de diagnóstico o compile programas sin poner en riesgo la estabilidad del VPS.

    4. Gobernanza y Evals (El Control Humano)

    El arnés define las fronteras éticas y operativas. Registra logs estructurados para auditorías, escanea prompts entrantes contra inyecciones y, lo más importante, implementa sistemas de autorización (Human-in-the-loop). Si el agente quiere realizar una acción crítica (como eliminar datos o transferir fondos), el arnés congela la ejecución y solicita confirmación al administrador por Telegram.


    Hermes Agent: Un Arnés Agéntico Open-Source

    El framework de Hermes Agent de Nous Research es un excelente ejemplo de un Agentic Harness de producción. No es un modelo de IA; es el andamiaje técnico que te proporciona la persistencia en SQLite, el aislamiento en Docker sandboxes y la interfaz de MCP listos para usar de forma nativa.

    Entender la IA como un sistema completo y no como una simple consulta a una API es la base que enseñamos en el curso de Construye con IA para desarrollar productos robustos. Además, es la arquitectura de infraestructura que implementamos de principio a fin en el nuevo curso de Agentes IA Autónomos en Producción con Hermes Agent.


    Conclusión: Deja de comprar modelos, diseña tu arnés

    Los modelos de lenguaje seguirán bajando de precio y haciéndose más inteligentes cada mes. Son un commodity. El verdadero valor y la propiedad intelectual de tu negocio radican en el diseño de tu Agentic Harness. Al construir un arnés modular, seguro y persistente, garantizas que cualquier modelo (local o en la nube) pueda operar con consistencia para resolver las tareas operativas de tu empresa.

    Si estás estructurando el arnés agéntico para tu negocio y quieres discutir decisiones de arquitectura o seguridad con otros desarrolladores senior de nuestra comunidad, te espero en Dominicode Labs.


    Todo esto descansa sobre una distinción que conviene no dar por sabida: la definición operativa de agente de IA, la que se puede verificar mirando tu código en vez de la etiqueta del producto.

    Preguntas Frecuentes (FAQ)

    ¿Cuál es la diferencia entre LangChain y un Agentic Harness completo?

    ¿Cuál es la diferencia entre LangChain y un Agentic Harness completo? LangChain o LlamaIndex son librerías de software y componentes que te ayudan a estructurar flujos de datos e integraciones. Un Agentic Harness es el sistema en ejecución completo en producción (la arquitectura de servidores, bases de datos de estado, sandboxes aislados de Docker y gateways de mensajería) que aloja y opera al agente de forma continua.

    ¿Por qué la base de datos de persistencia es crítica en el arnés?

    Porque las APIs de inferencia en la nube no guardan historial de conversación real; son totalmente stateless. Sin una base de datos local sólida en el arnés que registre el estado de las sesiones y variables ante cualquier reinicio de servidor, tu agente sufrirá de amnesia agéntica, perdiendo el hilo de su tarea en curso.

    ¿Se pueden integrar políticas de seguridad en el arnés?

    Sí, de hecho es el lugar ideal para hacerlo. Al centralizar el control de ejecución en el arnés, puedes añadir filtros de censura de salida, restringir accesos a carpetas mediante permisos del sistema de archivos y bloquear comandos de consola peligrosos mediante aprobaciones manuales del usuario.

    ¿El arnés agéntico depende de un modelo específico?

    No. Un arnés bien diseñado debe estar totalmente desacoplado del backend de inferencia. Al utilizar APIs compatibles con la interfaz de OpenAI o Anthropic, puedes conectar tu arnés a un servidor local de oMLX en Mac, a Ollama en local, o a modelos propietarios en la nube (como Claude 3.5 o GPT-4) sin reescribir la lógica operativa de tu sistema.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Claude Code: Ahorra 90% en tokens con este truco

    Claude Code: Ahorra 90% en tokens con este truco

    Ayer estaba revisando la factura de mi cuenta de Anthropic. Estaba utilizando la nueva CLI de Claude Code para refactorizar un proyecto local y noté que los costes se estaban disparando de forma absurda. Cada pequeña pregunta rápida de "sí" o "no" me estaba costando miles de tokens de entrada completos.

    ¿Cómo era posible? El sistema de Prompt Caching de Anthropic promete ahorrar hasta un 90% de los costes en contextos de conversación repetidos y largos.

    Al investigar la consola de depuración por debajo, descubrí al culpable. Un comportamiento por defecto en el diseño de Claude Code que destruye el caché en cada turno.

    Hoy te quiero explicar el truco de la bandera exclude-dynamic-system-prompt-sections, cómo configurarla en tu máquina y por qué te ahorrará cientos de dólares en tu factura de API de Claude.


    Por qué Claude Code rompe el Prompt Caching por defecto

    Para que el caché de prompts de Claude funcione, la IA necesita que los primeros bloques de texto de tu conversación (el System Prompt y los primeros archivos cargados) sean exactamente idénticos entre una llamada y la siguiente. Si cambia una sola letra o espacio en el System Prompt, el motor de Anthropic invalida el caché y tiene que volver a leer y procesar toda la conversación desde cero, cobrándote la tarifa completa.

    Por defecto, Claude Code intenta ser extremadamente inteligente. Cada vez que le haces una pregunta en la terminal, el CLI inyecta datos dinámicos de tu entorno directamente dentro del System Prompt:

    • La fecha y hora exacta actual (cambia cada segundo).
    • Tu directorio de trabajo actual (cambia si navegas carpetas).
    • El estado de tu repositorio de Git (cambia con cada commit o archivo modificado).

    Como esta información varía constantemente, tu System Prompt es distinto en cada interacción. El resultado: un 0% de efectividad de caché y una factura inflada de tokens de entrada.


    La Solución: Excluir las Secciones Dinámicas

    Para solucionar este desperdicio de tokens, Anthropic introdujo la bandera --exclude-dynamic-system-prompt-sections.

    Cuando ejecutas Claude Code con este parámetro, el CLI modifica su comportamiento arquitectónico: extrae toda la información dinámica y variable (fecha, git status, directorio) del System Prompt y la inyecta al final del User Message (el mensaje que tú escribes).

    De este modo:

    1. El System Prompt queda estático y congelado en la memoria de la API de Anthropic.
    2. Tu tasa de acierto de caché de prompts sube a prácticamente el 100%.
    3. Tus respuestas locales tardan milisegundos en lugar de segundos porque el modelo no tiene que volver a re-procesar los archivos del repositorio en cada turno.

    Cómo configurarlo en tu entorno de desarrollo

    Tienes dos formas de aplicar este hack de ahorro de costes según tu preferencia:

    Opción 1: Ejecución manual en consola

    Simplemente añade la bandera al arrancar la herramienta en tu terminal:

    claude --exclude-dynamic-system-prompt-sections
    

    Opción 2: Configuración persistente (Recomendado)

    Para no tener que escribir la bandera en cada sesión, puedes configurarla por defecto en tu archivo de preferencias global de Claude Code ubicado en ~/.claude/settings.json (o crearlo si no existe):

    {
      "excludeDynamicSystemPromptSections": true
    }
    

    Este tipo de optimizaciones de costes de API a bajo nivel y sintonía fina de prompts es la que enseñamos a dominar en el curso de Construye con IA para evitar sorpresas en facturación. Como vimos en nuestro post sobre desarrollo con IA y Loop Engineering, optimizar las APIs es crucial para mantener un runtime agéntico económico en producción, técnica que aplicamos a fondo en el nuevo curso de Hermes Agent.


    Conclusión: Controla tus llamadas

    Las herramientas agénticas de consola son increíblemente productivas, pero delegar el control de la API sin vigilar cómo se consumen los tokens es un error costoso. Al aplicar la exclusión de prompts dinámicos, garantizas un flujo de desarrollo veloz, económico y optimizado bajo los estándares de caché nativos de Anthropic.

    Si estás utilizando Claude Code en tu día a día y quieres compartir trucos de optimización de costes y automatización con otros desarrolladores senior de nuestra comunidad, te espero en Dominicode Labs.


    Preguntas Frecuentes (FAQ)

    ¿Perderá capacidad Claude Code al quitar esta información del System Prompt?

    No. El modelo sigue recibiendo exactamente la misma información (tu directorio actual, la fecha y el estado de git). La única diferencia es el lugar donde se inyecta esa información dentro del JSON de la llamada a la API. Al estar en el mensaje del usuario, no interfiere con el bloque de caché superior.

    ¿Cuánto dinero real puedo ahorrar con este ajuste?

    En repositorios medianos a grandes (donde el contexto inicial de archivos y reglas de código puede ocupar más de 20.000 tokens), el ahorro puede superar el 80% o 90% en tokens de entrada. En lugar de pagar por procesar 20.000 tokens en cada pregunta, solo pagarás una pequeña tarifa de lectura inicial y céntimos de uso de caché en los turnos posteriores.

    ¿Por qué Claude Code no tiene esta opción activada por defecto?

    Porque prioriza la experiencia de usuario inicial sobre el coste de API. Inyectar metadatos en el System Prompt garantiza que la IA entienda el contexto del sistema de archivos desde la primera palabra de forma muy estricta, aunque resulte ineficiente a nivel financiero para el desarrollador.

    ¿Se puede usar este truco en otros editores como Cursor?

    Cursor gestiona su propio sistema de prompt caching y almacenamiento de contexto de forma interna mediante indexación de archivos (embeddings). Este ajuste es exclusivo de la interfaz de consola de Claude Code (CLI oficial de Anthropic).


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Qué es un agente de IA (y qué no): guía para subir de nivel

    Qué es un agente de IA (y qué no): guía para subir de nivel

    Hace tres semanas un suscriptor me pasó el repositorio de su primer agente. Orgulloso, y con motivos: cuatrocientas líneas limpias, herramientas declaradas, tool calling funcionando.

    Le hice una sola pregunta. ¿Cuántas veces llama al modelo cuando lo ejecutas?

    Siempre tres. Las mismas tres, en el mismo orden, pasara lo que pasara.

    Eso no era un agente. Era un pipeline con tres llamadas a un LLM dentro. Y funcionaba perfectamente, que es lo que vuelve incómoda la conversación. Porque la respuesta habitual a qué es un agente de IA —"un sistema autónomo que usa herramientas para cumplir un objetivo"— describe igual de bien su script que Claude Code.

    Y no son la misma categoría de software.

    La diferencia no es semántica: decide qué tienes que instrumentar antes de dejarlo suelto y qué ocurre el día que se equivoca a las tres de la mañana.

    Aquí va la definición operativa que uso: un test que aplicas a tu código en dos minutos, la anatomía real, los grados de autonomía y —lo más importante— cuándo no deberías montar un agente.


    Resumen rápido

    • Un agente de IA es un sistema donde el modelo decide el flujo de control: qué acción viene después y cuántas. No lo define la autonomía ni el uso de herramientas.
    • El test: si el número de llamadas al modelo es fijo y puedes dibujar el camino antes de ejecutar, es un workflow con un LLM dentro. Y suele ser la opción correcta.
    • La anatomía real son cinco piezas: objetivo, política de decisión, herramientas, contexto y verificador con criterio de parada. La quinta es la que casi nadie monta.
    • Un límite de iteraciones no es un criterio de parada. Es un timeout.
    • Cruzar la línea es binario; lo que hay al otro lado, no. Hay grados de autonomía, y cada grado exige instrumentación distinta. Los incidentes suelen ser un grado 3 con instrumentación de grado 1.
    • No son agentes: un chatbot con herramientas, un pipeline determinista con un nodo de IA, un RAG clásico.

    Qué es un agente de IA: la definición que sí se puede verificar

    Un agente de IA es un sistema en el que el modelo decide el flujo de control: qué acción se ejecuta a continuación, con qué argumentos y cuándo parar. No lo define la autonomía ni el uso de herramientas, sino quién elige el siguiente paso.

    No es el que usa herramientas. No es el que parece inteligente. Es el que decide qué pasa después.

    La definición de marketing —"autónomo", "usa herramientas", "cumple objetivos"— es inútil precisamente porque no excluye nada: bajo ese paraguas cabe un cron con un prompt dentro.

    Anthropic lo formuló bien en Building effective agents (diciembre de 2024): los workflows son "sistemas donde los LLM y las herramientas se orquestan mediante caminos de código predefinidos"; los agentes, "sistemas donde los LLM dirigen dinámicamente sus propios procesos y su uso de herramientas, manteniendo el control sobre cómo realizan las tareas".

    Traducido a algo que puedas usar hoy: el diagrama de flujo de un workflow existe antes de ejecutarlo. El de un agente no existe hasta que termina.

    Si puedes dibujar en una pizarra todo lo que va a pasar, no has construido un agente. Has construido un programa que llama a un modelo. Que, insisto, suele ser mejor decisión.


    El test: ¿agente o workflow con un LLM dentro?

    Tres preguntas. Se contestan mirando tu código, no leyendo documentación.

    1. ¿El número de llamadas al modelo es fijo? Si siempre son tres, es un workflow.
    2. ¿La salida de una herramienta cambia cuál se llama después? Si el orden lo escribiste tú, es un workflow.
    3. ¿Hay un bucle del que el modelo puede decidir no salir? Si no hay bucle, no hay agente.

    Abre el archivo, busca la llamada al modelo y mira qué tiene alrededor. Esto es un workflow:

    // Workflow: el camino está escrito. Siempre estos tres pasos, en este orden.
    const intencion = await modelo.clasificar(email)
    const resumen = await modelo.resumir(email)
    const respuesta = await modelo.redactar(intencion, resumen)
    
    await enviar(respuesta)
    

    Y esto es un agente:

    // Agente: el modelo elige la siguiente acción con lo que acaba de observar.
    const mensajes: Mensaje[] = [{ role: 'user', content: objetivo }]
    let pasos = 0
    
    while (pasos++ < LIMITE) { // LIMITE es un timeout, no un criterio de parada
      const decision = await modelo.responder({ mensajes, tools })
    
      if (decision.tipo === 'final') break // ojo: aquí para el modelo, no un verificador
    
      const observacion = await ejecutar(decision.tool, decision.args)
      mensajes.push(decision, observacion) // lo observado entra en la siguiente decisión
    }
    

    Toda la diferencia está en una palabra: while. En el primero, un await va detrás de otro y el orden lo pusiste tú. En el segundo hay un bucle, y dentro del bucle el que elige es el modelo.

    Fíjate en los dos comentarios que he dejado en el segundo bloque, porque ese ejemplo todavía está incompleto a propósito: para cuando el modelo dice que ha terminado, y eso no es un criterio de parada. Volvemos a ello en la anatomía.

    Si en tu repositorio no aparece ese bucle —ni explícito, ni dentro de la librería que uses—, no tienes un agente. Y si el while solo reintenta la misma llamada cuando falla la red, tampoco: eso es un retry.

    Ese bucle tiene nombre propio, fases y modos de fallo documentados: lo desmonté pieza a pieza en Agentic loop: el mecanismo detrás de los agentes de IA.


    La anatomía real: cinco piezas, y casi nadie monta la quinta

    Un agente de IA se compone de cinco piezas: objetivo, política de decisión, herramientas, contexto y verificador con criterio de parada. Las cuatro primeras salen en cualquier tutorial. La quinta es la que separa una demo de un sistema.

    Pieza Qué es Qué pasa si falta
    Objetivo El resultado esperado, no la instrucción Optimiza para parecer útil, no para terminar
    Política de decisión El modelo eligiendo la siguiente acción No hay agente: hay script
    Herramientas La superficie de acción sobre el mundo real Razona precioso y no cambia nada
    Contexto Lo que sabe en cada iteración Repite trabajo hecho y se contradice
    Verificador y criterio de parada La señal que dice si el trabajo está bien Para cuando cree que ha acabado

    Estas cinco son las piezas del agente. El andamiaje que lo envuelve —registro de herramientas, guardrails, gestión de contexto— es otra capa distinta, y la desglosé en qué es un agent harness.

    Las herramientas son donde más gente se pasa de frenada: doce tools disponibles, descripciones ambiguas y un modelo eligiendo mal. No es fallo del modelo, es fallo de diseño, y lo desarrollé en cómo evitar que los agentes elijan mal sus herramientas.

    El contexto arruina ejecuciones largas en silencio. Qué recuerda entre iteraciones, qué recuerda entre sesiones y qué debe olvidar es arquitectura, no implementación: las cuatro capas del modelo CoALA están en implementación de memoria en agentes de IA.

    Y llegamos a la quinta, que es donde está el problema de verdad.

    Un límite de iteraciones no es un criterio de parada

    Casi todo el mundo cree que tiene verificador porque ha escrito esto:

    while (pasos < 10) { /* ... */ }
    

    Eso es un timeout. Dice cuándo dejar de gastar dinero. No dice nada sobre si el trabajo está bien hecho.

    El criterio de parada es un comando o una función que responde sí o no sin que intervenga tu criterio. Los tests en verde. El typecheck limpio. Un eval puntuado contra casos conocidos. Un schema que valida la salida.

    Y aquí se resuelve la tensión que quizá te haya chirriado antes: dije que el modelo decide cuándo parar, y ahora digo que el criterio tiene que ser externo. Las dos cosas. El modelo propone que ha terminado; el verificador confirma o lo devuelve al bucle. Un agente que se autoevalúa no tiene criterio de parada: tiene una opinión.

    La diferencia se nota el día que el agente sale del bucle en la iteración 4 y te devuelve algo roto. Salió porque el modelo dijo "listo", y el modelo dijo "listo" porque no había nada delante que le llevara la contraria.

    Un agente sin verificador no es autónomo. Es no supervisado, que es otra cosa. Montar esa señal es lo que separa una demo de un sistema, y está en evaluaciones automatizadas para agentes de IA.

    El verificador tiene un hermano que se olvida igual de rápido: el perímetro. Contenedor aislado, rama nueva, credenciales de solo lectura. Nunca ejecución de código generado sobre el servidor real. Cuanta más autonomía das, más estrecho tiene que ser el perímetro, no al revés.


    Los grados de autonomía: cuánto decide el modelo

    El test de arriba te dice si has cruzado la línea. No te dice cuánto la has cruzado, y eso es exactamente lo que decide qué tienes que montar debajo. Hay cinco grados, del 0 al 4, y cada uno exige una instrumentación distinta.

    La escala que viene es mía, no un estándar de la industria. La uso para decidir qué instrumentación exige cada salto antes de darlo. Si te sirve, róbala; si no, calibra la tuya y quédate con la última columna.

    Grado Lo decide tu código Lo decide el modelo Ejemplo típico Mínimo que exige
    Grado 0 El flujo y la ejecución completa El texto que devuelve Chat, autocompletado Nada. El bucle eres tú
    Grado 1 Qué acciones existen y cuándo se ejecutan Cuál encaja en este caso Tool calling de un salto, routing Validación de argumentos
    Grado 2 El catálogo y el permiso de cada acción El orden y cuántas hacen falta Agente con aprobación por acción Un humano revisando cada acción antes de ejecutarla, no el resumen final
    Grado 3 El perímetro y el criterio de parada El plan completo dentro del perímetro Un agente arreglando un test en CI Verificador automático, sandbox y trazas
    Grado 4 Solo el perímetro El plan y sus propias herramientas Self-improving loop Todo lo anterior más evals de regresión

    La línea del test está entre el grado 1 y el grado 2. Por debajo, el orden lo escribiste tú: workflow. Del grado 2 hacia arriba, el orden lo decide el modelo, y ahí empieza el agente. Ser agente es sí o no. Cuánta cuerda le das, no.

    Mira solo la última columna. Es la única que importa de verdad.

    Subir de grado no es cambiar de modelo ni instalar un framework con la palabra "agent" en el nombre. Es tener montado lo que ese grado exige antes de subir.

    El incidente típico no lo provoca un agente malo. Lo provoca un grado 3 corriendo con instrumentación de grado 1: sin trazas para reconstruir qué decidió, sin sandbox y sin señal automática de si aquello estaba bien. Qué capturar de cada ejecución para poder auditarla está en cómo monitorear agentes de IA en producción.

    El grado 4 es el techo actual y el más malinterpretado. Un agente que escribe sus propias herramientas al detectar una tarea que no sabe hacer no es magia: es un bucle que compila, testea en aislamiento y solo incorpora la habilidad si los tests pasan. Lo tienes entero en Self-Improving Loop.

    Una vez sabes que has cruzado la línea, la pregunta útil ya no es "¿esto es un agente?". Es "¿en qué grado corre y qué he puesto debajo?"


    Qué no es un agente, aunque lo llamen así

    Un chatbot con herramientas. Buscar en la web y devolverte el resultado sigue siendo un salto único. La prueba es si puede reintentar por su cuenta a partir de lo que acaba de observar. Si no puede, es un chat con herramientas conectadas.

    Un pipeline determinista con un nodo de IA. Un flujo de n8n, Zapier o Make con una caja que dice "AI" es un workflow: el camino está dibujado en el canvas y el modelo rellena huecos. Cuando un paso falla, el flujo se rompe; no reformula la estrategia.

    Un RAG clásico. Recuperar, inyectar en el prompt, responder. Camino fijo, una llamada. Se vuelve agéntico solo cuando el modelo decide si vuelve a buscar, con qué query y cuándo parar. Ese "decide" es toda la diferencia.

    Y una que se ha puesto de moda: más agentes no es más agente. Cinco LLM encadenados suelen ser un workflow caro con pérdida de contexto en cada salto. Cuándo compensa y cuándo es autolesión lo analicé en cuándo usar multi-agente sin orquestador.

    Ninguna de las cuatro es peor que un agente. Suelen ser mejores: más baratas, más rápidas y depurables. Cuando un workflow falla, sabes en qué paso.


    Cuándo NO deberías montar un agente

    Para que compense tienen que darse tres condiciones. Las tres. No dos de tres.

    Que exista una señal automática de si el trabajo está bien. Si el único verificador eres tú leyendo el resultado, no has delegado el bucle: lo has movido a tu bandeja de entrada.

    Que el camino no sea siempre el mismo. Esta es la que más se ignora. Si el flujo es idéntico en el 95% de las ejecuciones, estás pagando a un modelo por redescubrir cada vez un orden que ya conoces. Escríbelo en código. Anthropic, en el artículo que cité arriba, recomienda buscar siempre la solución más simple posible y añade que eso "puede significar no construir sistemas agénticos en absoluto".

    Y si tu duda de fondo es cuál de tus tareas merece un agente y cuál no, esa clasificación —tarea por tarea— está en cómo clasificar tareas de desarrollo para delegarlas a la IA y, con los números de coste al lado, en IA generativa vs IA agéntica.

    Que el error sea reversible dentro del perímetro. Migraciones sobre datos de producción, borrados, despliegues sin rollback, correos a clientes reales. Ahí no se sube a grado 3: ahí el modelo propone y tú apruebas, que es para lo que existe el grado 2.

    Falla una de las tres y la respuesta correcta es un workflow. No es una derrota: es ingeniería.


    La ruta: por dónde empezar y cómo subir de nivel

    Con esto claro, aprender agentes deja de ser una lista de herramientas y pasa a ser una progresión de grados.

    Etapa 1 — Usa un agente antes de construir uno (grados 0-1)

    Trabaja unas semanas con un harness ya hecho —Claude Code, Codex CLI, el que prefieras— sobre tu repositorio real. No para aprender la herramienta: para ver de primera mano dónde decide mal y qué información le faltaba cuando lo hizo. Eso es lo que después no sabrás diseñar si nunca lo has sufrido.

    Y haz dos cosas desde el primer día, porque cambian el resultado más que el modelo que elijas.

    Escribe el contrato: un CLAUDE.md en la raíz convierte al agente de invitado que improvisa en ejecutor con reglas explícitas, y cómo redactarlo está en CLAUDE.md: el contrato entre tú y el agente.

    Y especifica antes de dejarle editar, porque un agente al que le pides que programe a ciegas rellena con invención todo lo que no escribiste. La metodología está en Spec-Driven Development: evita el caos de la IA, y completa, con plantillas y flujo de trabajo, en el libro de Spec-Driven Development.

    Etapa 2 — Construye uno pequeño de verdad (grado 2)

    No un framework: un bucle. Un objetivo, dos herramientas, argumentos validados y un criterio de parada que no sea un contador. Doscientas líneas enseñan más que cualquier tutorial, porque ves dónde se rompe.

    Valida los argumentos con un schema desde la primera línea: la frontera entre el texto probabilístico del modelo y tus tipos tiene que ser explícita, y es lo que enseño en el curso de Zod. El stack mínimo completo —SDK, Zod y un bucle explícito— está en construye un agente de IA en TypeScript.

    Cuando quieras que esas herramientas dejen de estar acopladas a tu código y las consuma cualquier cliente compatible, entra MCP: el recorrido completo, servidor y agente incluidos, está en cómo construir un agente de IA y su MCP server paso a paso.

    Si prefieres hacer este salto acompañado y llegar de la idea a un producto funcionando, es el camino del curso Construye con IA.

    Etapa 3 — Sube al grado 3 con la instrumentación por delante

    Aquí se separa el proyecto de fin de semana del sistema que corre solo. Ya sabes qué exige el grado 3, así que la pregunta no es cuáles son las piezas: es en qué orden se montan. Va este, y el orden importa.

    Primero el sandbox. Es la única que te protege del peor día, y es la más barata de todas: un contenedor y una rama nueva. Montarla la última es como ponerse el cinturón al llegar.

    Después las trazas. Sin ellas no puedes depurar nada de lo que viene después, porque no sabrás qué decidió el agente ni con qué información.

    Luego el verificador. Ahora sí puedes construirlo, porque las trazas te enseñan en qué se equivoca de verdad y contra qué merece la pena verificar.

    Y por último los evals. Son el verificador aplicado a un conjunto de casos conocidos, así que llegan cuando ya tienes uno.

    La memoria persistente no está en esa lista a propósito: es una optimización de coste y de continuidad, no una condición de seguridad. Se monta cuando el agente ya corre bien, no antes. Ese error de orden —memoria elegante y cero trazas— lo he visto más veces de las que me gustaría, y es también el que describo en loop engineering.

    Y cuando quieras montar esto como disciplina profesional y no como proyecto suelto, el roadmap de carrera está en qué es un Agentic Engineer y cómo convertirte en uno.


    Lo único que tienes que hacer hoy

    Abre el repositorio de eso que llamas agente y busca la llamada al modelo.

    Si alrededor no hay un bucle donde la salida de una herramienta cambia la siguiente decisión, tienes un workflow. Deja de intentar convertirlo en agente y hazlo mejor workflow: será más barato y no te despertará de madrugada.

    Si sí lo hay, contesta la segunda pregunta: ¿qué señal automática le dice que ha terminado? Si la respuesta es un número de iteraciones, acabas de encontrar el trabajo de esta semana. Y es el que más te va a rentar.

    Si quieres el esqueleto ya montado para no empezar de cero —bucle, herramientas y criterio de parada—, lo he empaquetado gratis en el Hermes Agent Kit.

    Y si prefieres discutir arquitecturas concretas con gente que ya tiene agentes corriendo en producción, te espero en Dominicode Labs.


    Preguntas frecuentes

    ¿Qué es un agente de IA exactamente?

    Un agente de IA es un sistema en el que el modelo decide el flujo de control: qué acción se ejecuta a continuación, con qué argumentos y cuándo detenerse. No lo define la autonomía ni el uso de herramientas, sino quién elige el siguiente paso. Si el orden de las acciones está escrito en tu código, tienes un workflow con un LLM dentro. Si ese orden se decide en tiempo de ejecución a partir de lo que el sistema acaba de observar, tienes un agente.

    ¿Cuál es la diferencia entre un agente de IA y un workflow con un LLM?

    El diagrama de flujo. El de un workflow existe antes de ejecutarlo, porque los caminos están predefinidos en código; el de un agente no existe hasta que la ejecución termina. Se comprueba con dos señales: si el número de llamadas al modelo es fijo, es un workflow; si la salida de una herramienta puede cambiar cuál se llama después, es un agente. El workflow no es una versión inferior: es más barato, más rápido y más fácil de depurar.

    ¿Un chatbot con herramientas es un agente de IA?

    No mientras no cierre el bucle. Un chatbot que busca en la web y te devuelve el resultado ejecuta un salto único: no comprueba si lo que obtuvo resuelve el objetivo ni cambia de estrategia cuando no lo resuelve. La prueba está en el código, no en la interfaz: si no existe una iteración en la que la observación de una herramienta determine cuál se llama después, tienes un chat con herramientas conectadas.

    ¿ChatGPT o Claude son agentes de IA?

    Por sí solos no: son modelos servidos tras una interfaz de chat, y ahí el bucle lo cierras tú al leer la respuesta y escribir la siguiente instrucción. Se convierten en la política de decisión de un agente cuando los envuelves en un sistema que ejecuta sus llamadas a herramientas y le devuelve el resultado para que decida el siguiente paso: eso es lo que hacen Claude Code o Codex CLI. El agente no es el modelo; es el modelo más el bucle, las herramientas y el criterio de parada.

    ¿Qué ejemplos reales de agentes de IA hay hoy?

    Los más maduros en 2026 son los agentes de programación que corren sobre un repositorio: Claude Code, Codex CLI de OpenAI, Cursor en modo agente y Gemini CLI. Todos comparten la misma estructura: un bucle que lee ficheros, ejecuta comandos, observa la salida y decide la siguiente acción, con los tests como criterio de parada. Fuera del código, los casos que funcionan son los que tienen verificación automática: triaje de incidencias, migraciones de datos validadas contra un schema y control de calidad de contenido.

    ¿Necesito LangChain o un framework de agentes para construir el mío?

    No. El núcleo de un agente son unas doscientas líneas: un bucle, un catálogo de herramientas con argumentos validados, el historial de observaciones y un criterio de parada. Escribirlo a mano una vez enseña más que LangChain, Mastra o el Vercel AI SDK juntos, porque ves exactamente dónde se rompe. El framework empieza a compensar después: cuando necesitas persistencia entre ejecuciones, orquestación de varios procesos o trazabilidad estándar.

    ¿Por qué un límite de iteraciones no sirve como criterio de parada?

    Porque es un timeout: evita que el agente gaste tokens sin fin, pero no dice nada sobre la calidad del resultado. El criterio de parada es una señal externa al modelo que responde sí o no sobre si el objetivo está cumplido: tests en verde, typecheck limpio, un schema que valida la salida o un eval puntuado. Sin esa señal, el agente termina cuando cree que ha terminado, y esa creencia no se puede auditar.

    ¿Cuándo no conviene usar un agente de IA?

    Cuando falla alguna de estas tres condiciones. Que exista una señal automática capaz de decir si el trabajo está bien hecho sin que lo revises tú. Que el camino no sea siempre el mismo, porque si el flujo es idéntico en casi todas las ejecuciones estás pagando por redescubrir un orden que ya conoces. Y que el error sea reversible: sobre datos de producción, borrados o despliegues sin rollback, el modelo propone y tú apruebas.

    ¿Es lo mismo un agente de IA que un sistema multi-agente?

    No, y encadenar varios modelos no hace el sistema "más agéntico". Un sistema multi-agente reparte el trabajo entre varias instancias con roles distintos, y cada salto pierde contexto, suma latencia y multiplica el coste. Muchas veces lo que se ha modelado como un segundo agente debería haber sido una herramienta del primero. Empieza con un solo agente y varias herramientas.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Clasificar tareas con IA: guía de supervivencia para developers

    Clasificar tareas con IA: guía de supervivencia para developers


    status: borrador
    title: "Clasificar tareas con IA: guía de supervivencia para developers"
    slug: clasificar-tareas-con-ia-desarrollo-software
    excerpt: "Aprende a clasificar tareas con IA en desarrollo de software. Descubre cómo dividir tareas seriales y paralelas para programar de forma profesional sin bugs."
    keywords:

    • clasificar tareas con IA
    • tareas seriales vs paralelas software
    • desarrollo guiado por IA
    • agentes de inteligencia artificial

    El martes pasado perdí cuatro horas intentando que Claude Code (v0.2.0, corriendo con el modelo Claude 3.5 Sonnet) reescribiera un módulo de pagos entero de un solo golpe. El resultado fue un bucle infinito de errores de tipado en TypeScript que me enseñó la importancia de clasificar tareas con IA antes de ponerme a tirar código.

    Si tratas a un LLM como a un junior todoterreno sin entender qué puede resolver en paralelo y qué requiere tu intervención directa, vas a perder más tiempo depurando que programando. Para construir software real con inteligencia artificial, necesitas dividir tu backlog bajo un criterio muy simple: estructura mental vs. ejecución de código.

    Aprender a clasificar tareas con IA es lo que separa a los programadores que sufren de "vibe coding hangover" de los que construyen aplicaciones mantenibles y escalables en producción.


    ¿Por qué debes clasificar tareas con IA?

    Cuando automatizas flujos con agentes, la mayoría de los desarrolladores cometen el error de meter todo en una gran cadena secuencial. No entienden cómo fluyen los datos y la memoria dentro de un modelo de lenguaje.

    Los LLMs tienen una ventana de contexto limitada y, a medida que la conversación se alarga, sufren de pérdida de atención. Si el modelo comete un pequeño error en el paso 1 y continúas la secuencia sin corregirlo, ese error se propaga y amplifica en los pasos 2, 3 y 4.

    Por eso, separar las tareas no es una cuestión de organización escolar: es una necesidad de arquitectura técnica para evitar que el contexto del modelo se contamine.


    Tareas seriales vs. paralelas: El cuello de botella del contexto

    Para delegar a la IA de forma óptima, debes entender la diferencia entre dos tipos de flujos de trabajo:

    A. Tareas Seriales (Secuenciales)

    Son aquellas donde cada paso depende estrictamente del resultado del paso anterior. No puedes avanzar si el paso previo no está validado.

    • Ejemplo: Diseñar un backend con NestJS. No puedes escribir los controladores ni los queries del ORM hasta que la estructura de tablas SQL esté completamente definida y validada.
    • Workflow: Exigen pasos secuenciales cortos con validaciones humanas intermedias. Necesitas un modelo integrado en tu IDE (como Cursor o Claude Code) operando con supervisión activa. Tú guías el flujo, pruebas cada paso en local y decides el siguiente movimiento.

    B. Tareas Paralelas (Independientes)

    Son tareas independientes que no comparten estado entre sí y se pueden ejecutar en entornos aislados de forma simultánea.

    • Ejemplo: Traducir archivos i18n de traducción, documentar funciones utilitarias independientes o escribir tests unitarios de Jest para componentes que no tienen acoplamiento entre sí.
    • Workflow: Este es el territorio ideal de los agentes autónomos que corren en segundo plano. Puedes lanzar múltiples llamadas paralelas a la API y resolver el backlog en segundos mientras tú te enfocas en diseñar la lógica del negocio.

    A continuación, puedes ver una comparativa clara de cómo enfocar cada tipo de tarea:

    Característica Tareas Seriales (Secuenciales) Tareas Paralelas (Independientes)
    Dependencia Alta (Paso B necesita el output de A) Nula o muy baja (Módulos aislados)
    Workflow de IA Interactivo (Human-in-the-loop) Agentes autónomos en background
    Ejemplo práctico Depuración de bugs complejos, diseño de APIs Escribir tests unitarios, documentación
    Riesgo de desvío Alto (los errores de contexto se acumulan) Bajo (tareas acotadas y repetitivas)
    Intervención humana Constante (validación paso a paso) Al inicio (spec) y al final (code review)

    Cómo clasificar tareas con IA: lo que delegas y lo que no

    La IA es un ejecutor brutal de especificaciones cerradas. Si le das reglas claras y un entorno acotado, escribirá código mejor y más rápido que tú. Esto es lo que llamamos el "desarrollo guiado por IA".

    Para flujos secuenciales complejos, la clave está en fragmentar el código. No le pidas al modelo "escribe el endpoint de cobro con Stripe entero". En su lugar, fragméntalo en una secuencia controlada:

    // Paso 1: Pídele que defina la interfaz de datos estrictamente
    interface PaymentPayload {
      amount: number;
      currency: 'USD' | 'EUR';
      token: string;
    }
    
    // Paso 2: Una vez validada la interfaz, pídele implementar el validador
    function validatePayment(payload: PaymentPayload): boolean {
      return payload.amount > 0 && payload.token.length > 0;
    }
    

    Qué delegar a la IA (Ejecución y Boilerplate)

    • Scaffolding: Configuración de herramientas, setup de linters, inicialización de módulos.
    • Refactoring menor: Traducir funciones, migrar código JavaScript legacy a TypeScript clásico.
    • Tests y Documentación: Tareas repetitivas que consumen tiempo y tienen baja ambigüedad.

    Qué NUNCA debes delegar al modelo (Criterio y Dirección)

    • Decisiones de arquitectura: Decidir si tu base de datos debe ser relacional, si necesitas microservicios, o qué abstracción introducir hoy para no bloquear el desarrollo en 6 meses. La IA optimiza a nivel local, pero no ve a largo plazo.
    • Comprensión del negocio: Qué le importa realmente al usuario y qué tradeoffs valen la pena asumir.

    Para evitar que tu proyecto se desvíe, yo utilizo una metodología de diseño de especificaciones antes de tocar código. En el Libro SDD (Leanpub) explico cómo escribir especificaciones claras que los modelos de lenguaje entienden a la perfección y ejecutan a la primera.


    El loop humano: Tú eres el compilador final

    La automatización no significa que el programador desaparezca. Al contrario, la evolución natural del programador tradicional, como vimos en nuestro post sobre loop engineering y la evolución de la IA, exige que pases de escribir código a orquestar sistemas que escriben código.

    Tu rol ya no es picar código sin parar. Tu trabajo es diseñar la especificación, configurar los límites de los agentes (como las directivas en la documentación de Claude Code de Anthropic), y actuar como el control de calidad senior que decide qué entra a producción y qué se descarta.

    Esto es parte de lo que explico en mi artículo sobre el stack de IA agentica en 2026, donde analizamos cómo los ingenieros senior multiplican su productividad manejando subagentes independientes para tareas aisladas.

    Si quieres dominar este flujo y aprender a estructurar proyectos reales que funcionen con agentes y Claude Code, te recomiendo revisar el Curso "Construye con IA" en Udemy. Es el paso a paso exacto que yo sigo para lanzar productos sin perder la cabeza con bugs infinitos.

    Empieza hoy por lo básico: abre tu backlog y etiqueta cada tarea pendiente. Sabrás exactamente cuándo colaborar en vivo, cuándo lanzar un agente en background y cuándo apagar la pantalla y pensar tú solo.

    También puedes unirte a Dominicode Labs para acceder a herramientas, experimentos y una comunidad de desarrolladores seniors que están construyendo el futuro del software con inteligencia artificial aplicada de verdad.


    Preguntas frecuentes

    ¿Cómo clasificar tareas con IA en seriales o paralelas?

    Pregúntate si el output de un paso es obligatorio para que el siguiente empiece a procesarse. Si la respuesta es sí (como definir el esquema SQL antes de escribir el ORM), la tarea es serial y secuencial. Si las tareas pueden ejecutarse en entornos independientes sin afectarse mutuamente (como escribir tests de archivos diferentes), son paralelas.

    ¿Por qué los modelos de IA fallan en las tareas seriales largas?

    A medida que el prompt y la conversación se alargan, el modelo sufre de pérdida de atención (needle in a haystack) y alucinaciones. Si el paso 1 tiene un pequeño error de interpretación, ese error se arrastra y amplifica en los pasos siguientes, destruyendo el resultado final. La clave es fragmentar el proceso en prompts individuales.

    ¿Se puede automatizar al 100% el desarrollo de software con agentes de IA?

    No en aplicaciones de producción complejas. Los agentes actuales destacan implementando código bajo especificaciones acotadas. Sin embargo, la toma de decisiones de negocio, el diseño de la arquitectura general y la integración de APIs de terceros siguen requiriendo la supervisión y validación de un programador humano experimentado.

    ¿Qué herramientas son mejores para ejecutar tareas paralelas con LLMs?

    Para flujos paralelos de volumen (como traducción o análisis de código masivo), las APIs de Claude o OpenAI conectadas a scripts locales son la opción más rápida y económica. Para desarrollo interactivo en local y tareas seriales complejas que requieren explorar el workspace, herramientas como Claude Code o entornos basados en agentes autónomos son ideales.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.