# Construye un equipo de agentes gobernado (y por que luego vas a querer KCP)

Un sistema multiagente no se vuelve seguro por tener mas agentes. Si cada agente puede decidir libremente que leer, que escribir y cuando actuar, solo conviertes un problema en cuatro. En este post construimos una demo de clinica con **4 agentes**, un **playbook declarativo**, una regla de autoridad **lowest-of**, escalado humano y un **ledger verificable**. No usamos las herramientas de Thor todavia: primero entendemos el mecanismo, luego veremos por que KCP hace falta de verdad.

Y te dejo el código para que puedas probarlo por ti mismo: [https://github.com/joedayz/governed-agents](https://github.com/joedayz/governed-agents)

## **El problema: mas agentes no significa mas control**

Cuando la gente escucha "multiagente", suele imaginar algo asi:

*   un agente busca contexto
    
*   otro decide
    
*   otro redacta
    
*   otro ejecuta
    

Suena ordenado. Pero si no hay reglas verificables, lo unico que hiciste fue repartir el caos.

La pregunta correcta no es:

> **"Cuantos agentes tengo?"**

La pregunta correcta es:

> **"Que puede hacer cada agente, con que autoridad, y como lo pruebo despues?"**

Ese es el objetivo de esta demo.

## **La demo: una clinica, una solicitud de cita, cuatro agentes**

Usamos un caso facil de entender para cualquier lector: un paciente escribe a la clinica, describe sintomas, y el sistema debe decidir que hacer.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/0d4e9cb9-5550-4cd6-b051-1fde12d66f57.png align="center")

La idea no es "tener varios LLMs". La idea es **separar responsabilidades**:

*   el `retriever` lee y resume
    
*   el `assessor` calcula hechos con reglas
    
*   el `drafter` redacta
    
*   el `executor` solo ejecuta dentro de un scope permitido
    

Dos usan modelo. Dos no.

Esa mezcla es importante: **no todo problema debe resolverse con un LLM**.

## **Arquitectura mental: playbook + caps + escalado humano**

Todo el comportamiento del equipo sale de un manifiesto (`knowledge.yaml`) y de un orquestador pequeno que hace una sola cuenta:

```yaml
efectivo = min(granted del paso, cap del agente)
brecha   = needs - efectivo
```

![](http://localhost:63342/markdownPreview/394426671//Users/josediaz/Projects/JoeDayz/kcp/equipo-agentes align="center")

Si la brecha es mayor que cero, el paso **escala a un humano**.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/a383890e-5119-4731-b6d2-fc39c9ac1429.png align="center")

No hay magia. No hay "el modelo parecia confiable". Hay una regla simple y auditable.

## **Los parametros reales del equipo**

Estos son los agentes definidos en la demo:

| **Agente** | **usa\_llm** | **cap** | **Hace** |
| --- | --- | --- | --- |
| `retriever` | si | `explain` | Lee y resume protocolos y FAQ |
| `assessor` | no | `propose` | Calcula prioridad y accion con reglas |
| `drafter` | si | `propose` | Redacta la respuesta al paciente |
| `executor` | no | `propose` | Ejecuta acciones aprobadas |

Y estos son los pasos del playbook:

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/23639cdd-441a-4657-a868-6eaa61b3a95b.png align="center")

Fijate en el paso 5:

*   el agente es `executor`
    
*   su `cap` real es `propose`
    
*   el paso necesita `execute`
    

Entonces:

```yaml
efectivo = min(propose, propose) = propose
needs    = execute
brecha   = 2
```

![](http://localhost:63342/markdownPreview/394426671//Users/josediaz/Projects/JoeDayz/kcp/equipo-agentes align="center")

Resultado: **ese paso siempre escala a humano**.

Eso es gobernanza. El modelo no "se porta bien": **no puede saltarse la escalera**.

## **Diagrama del flujo completo**

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/32b80297-8870-4549-8d5c-48d52cd690e4.png align="center")

Los cuatro outcomes del sistema son:

*   `autonomous`: el agente puede actuar solo
    
*   `informed`: se informa a un humano, pero no bloquea
    
*   `authorized`: se detiene hasta firma humana
    
*   `learning`: el agente propone una mejora y el humano decide
    

## Que hace cada agente, exactamente

### 1\. retriever

**Parametros**

*   usa\_llm: true
    
*   cap: explain
    
*   lee docs/protocolo-triaje.md
    
*   lee docs/faq-citas.md
    
*   salida: un resumen breve para el resto del flujo
    

**Responsabilidad**

No decide. No clasifica. No confirma citas. Solo transforma documentos en contexto util.

**Por que existe**

Porque leer y resumir texto si es una tarea natural para un LLM.

### 2\. assessor

**Parametros**

*   usa\_llm: false
    
*   cap: propose
    
*   entrada principal: caso\["sintomas"\]
    
*   salida: prioridad, accion\_sugerida, caso\_limite, requiere\_urgencias
    

**Reglas actuales**

*   si hay dolor de pecho, falta de aire o desmayo -> prioridad alta
    
*   si hay fiebre, dolor de garganta, tos o vomitos -> prioridad media
    
*   en otro caso -> prioridad baja
    

**Responsabilidad**

Convierte sintomas en un hecho deterministico.

**Por que no usa LLM**

Porque esta parte no deberia depender de creatividad. Si el mismo caso entra hoy y manana, deberia producir el mismo resultado.

### **3.** `drafter`

**Parametros**

*   `usa_llm: true`
    
*   `cap: propose`
    
*   entrada: resumen del `retriever` + hecho calculado por `assessor`
    
*   salida: borrador de respuesta para el paciente
    

**Responsabilidad**

Toma una decision ya calculada y la vuelve lenguaje claro.

**Limite importante**

Puede **proponer** texto. No puede comprometer agenda ni ejecutar acciones irreversibles.

### **4.** `executor`

**Parametros**

*   `usa_llm: false`
    
*   `cap: propose`
    
*   `action_scope.paths: [salidas/]`
    
*   salida: escritura en `salidas/`[`respuesta-cliente.md`](http://respuesta-cliente.md)
    

**Responsabilidad**

Ejecuta acciones chicas y acotadas.

**Limite importante**

Aunque un paso le otorgue `execute`, su `cap` sigue siendo `propose`. Por eso:

*   puede escribir en `salidas/`
    
*   no puede confirmar agenda sin autorizacion humana
    
*   no puede escribir fuera de `salidas/`
    

Eso es **fail-closed**: lo no declarado queda prohibido.

## **El manifiesto que gobierna todo**

La parte mas valiosa de la demo no esta en el prompt. Esta en el manifiesto:

```yaml
agentes:
  retriever:  { cap: explain, usa_llm: true,  hace: "lee y resume protocolos y FAQ" }
  assessor:   { cap: propose, usa_llm: false, hace: "calcula prioridad y accion con reglas" }
  drafter:    { cap: propose, usa_llm: true,  hace: "redacta la respuesta al paciente" }
  executor:   { cap: propose, usa_llm: false, hace: "ejecuta acciones aprobadas" }

playbook:
  id: gestionar-cita-clinica
  pasos:
    - id: 5
      titulo: "Confirmar la reserva de la cita (compromete agenda)"
      agente: executor
      granted: propose
      needs: execute

action_scope:
  executor:
    paths: [salidas/]
```

Esto ya empieza a parecerse a un control plane:

*   define el equipo
    
*   define los limites
    
*   define el flujo
    
*   define que acciones requieren humano
    

La gran leccion es esta:

> **La autoridad no vive en el modelo. Vive en datos declarativos y reglas verificables.**

## **Como se comporta con distintos casos**

La demo incluye cuatro escenarios predefinidos:

| **Caso** | **Sintomas** | **Resultado** |
| --- | --- | --- |
| `alta` | dolor de pecho y falta de aire | va a urgencias |
| `media` | fiebre leve y dolor de garganta | cita en 24 horas + informed |
| `baja` | chequeo general | cita en 2 a 5 dias |
| `borde` | tos leve | cae en prioridad media |

Puedes correrlos asi:

### **Sin Anthropic**

```shell
python3 orquestador.py --sim --caso alta
python3 orquestador.py --sim --caso media
python3 orquestador.py --sim --caso baja
python3 orquestador.py --sim --caso borde
```

### **Con Anthropic**

```shell
source /Users/josediaz/.api-keys
python3 orquestador.py --caso alta
python3 orquestador.py --caso media
python3 orquestador.py --caso baja
python3 orquestador.py --caso borde
```

Lo importante a observar no es solo la respuesta final. Mira tambien:

*   como cambia el paso 2
    
*   cuando aparece `informed`
    
*   por que el paso 5 sigue escalando
    
*   que queda registrado en `ledger.jsonl`
    

## **El ledger: evidencia, no solo logs**

Cada paso escribe un recibo encadenado en `ledger.jsonl`.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/e5c4d656-7485-49e3-8396-ec729af4951b.png align="center")

Si alguien edita un evento viejo, la cadena deja de verificar.

Eso cambia la conversacion de:

*   "creemos que el agente se porto bien"
    

a:

*   "aqui esta la secuencia exacta, con actor, outcome y hash"
    

En sistemas multiagente esto importa aun mas, porque ya no preguntas solo "que hizo el modelo", sino **que hizo cada actor y con que autoridad**.

## **Y entonces, si esto ya funciona, por que luego necesitaremos KCP**

Porque esta demo **funciona**, pero todavia es una version manual y pequena.

Estas son las limitaciones que aparecen en cuanto quieres escalar:

### **1\. El contexto sigue muy cableado a mano**

Hoy el `retriever` sabe explicitamente que debe leer:

*   `docs/`[`protocolo-triaje.md`](http://protocolo-triaje.md)
    
*   `docs/`[`faq-citas.md`](http://faq-citas.md)
    

Eso sirve en un ejemplo chico. Pero en un sistema real querras:

*   descubrir conocimiento por `intent`
    
*   marcar fuentes deprecadas
    
*   enrutar contexto por audiencia
    
*   separar docs, skills, politicas y playbooks sin hardcode
    

Eso es exactamente el tipo de problema que KCP resuelve.

### **2\. El manifiesto ya existe, pero aun no es interoperable de punta a punta**

Ya tenemos `knowledge.yaml`, pero todavia:

*   parte del comportamiento vive en YAML
    
*   parte vive en [`orquestador.py`](http://orquestador.py)
    
*   parte vive en [`agentes.py`](http://agentes.py)
    

KCP empuja a que el conocimiento y sus metadatos sean **navegables por cualquier agente**, no solo por este script puntual.

### **3\. El equipo no tiene skills reutilizables**

Hoy tenemos agentes con roles, pero no una biblioteca de capacidades declaradas que otro runtime pueda cargar y respetar.

Con KCP, la idea deja de ser:

*   "este script sabe hacer esto"
    

y pasa a ser:

*   "esta capacidad esta declarada, versionada y enrutable"
    

### **4\. La gobernanza local no basta cuando aparecen mas herramientas**

En esta demo el `executor` solo escribe un archivo.

En produccion, los agentes querran tocar:

*   calendarios
    
*   bases de datos
    
*   tickets
    
*   correo
    
*   APIs externas
    

En ese punto necesitas un protocolo claro para decir:

*   que conocimiento cargar
    
*   que tools presentar
    
*   que scope aprobar
    
*   como dejar evidencia portable
    

### **5\. Querras que varios runtimes entiendan el mismo mapa**

Si mañana cambias:

*   de script local a Claude Code
    
*   de un agente a varios
    
*   de un repo a varios repos
    

no quieres reescribir la semantica del contexto desde cero.

Quieres un formato comun.

Eso es KCP: **hacer navegable el conocimiento y gobernable el contexto**.

## **El punto pedagogico de esta demo**

No construimos este ejemplo para competir con un framework.

Lo construimos para que la necesidad del framework se vuelva obvia.

Primero entiendes estas ideas a mano:

1.  separar roles
    
2.  declarar autoridad
    
3.  distinguir `cap`, `granted` y `needs`
    
4.  escalar a humano cuando la brecha lo exige
    
5.  dejar evidencia verificable
    

Y solo despues tiene sentido introducir KCP como la forma de volver eso:

*   reusable
    
*   estandar
    
*   interoperable
    
*   escalable
    

Sin ese paso intermedio, KCP parece "otra capa mas".

Con esta demo, se entiende que KCP es el siguiente paso natural.

## **Resumen para llevar**

| **Idea** | **En la demo** | **Por que importa** |
| --- | --- | --- |
| Separacion de roles | 4 agentes con responsabilidades distintas | reduce mezcla de decisiones |
| Autoridad declarada | `cap`, `granted`, `needs` | evita permisos implicitos |
| Governanza deterministica | regla `lowest-of` | hace verificable el flujo |
| Escalado humano | `authorized`, `informed`, `learning` | concentra supervision donde importa |
| Scope restringido | `action_scope.paths: [salidas/]` | aplica fail-closed |
| Evidencia | `ledger.jsonl` | permite auditoria posterior |
| Escalabilidad futura | KCP | evita hardcode de contexto y reglas |

## **Referencias**

*   Demo completa: `equipo-agentes/`
    
*   Manifiesto del equipo: `equipo-agentes/knowledge.yaml`
    
*   Orquestador: `equipo-agentes/`[`orquestador.py`](http://orquestador.py)
    
*   Agentes: `equipo-agentes/`[`agentes.py`](http://agentes.py)
    
*   Protocolo KCP: [Knowledge Context Protocol](https://github.com/Cantara/knowledge-context-protocol)
    

Si el primer post respondia *"como gobierno un agente?"*, este responde *"como gobierno un equipo?"*. El siguiente paso ya no es agregar mas prompts: es darle a ese equipo un **mapa de conocimiento portable**. Ahi es donde KCP deja de ser teoria y empieza a volverse necesario.

Enjoy!

Joe
