Andrew Ng abrió el código de OpenWorker, su agente de escritorio open source, y lo primero que hicimos fue leerlo: módulo por módulo, línea por línea. No lo ejecutamos —eso lo declaramos desde el principio, es una auditoría estática—, pero acabamos con un mapa bastante completo de cómo está construido por dentro.
Íbamos esperando un demo. Encontramos un harness de producción: casi 290 archivos de Python más la app de escritorio, con módulos que suman miles de líneas dedicadas a una sola cosa — que el agente no haga daño. Y en esa lectura pasaron dos cosas al mismo tiempo.
La primera: su capa de gobernanza es, punto por punto, lo que venimos predicando. Ng construyó, de forma independiente y productizada, los mismos siete controles que definimos para nuestro propio harness. Validación incómoda y bienvenida, todo a la vez. La segunda: descubrimos que en el eje donde nosotros ponemos toda la apuesta —la memoria— OpenWorker deliberadamente no juega. Y esa diferencia le da sentido a nuestro producto.
Auditamos el harness de Andrew Ng y salió un veredicto que incomoda un poco: es el mejor freno del mercado abierto —gobernanza de nivel producción— pero con memoria de sesión. Nosotros tenemos memoria viva, pero aún no un motor de permisos tan formal. La diferencia real entre ambos no es mejor freno contra peor freno: es freno contra memoria.
OpenWorker resuelve el freno. Nosotros resolvemos la memoria. Nadie combina hoy, bien, las dos cosas — y ese hueco es exactamente el producto que buscamos: el gobernador con memoria.
1. El experimento: auditamos el harness de Andrew Ng (y qué encontramos)
El método, para que no queden dudas: lectura de código, no ejecución. Clonamos andrewyng/openworker y andrewyng/aisuite (head de ambos repos) y mapeamos su arquitectura, sus flujos de gobernanza y sus decisiones de diseño. Todos los números que citamos —líneas de código, topes, umbrales— salen de leer los archivos, no de correrlos.
La expectativa era modesta: los "agentes de escritorio" suelen ser demos elegantes con un modelo conectado y poco más. Lo que encontramos fue distinto. OpenWorker no chatea: entrega archivos reales —documentos, planillas, reportes— y lo hace con una obsesión declarada por la seguridad. El tamaño lo confirma: ~290 archivos .py más ~199 de TypeScript para la app de escritorio (Electron/TUI) y el servidor en Python.
Y donde verdaderamente se juega el diseño no es en el modelo, sino en los módulos que lo rodean. Este es el inventario de la capa de gobernanza, con sus líneas reales:
| Módulo | LOC | Qué hace |
|---|---|---|
engine.py | 2.164 | El loop del turno. Con un tope duro de 12 iteraciones por defecto |
permissions.py | 687 | Motor allow/deny/ask. Modos Plan / Interactive / Auto. Path-scoping y parseo anti-escape de comandos. Paths protegidos que el propio agente no puede editar |
compaction.py | 561 | Auto-compactación de contexto: umbral 80% / tope 250k tokens; conserva 25% reciente + resumen + estado mecánico |
reviewer.py | 405 | Un segundo modelo que juzga cada acción del primero |
toolchain.py | 290 | Cadena de herramientas |
provenance.py | 257 | Trazabilidad de cada aprobación |
audit.py | 243 | Audit trail con provenance de cada llamada |
risk.py | 147 | Cinco clases de riesgo: READ · EGRESS · WRITE_LOCAL · EXEC · EXTERNAL |
unattended.py | 43 | Los runs no atendidos nunca se auto-aprueban: van a bandeja |
Fíjate en el desbalance, porque es la historia completa: más de 1.500 líneas repartidas en módulos cuya única función es decidir qué no debe hacer el agente. Nadie invierte 1.500 líneas de gobernanza si el producto fuera "el modelo". El harness es el producto — y Ng lo demuestra con el énfasis de su propio código.
2. Qué es OpenWorker: "governed by design" en tres capas
La arquitectura es deliberadamente simple y local: una app de escritorio que habla con un servidor de agente local (Python), que a su vez toca tus archivos, tus herramientas y tu modelo. Todo corre con tus llaves, en tu máquina. El modelo es "bring your own": OpenAI, Anthropic, Google u Ollama — este último, local.
Eso ya es una señal. Pero lo que de verdad define a OpenWorker es cómo trata el problema de la autonomía. Su lema interno podría resumirse en una frase que parece salida de nuestras propias notas: la gobernanza es la arquitectura, no un plugin. Y la implementa en tres capas.
1. Hard floors (pisos duros). Las operaciones peligrosas o irreversibles son human-only, siempre. Ningún modo —ni el full-auto— las baja. Los floors de seguridad solo se pueden endurecer, nunca relajar: bajar un tool de write a read apagaría de un golpe el path-scoping y el modo lectura. Regla de un solo sentido, y es la correcta.
2. Escalera de autonomía ganada. Aprobación por defecto → reglas permanentes → allowlists. En modo auto, un modelo revisor deja pasar lo rutinario y escala lo dudoso. Y si ve denegaciones repetidas, dispara un circuit breaker. La autonomía no se asume: se gana.
3. Audit trail con provenance. Cada llamada queda registrada con su origen —automática, del usuario o denegada— más el razonamiento del revisor. No es un log: es un rastro que explica por qué algo se permitió o no.
Si esto te suena a algo que ya leíste en este blog, es porque lo es. Ng no inventó un harness distinto al que venimos describiendo: construyó el mismo, con más disciplina de la que casi nadie pone.
3. Los siete controles, ahora con nombre y apellido
En varios artículos de esta serie definimos los siete controles que un agente que trabaja solo debería tener para ser gobernable. Escribimos que eran "predicados": los enunciamos, pero cada quien los implementa como puede. OpenWorker los tiene todos, y con nombre y apellido en el código:
| Control (nuestra definición) | Cómo lo implementa OpenWorker |
|---|---|
| 1. Tope duro de pasos | max_iterations = 12 en engine.py. El agente no puede girar sin fin |
| 2. Human-in-the-loop | Hard floors: lo irreversible pasa, sí o sí, por un humano |
| 3. Verificación independiente | reviewer.py: un segundo modelo juzga cada acción del primero |
| 4. Mínimo privilegio | permissions.py: path-scoping + parseo anti-escape + paths que el agente no puede editar |
| 5. Circuit breaker | Denegaciones repetidas cortan la autonomía del run |
| 6. Observabilidad | audit.py + provenance.py: cada acción, con su origen y su razón |
| 7. Modelo-agnóstico | BYO key: OpenAI, Anthropic, Google u Ollama local |
Y encima de esos siete hay un octavo, transversal: las cinco clases de riesgo de risk.py —READ, EGRESS, WRITE_LOCAL, EXEC, EXTERNAL— en lugar del binario pobre de "permitir o denegar". Clasificar cada herramienta por riesgo, y no solo por acceso, es una decisión de diseño que se nos había quedado a medio camino. Es una de las cosas que copiamos.
Que los siete controles no son una idea nuestra: son un estándar que alguien con los recursos de Andrew Ng, construyendo en abierto y con foco en seguridad, terminó implementando también. Cuando dos equipos llegan al mismo diseño por caminos independientes, lo que tienes no es coincidencia — es una arquitectura que se está volviendo canónica. Y nosotros ya la habíamos escrito antes de ver su código.
4. El reviewer: "el que arregla nunca es el único que revisa"
Si tuviera que rescatar una sola pieza de todo OpenWorker, sería reviewer.py. Son 405 líneas que implementan una idea simple y poderosa: una segunda inteligencia, distinta de la que actúa, juzga cada acción antes de que ocurra.
Hay tres detalles de diseño que la convierten en algo más que "un segundo modelo chequeando". Los tres son decisiones que se ven fáciles y no lo son:
- Costos asimétricos. El diseño razona que un "allow" equivocado puede borrar trabajo real, mientras que un "unsure" solo cuesta un clic humano. Como los errores no cuestan lo mismo, el revisor falla hacia el lado conservador: fail closed. Ante la duda, no deja pasar.
- Juzga alcance, no plausibilidad. No evalúa si la acción "tiene sentido" —eso lo puede manipular un buen prompt—, sino si está dentro del alcance que se le concedió. Es un criterio mucho más difícil de engañar.
- Todo lo que ve es DATO, no instrucciones. Esta es la joya: la defensa contra prompt injection. Si el contenido que el agente lee —una web, un archivo, un correo— intenta dar órdenes al revisor, no lo consigue, porque el revisor trata todo como información a evaluar, nunca como un mandato a obedecer. Como dice su propio diseño: el atacante puede dirigirse al agente, pero nunca al juez.
Esa frase es exactamente la que aplicamos en nuestro harness v3 con el worker + verificador. Ver otro equipo llegar por separado a "que el que revisa no sea el que actuó" —y además blindarlo contra inyección— confirma que el patrón no es un capricho nuestro: es la forma correcta de construir un agente en el que se pueda confiar.
5. La diferencia real: freno contra memoria
Hasta acá, todo convergencia. Pero la auditoría no era para darnos palmadas en la espalda: era para encontrar dónde somos distintos. Y el eje aparece apenas cambias la pregunta. OpenWorker pregunta "¿cómo impido que este agente haga algo mal?". Nosotros preguntamos "¿cómo hago que este agente siga siendo el mismo, y mejor, dentro de seis meses?".
La primera pregunta se responde con un freno: control por acción, permisos, revisores, auditoría. La segunda se responde con memoria: continuidad, contexto persistente, identidad que sobrevive a la sesión. Y aquí está la tabla que lo ordena todo:
| Dimensión | OpenWorker (Ng) | Nuestro harness |
|---|---|---|
| Verbo central | Frenar (control por acción) | Recordar (continuidad / identidad) |
| Naturaleza | Producto de escritorio (individuo) | Plataforma soberana (organización) |
| Memoria | De sesión + compaction (resumen) | Multi-capa persistente: vector + grafo + dreaming + intents (+500 sesiones) |
| ¿Aprende entre sesiones? | No | Sí (grafo de conocimiento + dreaming) |
| Contexto / tokens | Auto-compactación con presupuesto (80% / 250k) | Memoria externa + recuperación por relevancia |
| Gobernanza | Explícita y productizada (permisos, riesgo×5, reviewer, floors, circuit breaker, audit) | Aspiracional (checkpoints, loops, supervisión, telemetría) |
| Skills | Store propio | Skills markdown + auto-creación (skill forge) |
| Alcance | Un usuario, su escritorio | La organización, su infraestructura |
Léelo con cuidado, porque la conclusión no es "uno es mejor". Es más preciso —y más útil— que eso. OpenWorker tiene el freno que a nosotros nos faltaba formalizar. Nosotros tenemos la memoria que a él le falta por diseño. Su memoria es de sesión: al terminar la conversación, el agente olvida. El nuestro no: consolida lo aprendido, lo guarda en un grafo de conocimiento y lo trae de vuelta cuando hace falta, incluso entre sesiones y entre proyectos.
Y hay una asimetría final que decide todo: el freno se puede copiar; la memoria, no. Cualquiera puede leer reviewer.py e implementar un segundo modelo que revise (nosotros lo estamos haciendo). Pero construir una memoria que aprenda de verdad —que acumule, consolide y no alucine— requiere infraestructura persistente que no se improvisa leyendo un archivo. Ese es el activo que no viaja en un git clone.
6. El hueco = la oportunidad: el gobernador con memoria
Juntemos las dos piezas. OpenWorker tiene el gobernador: un motor de permisos serio, con riesgo clasificado, revisor independiente y auditoría. Nosotros tenemos la memoria: un sistema persistente y multi-capa que hace que el agente acumule conocimiento en vez de reiniciar cada vez.
Nadie combina hoy, óptimamente, las dos cosas. Y esa frase no es marketing: es lo que deja la auditoría cuando pones los dos sistemas lado a lado. El mercado actual se divide entre agentes muy buenos portándose bien pero sin memoria (OpenWorker y casi todos los "coworkers" de escritorio) y agentes con memoria pero con gobernanza improvisada (la mayoría de los frameworks de orquestación).
El producto que gana es el gobernador con memoria: un sistema que a la vez recuerda lo que aprendió y rinde cuentas por lo que hace. Y que lo hace soberano — sobre tu infraestructura, con tus llaves, sin que un tercero controle ni tus datos ni tu cache ni tus permisos.
No leímos su código para admirarlo: lo leímos para robarle lo bueno. Esto es lo que adoptamos en nuestro propio harness:
1. Un reviewer: un segundo modelo que juzga acciones (el que arregla ≠ el que revisa). 2. Floors que solo endurecen, nunca relajan. 3. Clasificar cada herramienta por clase de riesgo, no solo allow/deny. 4. Path-scoping + parseo de comandos (bloquear escapes tipo find -exec, xargs, python -c). 5. Auto-compactación con presupuesto de tokens. 6. Que nuestros intents aterricen en una bandeja con aprobación humana, sin auto-ejecutarse.
Una auditoría que no cambia tu código no sirvió de nada. La nuestra ya movió seis piezas.
Y esto conecta directo con lo que ofrecemos. Cuando decimos que integramos IA soberana a la operación de una pyme o una corporación latinoamericana, no estamos vendiendo "un modelo". Estamos vendiendo la combinación que nadie más tiene empaquetada: un agente que recuerda tu negocio durante meses y que, además, no puede hacer una tontería sin dejar rastro y sin un freno. Sobre infraestructura tuya. Con memoria que es tuya.
Cierre: lo que aprendimos (y qué construimos con esto)
La lección de auditar a un gigante es incómoda y valiosa al mismo tiempo. Incómoda, porque Ng construyó mejor que nosotros la capa del freno: su gobernanza es más madura y más formal de lo que teníamos. Valiosa, porque su código nos dio el mapa exacto de esa capa —y confirmó que nuestra apuesta por la memoria es donde se juega el diferencial que él no cubre.
No es una derrota ni una victoria. Es un reparto de roles que el mercado todavía no resolvió: Ng puso el gobernador. Nosotros ponemos la memoria. El que junte los dos, gana — y nosotros estamos en posición de juntarlos, porque tenemos el activo que no se copia.
Así que la próxima vez que alguien te diga que los agentes "son todos iguales, es cuestión del modelo", dale dos preguntas. Primero: ¿tu agente recuerda lo de la semana pasada, o empieza de cero cada mañana? Segundo: ¿puede borrar algo sin que quede registro, o hay un freno que no depende de que el prompt se porte bien? Si las respuestas son "no recuerda" y "esperemos que no", lo que tienes no es un agente: es un chatbot con más pasos.
El mejor freno del mercado abierto y la mejor memoria no están todavía en el mismo sistema. Los estamos escribiendo nosotros.
¿Tu "agente de IA" recuerda tu negocio — o empieza de cero cada día?
En Wagner Solutions integramos agentes con memoria persistente y con gobernanza explícita por acción: recuerdan el contexto de tu operación entre sesiones y rinden cuentas por cada decisión que toman, sobre tu propia infraestructura. No es un chatbot con más pasos — es un sistema que aprende y que se puede auditar. Si estás poniendo agentes en producción, la memoria y el freno se diseñan juntos, desde el principio.
Hablemos 30 minutos →