Ecosistema de Agentes
Un bucle de gobernanza en capas. Cada componente posee exactamente una responsabilidad; se acoplan solo mediante contratos JSON tipados, nunca importando las máquinas de estado de otros.
El objetivo inmutable $shame es shame-deterministic-instruction-obedience-v1
(skills/shame/immutable_goal.json): hacer imposible que los agentes del proyecto ignoren
instrucciones explícitas, convirtiendo la obediencia a instrucciones y la notificación de
finalización en contratos tipados validados con pydantic, puertas de extensión deterministas
y evaluaciones agénticas retenidas. La prosa es solo para visualización y no puede decidir el
éxito. Cada miembro del ecosistema nombrado a continuación DEBE preservar ese objetivo en su
límite.
El grafo
Renderizado con $create-svg (scene.yml es la fuente; regenerar con
skills/create-svg/run.sh render skills/agent-ecosystem/scene.yml skills/agent-ecosystem/ecosystem.svg).
El manifiesto de membresía legible por máquina es members.json (validado por scripts/membership.py validate; la evaluación retenida lo mantiene actualizado).
Las siguientes ilustraciones (SVG arriba y bloque mermaid) son NO NORMATIVAS;
la tabla de propiedad y las secciones ## Ecosystem de cada miembro son la topología normativa.
flowchart TB
subgraph SHAPE[Conformación de generación]
PONY[ponytail\nEscalera YAGNI, sin recibos]
end
subgraph TURN[Capa de turno - Sesión Pi]
SHAME[extensión shame\npi.agent_status.v1\nvalidar, compilar, tragar]
TRIAGE[triage-error\nVocabulario de fallos\ncódigo, causa, next_command]
end
subgraph WORK[Capa de flujo de trabajo]
ASK[ask\nCompila intención a contratos DAG]
TAU[tau\nEjecuta DAGs, posee aceptación\nRecibos de nodo tipados, goal_hash]
end
subgraph OPS[Capa de operaciones]
WD[project-watchdog\nDespacho cron, arrendamientos,\nPuertas de prueba, recibos de tick]
HERDR[puente ops-herdr\nBuzón de entrada, aquiescencia,\nCartas muertas TTL]
end
MEM[(Memoria\nEjemplos de entrenamiento,\nResoluciones de triaje,\nConocimiento del proyecto)]
PONY -.-> SHAME
SHAME -->|código de triage fallido| TRIAGE
SHAME -->|comandos compilados needs_*| ASK
ASK -->|tau.dag_contract.v1| TAU
TAU -->|recibos de nodo / handoff v2 lleva estado| SHAME
WD -->|ticket_repair vía ask| ASK
WD -->|lee veredictos| TAU
HERDR -->|códigos de triaje de carta muerta| TRIAGE
SHAME -->|ejemplos etiquetados| MEM
TRIAGE -->|códigos acuñados| MEM
TAU -->|exportación posterior a ejecución de recibos de nodo fallidos| MEM
Tabla de propiedad
| Componente | Posee | Emite | Consume | DEBE para el objetivo inmutable $shame |
|---|---|---|---|---|
| Agentes del proyecto | obediencia a instrucciones en el límite del turno | informes pi.agent_status.v1 | instrucciones del operador, resultados de herramientas, recibos | DEBE informar trabajo supervisado como datos de estado tipados, usar continuing.not_done[].next_command para trabajo incompleto ejecutable por el agente, y nunca tratar la prosa/commits/opinión del revisor como prueba de finalización. |
| triage-error | vocabulario de fallos (failure_codes.json) | {code, cause, next_command} | texto de error crudo de cualquier capa | DEBE hacer que una señal cruda se asigne a un código de catálogo o acuñado; las etiquetas terminales vagas no pueden convertirse en decisiones válidas. |
| shame | estado de turno (pi.agent_status.v1) y shame.immutable_goal.v1 | objetos de estado, objetivo inmutable, ejemplos de entrenamiento | códigos de triaje, etiquetas humanas | DEBE mantener la verdad del estado validada con pydantic, solo prosa para visualización y controlada por evaluación. |
| extensión lazy-report-shame-shame-shame | cumplimiento de message_end de Pi | paquetes de rechazo, estado renderizado, comandos de seguimiento | JSON de estado final, libros de continuación | DEBE rechazar JSON de estado faltante/inválido, eliminar prosa de estado generada por el modelo, renderizar desde datos validados y poner en cola comandos de continuación/escalamiento compilados. |
| status-json-check.mjs | extracción de estado final e invocación del validador | resultado del verificador con objeto de estado validado | texto del asistente | DEBE no decidir la validez del estado con expresiones regulares, encabezados de prosa, markdown, HTML o juicio del LLM. |
| agent_status_schema.py | legalidad del estado pydantic | pasar/fallar de análisis | JSON de estado final | DEBE hacer que los estados inválidos sean irrepresentables con extra=forbid, cargas de estado tipadas, códigos de triaje canónicos y not_done solo en continuing. |
| compile-status-command.mjs | compilación tipada de estado a comando | comando de seguimiento exacto o ningún comando | objeto de estado validado con pydantic | DEBE compilar cargas continuing/needs_* mecánicamente y compilar estados terminales/humanos a ningún comando automático. |
| evaluaciones agénticas | prueba de regresión retenida | informes de preparación | accesorios y comandos | DEBE fallar si la política de estado basada en regex/prosa regresa o si los invariantes de estado pydantic se debilitan. |
| ask | compilación de intención a DAG | tau.dag_contract.v1, paquetes de recuperación | cargas de escalamiento de estado | DEBE consumir cargas tipadas needs_* en lugar de prosa de escalamiento informal. |
| tau | ejecución y aceptación de DAG | recibos de nodo, tau.agent_handoff.v1/v2, hashes de objetivo | contratos DAG, objetos de estado incrustados | DEBE poseer hashes de objetivo inmutables y recibos de aceptación tipados; la prosa del revisor no puede reemplazar la aceptación. |
| project-watchdog | despacho programado | recibos de tick, puertas de prueba, bloqueos, libros de continuación | tickets de GitHub, veredictos de tau | DEBE exponer trabajo abierto legible por máquina para que done pueda fallar mientras los tickets/puertas/próximos pasos permanezcan sin resolver. |
| ops-herdr | transporte entre sesiones | registros de buzón de entrada, cartas muertas | códigos de triaje | DEBE transportar fallos/estado entre sesiones como registros tipados de buzón de entrada o cartas muertas con códigos de triaje. |
| ponytail | minimalismo de generación | comentarios de deuda ponytail: (no recibos) | nada del mundo de recibos | DEBE no anular los requisitos de estado, recibo, prueba o evaluación. |
| Memoria | recuperación | respuestas de lectura de almacenamiento/recuperación (no recibos de sobre; las recuperaciones son observaciones, nunca envueltas) | todo duradero | DEBE almacenar ejemplos de shame, resoluciones de triaje y conocimiento del proyecto con lectura; las recuperaciones son observaciones, no recibos de finalización. |
| agent-ecosystem | propiedad de componentes y límites de recibos | validación pi.receipt_envelope.v1 | cargas de límite | DEBE publicar el mapa de propiedad y requerir el envoltorio del sobre en los límites que cambian la autoridad. |
| goal-helper | forma de objetivo centrada en prueba | indicación/lista de verificación de objetivo inmutable | texto de objetivo humano | DEBE mantener el éxito vinculado a la prueba principal, criterios de finalización, alcance permitido, deriva prohibida, presupuesto de reintentos y condición de parada. |
pi.receipt_envelope.v1 - el sobre límite
Envuelva una carga en el sobre SOLO en límites que cambian la autoridad: despacho, entrega, aceptación, escalamiento, cierre, fallo duradero. Los objetos internos permanecen sin envolver (decisión YAGNI revisada: sin bus de eventos universal, sin sobre en cada artefacto).
{
"schema": "pi.receipt_envelope.v1",
"receipt_id": "id-estable",
"payload_schema": "pi.agent_status.v1",
"producer": "shame",
"emitted_at": "RFC3339",
"goal_hash": "sha256:<64hex> (opcional)",
"parent_refs": [
{"receipt_id": "id", "expected_schema": "s", "expected_producer": "p", "digest": "sha256:<64hex> (opcional)"}
],
"triage_code": "código de catálogo o acuñado (opcional)",
"payload": {}
}
Validar con:
skills/agent-ecosystem/run.sh validate <envelope.json>
echo '{...}' | skills/agent-ecosystem/run.sh validate -
Reglas aplicadas por scripts/receipt_envelope.py (pydantic, extra=forbid):
triage_code, cuando está presente, debe ser un código de catálogo de triage-error o un código acuñado*_unclassified_<8hex>- misma regla quepi.agent_status.v1.failure.goal_hashyparent_refs[].digestdeben sersha256:+ 64 hex minúsculas.parent_refsrequierengoal_hash: un borde de evidencia sin un objetivo compartido no es confiable y falla la validación.- Pydantic prueba solo la ESTRUCTURA. La RESOLUCIÓN de referencias es un paso
separado del lado del consumidor con cuatro comprobaciones obligatorias: el recibo referenciado existe;
su esquema es igual a
expected_schema; su productor es igual aexpected_producer; yresolved_parent.goal_hash == envelope.goal_hash(un hash presente no es un objetivo compartido hasta que se compara). La verificación del digest se aplica cuandodigestestá configurado. Un sobre estructuralmente válido no es todavía uno confiable. payload.schemaes OBLIGATORIO en cada carga envuelta y debe ser igual alpayload_schemadel sobre; una carga anónima falla la validación.- Los cambios en el conjunto de campos de cualquier esquema
extra=forbidson disruptivos por construcción; requieren una nueva versión del esquema, nunca una edición in situ.
Convenciones de campo JSON compartidas
Los campos siguientes son la superficie compartida real. Un componente "comparte" un campo cuando emite o valida el mismo nombre, forma y semántica que el propietario.
| Campo | Forma | Propietario | Compartido por |
|---|---|---|---|
schema | id versionado, ej. pi.agent_status.v1 | cada propietario de esquema | cada objeto de contrato; los bumps de versión son aditivos o nombre nuevo |
code (triaje) | entrada de catálogo o <prefix>_unclassified_<8hex> | triage-error | shame failure.triage.code, sobre triage_code, cartas muertas de herdr, paquetes de recuperación de ask |
cause / next_command | cadena simple / comando ejecutable exacto | triage-error | todo consumidor de una clasificación de triaje; next_command es también el campo de continuación de shame continuing |
goal_hash | sha256: + 64 hex minúsculas | tau (paquete de objetivo inmutable) | estado de shame (opcional), sobre (opcional), cada recibo de nodo de tau |
verified[] | pares {command, result} | shame | prueba de estado finalizado en cualquier lugar donde se incruste un objeto de estado |
proof[] | rutas/URLs/ids concretos; las rutas locales en pi.agent_status.v1 deben existir antes de que done pase | shame | objetos de estado; las puertas de prueba de watchdog nombran los mismos artefactos |
parent_refs[] | {receipt_id, expected_schema, expected_producer, digest?} | sobre de agent-ecosystem | evidencia de escalamiento (reemplaza rutas ad hoc en needs_webgpt) |
producer / receipt_id / emitted_at | cadena / id estable / RFC3339 | sobre de agent-ecosystem | cualquier recibo envuelto en límite |
payload_schema | id versionado; debe ser igual a payload.schema cuando la carga declara uno | sobre de agent-ecosystem | cualquier recibo envuelto en límite |
| veredictos terminales | PASS FAIL BLOCKED NEEDS_ATTENTION | tau | join de ask, puertas de prueba de watchdog, monitores de flujo |
recoverable / not_this | bool / lista de exclusión | catálogo de triage-error | consumidores decidiendo reintentar vs escalar |
Convenciones de triage-error (normativas aquí, implementadas allí)
- Una señal cruda se asigna a UN
{code, cause, next_command}; un código genérico en un límite de capa es un error, no una clasificación. - Las entradas del catálogo viven en
skills/triage-error/failure_codes.jsoncon{code, layer, match[], cause, next_command, recoverable, not_this[]}. La coincidencia es determinista: la normalización es exactamente" ".join(text.lower().split())(minúsculas, todos los espacios en blanco colapsados a espacios simples, extremos recortados); una entrada coincide cuando CUALQUIERA de sus tokensmatch[](también en minúsculas) es una subcadena de la señal normalizada; cuando se da--layer, las entradas con unlayerdiferente se saltan; la PRIMERA entrada coincidente en orden de archivo gana. Nunca expresiones regulares, nunca juicio del LLM. Prohibido como clasificaciones terminales (son síntomas, no causas, y deben ser re-triajeadas desde la señal subyacente):NEEDS_ATTENTION,BLOCKED,browser_handler_timeout,unknown_error,generic_failure, y cualquier palabra de veredicto terminal simple. - Las señales no coincidentes acuñan
<layer-or-unknown>_unclassified_<8hex>donde los 8 caracteres hex son los primeros 8 de sha256 sobre el texto de la señal normalizada, por lo que la misma señal siempre acuña el mismo código. La acuñación abre el ticket + bucle de evaluación agéntica + memoria. Umbral de recurrencia: la SEGUNDA observación del mismo código acuñado desencadena promoción o alias. Representación de alias: un mapaaliasesde nivel superior en el archivo del catálogo asigna código acuñado -> código canónico; debido a que la acuñación es determinista sobre la señal normalizada, una señal recurrente reacuña el mismo código y el clasificador lo resuelve a través del mapa hasta la entrada canónica (registrada comoaliased_from); el código acuñado nunca es una segunda identidad canónica. Los efectos secundarios de ticket/evaluación/memoria son idempotentes por código acuñado (claveados por la cadena del código). - Cada componente del ecosistema que nombra un fallo utiliza un código de catálogo o acuñado. Tanto los validadores pydantic (esquema de estado, sobre) lo aplican en tiempo de análisis, por lo que una etiqueta ambigua no puede existir en un objeto válido.
Decisiones de diseño (de la revisión externa)
- El rigor se aplica a las DECISIONES, no a las observaciones. Mantenga la evidencia cruda
permisiva; mantenga los resultados aceptados estrictos. Una observación tipada
unknownes legal; una decisión ambigua no. - Los códigos acuñados
*_unclassified_*tienen un ciclo de vida provisional: promocione al catálogo o alias a un código existente cuando recurran; nunca permita que se expandan. - Los cambios de esquema son aditivos; los cambios de forma disruptivos obtienen una nueva versión
(patrón
tau.agent_handoff.v2), nunca ediciones in situ. - No construir: un bus de eventos de gobernanza universal; recibos para comentarios de ponytail, recuperaciones de Memoria o reintentos internos.
Membresía
Una habilidad o extensión se une al ecosistema añadiendo una sección ## Ecosystem en su
SKILL.md nombrando: qué esquemas produce, qué consume y qué
eventos de límite envuelve en el sobre. Miembros actuales: shame, triage-error,
tau, ask, project-watchdog, ops-herdr. Ponytail es adyacente por diseño.