En el post anterior dejamos una pregunta muy específica abierta: qué pasa exactamente cuando el agente decide usar una herramienta. Ya sabemos que hay un loop. Ya sabemos que en cada vuelta el sistema elige una acción. Pero no abrimos la acción en sí.
Eso es lo que toca ahora.
Y la respuesta tiene una parte contraintuitiva que vale la pena decir desde el principio:
cuando Claude Code “usa una tool”, el modelo no ejecuta nada.
Lo pide.
Esa distinción parece pequeña. No lo es.
El modelo no ejecuta. Emite una solicitud.
Cuando el modelo decide que necesita leer un archivo, no abre el archivo.
Lo que hace es producir una salida estructurada que dice, en esencia: quiero usar esta herramienta, con estos parámetros. Así se ve una solicitud real de Claude Code:
{ "type": "tool_use", "id": "toolu_01Hy3k9mX2pL8vRqN4wTzA", "name": "read_file", "input": { "path": "src/auth/handleAuth.ts" }}Eso es todo lo que sale del modelo. No una acción. Una intención estructurada con un id para rastrear la respuesta.
El runtime recibe eso, abre el archivo, y devuelve el resultado vinculado al mismo id:
{ "type": "tool_result", "tool_use_id": "toolu_01Hy3k9mX2pL8vRqN4wTzA", "content": "export async function handleAuth(\n userId: string,\n token: string\n): Promise<Session> {\n const user = await db.users.findById(userId);\n if (!user) throw new AuthError('User not found');\n return createSession(user, token);\n}"}El tool_use_id es el hilo que conecta la solicitud con su resultado. El modelo no tiene que saber cómo se ejecutó — solo recibe el contenido y continúa.
Lo que viene después ocurre fuera del modelo. Hay otro componente del sistema — el runtime — que recibe esa solicitud y se encarga de convertirla en algo real.
flowchart LR M(["🧠 Modelo"]):::model --> E(["📤 Emite solicitud"]):::model E --> RV(["✔ Runtime valida"]):::runtime RV --> RX(["⚙ Runtime ejecuta"]):::runtime RX --> RR(["📥 Devuelve resultado"]):::runtime RR --> MI(["🧠 Modelo interpreta"]):::model MI --> O(["💬 Decide qué sigue"]):::output classDef model fill:#312e81,stroke:#818cf8,color:#e2e2f0,stroke-width:2px classDef runtime fill:#164e63,stroke:#22d3ee,color:#e2e2f0 classDef output fill:#14532d,stroke:#4ade80,color:#e2e2f0 linkStyle 1,2,3 stroke:#22d3ee,stroke-width:2px linkStyle 4,5 stroke:#818cf8,stroke-width:2px
El modelo aparece dos veces: primero emitiendo la solicitud, después interpretando el resultado. En el medio, el runtime hace el trabajo físico. Esa estructura no es un detalle de implementación. Es la arquitectura central del sistema.
La capa que traduce
Entre el lenguaje del modelo y la acción real existe una brecha. El modelo habla en intenciones. El sistema operativo habla en llamadas de sistema. El runtime es lo que cruza esa brecha en ambas direcciones.
Hacia afuera: toma la intención estructurada del modelo, la valida, la convierte en una operación real y la ejecuta.
Hacia adentro: toma el resultado crudo de esa operación y lo convierte en algo que el modelo pueda leer y usar en la siguiente vuelta.
flowchart LR MI(["🧠 Intención"]):::model RV(["✔ Valida"]):::runtime RE(["⚙ Ejecuta"]):::runtime W(["🌍 Filesystem / Shell"]):::world RF(["📋 Formatea"]):::runtime MR(["🧠 Interpreta"]):::model MI --> RV --> RE --> W --> RF --> MR classDef model fill:#312e81,stroke:#818cf8,color:#e2e2f0,stroke-width:2px classDef runtime fill:#164e63,stroke:#22d3ee,color:#e2e2f0 classDef world fill:#1c1917,stroke:#78716c,color:#a8a29e linkStyle 0,1 stroke:#22d3ee,stroke-width:2px linkStyle 2 stroke:#78716c,stroke-width:2px linkStyle 3,4 stroke:#818cf8,stroke-width:2px
La palabra clave aquí es traducción.
El modelo produce una intención. El runtime la traduce en una acción. El resultado de esa acción lo traduce de vuelta a algo que el modelo pueda leer. Ese ciclo de traducción es lo que convierte una tool de una idea dentro de un prompt en una capacidad real del sistema.
Chat vs. agente: dónde termina el lenguaje
Esta separación es también la diferencia más profunda entre un chat y un agente.
Un chat clásico vive enteramente dentro del lenguaje. Puede describir lo que haría si leyera un archivo. Puede imaginar el resultado de un comando. Puede producir texto que suena como si hubiera verificado algo.
Pero no verificó nada.
En un agente con tools reales, el sistema puede cruzar esa frontera. Ya no se queda imaginando. Puede decir: no voy a adivinar; voy a revisar.
| Chat | Agente | |
|---|---|---|
| Qué produce | Texto sobre el mundo | Solicitudes al runtime |
| Fuente del resultado | Entrenamiento + inferencia | Ejecución real |
| Puede equivocarse sobre hechos | Sí, sin saberlo | Solo sobre interpretación |
| Toca archivos, shell, APIs | No | Sí, a través del runtime |
| Verifica o imagina | Imagina | Verifica |
El modelo todavía decide todo lo que importa
Hasta aquí podría parecer que el modelo es pasivo — que solo emite JSON y el runtime hace el trabajo real.
No es así.
El runtime ejecuta. Pero el modelo decide:
- qué tool usar
- con qué parámetros llamarla
- qué significa el resultado que vuelve
- si eso es suficiente para responder o si necesita otra vuelta
flowchart LR
D1{{"¿Qué tool?"}}:::decision --> D2{{"¿Qué parámetros?"}}:::decision
D2 --> RT(["⚙ Runtime"]):::runtime
RT --> D3{{"¿Qué significa?"}}:::decision
D3 --> D4{{"¿Respondo o sigo?"}}:::decision
D4 -->|"Sigo"| D1
D4 -->|"Respondo"| R(["💬 Respuesta"]):::output
classDef decision fill:#1c1917,stroke:#f59e0b,color:#fbbf24
classDef runtime fill:#164e63,stroke:#22d3ee,color:#e2e2f0
classDef output fill:#14532d,stroke:#4ade80,color:#e2e2f0
linkStyle 4 stroke:#818cf8,stroke-width:2px,stroke-dasharray:5
linkStyle 5 stroke:#4ade80,stroke-width:2px
El runtime es una caja dentro de ese ciclo. Ejecuta lo que el modelo le pide. Pero las decisiones antes y después de esa caja pertenecen al modelo.
La relación no es modelo contra runtime. Es modelo para decidir, runtime para ejecutar.
Por qué esta separación importa
La división entre modelo y runtime podría parecer un detalle de ingeniería. Pero tiene consecuencias directas en tres cosas importantes.
Seguridad. El modelo puede solicitar leer un archivo fuera del directorio permitido. El runtime lo rechaza. Esa capa de permisos no existe dentro del modelo — vive en el runtime. El modelo no puede darse acceso a sí mismo.
Confiabilidad. El runtime puede validar el formato de los parámetros antes de ejecutar, reintentar si algo falla y limitar el alcance de una operación. El modelo no tiene que manejar esos casos — el runtime los absorbe.
Extensibilidad. Agregar una nueva tool al sistema no requiere re-entrenar el modelo. Basta con registrarla en el runtime y describirla correctamente. El modelo aprende a usarla a partir de la descripción, no de un nuevo ciclo de entrenamiento.
Lo que viene después
Ahora ya tenemos las tres piezas base de la arquitectura.
El primer post explicó que Claude Code no es un chat — es un sistema que trabaja. El segundo abrió el loop. Este abrió la acción dentro de ese loop.
Lo que todavía no miramos de cerca son las tools más concretas que tiene el sistema: el filesystem y la shell.
Esas dos tools definen la mayor parte de lo que un agente puede hacer dentro de un proyecto real. No como conceptos — como operaciones físicas sobre tu máquina.
Eso es lo que toca abrir después.