Orkas Orkas
Inicio Blog Arquitectura
Arquitectura

Reescribir los cimientos del agente: una refactorización de Orkas desde cero

Cómo Orkas reconstruyó los cimientos de sus agentes a lo largo de la serie de versiones 1.0: un entorno de ejecución dentro del proceso, rotación de proveedores, orquestación dinámica de chats grupales, alojamiento abierto, memoria y evolución autónoma.

Cuando un producto de agentes de IA madura, lo más costoso no son las funciones, sino los cimientos. Este artículo recorre la refactorización desde cero que Orkas llevó a cabo a lo largo de su serie de versiones 1.0: una renovación completa de la invocación de modelos, el bucle del agente, la orquestación de múltiples agentes y el ecosistema de herramientas, junto con las ventajas y los costos de cada decisión.

La versión breve Para qué sirvió la reescritura El resultado es la aplicación que puedes instalar hoy: de código abierto con licencia MIT, con prioridad local y que funciona con tus propias claves de proveedor si así lo deseas.
Descargar Orkas — gratis

Por qué modificar los cimientos

Orkas es un espacio de trabajo de escritorio para agentes de IA con prioridad local: todo el trabajo de los agentes se ejecuta dentro de un proceso en la propia computadora del usuario, los datos residen localmente y la sincronización en la nube de extremo a extremo se realiza bajo demanda. Las funciones se acumularon rápidamente en las primeras versiones: una biblioteca de habilidades, una base de conocimientos, conectores y múltiples agentes al estilo de un chat grupal. Pero cuanto más avanzábamos, más claro quedaba: el verdadero cuello de botella no era ninguna función en particular, sino tres aspectos de los "cimientos".

  1. Si la capa de invocación de modelos sigue el viejo camino conversacional, queda atada a una serie de supuestos equivocados. Invocar un modelo de gran tamaño como si fuera un "chat de una pregunta y una respuesta" introduce una serie de valores predeterminados que tienen sentido para un chat, pero no para un agente: un límite fijo de tokens de salida, llamadas a herramientas en serie, tiempos de espera ocultos y un único proveedor fijado en el código. Un agente es un flujo de larga duración que ejecuta decenas de turnos seguidos, se acerca habitualmente al límite de la ventana de contexto, necesita leer archivos en paralelo y puede ser interrumpido por el usuario en cualquier momento: todos esos valores predeterminados acabarán causando problemas en producción. Peor aún, las capacidades más valiosas de un agente de escritorio —operaciones precisas con archivos, búsqueda local, ejecución de un intérprete de comandos, ejecución paralela con varios ejecutores y resolución de tareas de largo alcance— son precisamente las que esta capa de supuestos deja fuera.

  2. La orquestación era una "planificación estática". La versión inicial era un motor de planes/DAG: primero se pedía al modelo que descompusiera la tarea en un grafo de planificación y después un ejecutor distribuía el trabajo según ese grafo. Suena ordenado, pero la realidad de un agente es muy dinámica: leer un archivo revela que hay que cambiar de rumbo, y el resultado de una subtarea determina a quién se asigna el siguiente paso. Fijar las decisiones en un grafo generado de antemano implica que cada caso en el que "el plan no sigue el ritmo de la realidad" debe corregirse dentro del ejecutor.

  3. El ecosistema era un catálogo cerrado. Las habilidades solo podían proceder del mercado oficial, los conectores eran un catálogo definido en el código y las herramientas de agentes externos que ya estaban en la computadora del usuario eran una caja negra total para Orkas. Si un usuario quería incorporar un proyecto de terceros, su propio servidor MCP o hacer que un agente ya instalado en su computadora accediera a las habilidades y a la base de conocimientos de Orkas, nada de eso era posible desde el punto de vista de la arquitectura.

La idea central de esta refactorización es sencilla: recuperar el control de los cimientos del agente. En concreto, se materializa en cuatro ejes entrelazados: un entorno de ejecución propio dentro del proceso, una capa de modelos independiente del proveedor, una orquestación dinámica mediante chat grupal y el paso de un catálogo cerrado a una plataforma anfitriona abierta. Veámoslos uno por uno.

1. Llevar al escritorio un conjunto completo de capacidades de agente de programación

El escritorio es el terreno natural del agente: aquí hay un sistema de archivos real, un intérprete de comandos real y un conjunto de herramientas locales real. Un asistente que solo puede conversar desaprovecha el entorno; lo que realmente aprovecha las ventajas del escritorio es un conjunto completo de capacidades de agente de programación: lectura y escritura de archivos con precisión de intervalos de caracteres, búsqueda entre archivos, ejecución de bash y herramientas del sistema, puesta en marcha de varios ejecutores en paralelo y resolución de problemas de largo alcance para seguir trabajando durante decenas de turnos hasta terminar de verdad una tarea compleja.

El resultado principal de la refactorización existe precisamente para incorporar este conjunto de capacidades de forma nativa al propio proceso de Orkas: un entorno de ejecución de agentes independiente, cargable dinámicamente y ejecutado dentro del proceso, llamado core-agent en el código. No es otra envoltura para un chat, sino un motor de agentes que Orkas controla por sí mismo.

La decisión arquitectónica clave fue dividirlo en dos capas:

  • Capa del motor (paquete independiente): la mecánica pura del agente: el bucle de llamadas a herramientas, los eventos en transmisión continua, la compactación del contexto, la clasificación de errores y los reintentos, la abstracción del proveedor, el entorno aislado, la exploración de habilidades, la memoria y la autoevolución. No sabe nada de la lógica de negocio de Orkas: no lee directorios de datos de negocio, no entiende el formato de los archivos de conversación y nunca toca IPC.
  • Capa de adaptación (dentro del proceso principal): conecta el motor con Orkas: la persistencia de las sesiones, la rotación de proveedores, los permisos de las herramientas, el registro de habilidades, los conectores, la base de conocimientos y las distintas herramientas de generación. Traduce los eventos nativos del motor a los formatos de eventos propios de Orkas, de modo que la capa de negocio solo ve una interfaz estable.

Esta separación entre motor y adaptación es la raíz de toda la flexibilidad que viene después. El motor puede probarse y evolucionar de forma independiente; la capa de adaptación puede absorber de forma segura la complejidad específica de Orkas —rotación, períodos de espera, entorno aislado y permisos— sin contaminar el motor. La revisión de arquitectura del equipo lo resumió en una frase: esta complejidad está justificada; no fusionen las capas.

En qué consiste realmente el conjunto de capacidades

Tener el entorno de ejecución en nuestras manos no es una cuestión de presumir; se trata de permitir que el agente realmente "ponga manos a la obra" en el escritorio. El conjunto de capacidades se divide, a grandes rasgos, en cuatro grupos:

  • Operaciones precisas con archivos y búsqueda local. read_file permite leer por intervalos de caracteres y extrae automáticamente texto de documentos PDF / Office; edit_file realiza sustituciones precisas de "cadena anterior → cadena nueva" y exige una lectura antes de cualquier escritura; write_file guarda el resultado y mantiene un registro de él; stat_file consulta el tamaño; search_files localiza archivos por nombre/patrón glob y grep_files busca contenido entre archivos. Este grupo permite que el agente "explore código y modifique archivos" en un espacio de trabajo real como un ingeniero, en lugar de limitarse a consumir y emitir bloques completos.
  • Bash y herramientas del sistema. Un ejecutor de comandos en un entorno aislado, con un modo de ejecución en segundo plano —las tareas largas se separan del turno actual y los registros se guardan en un archivo— y controles para operaciones peligrosas según su nivel de riesgo. Gran parte de la capacidad de un agente de escritorio proviene precisamente de poder controlar directamente las herramientas del sistema.
  • Varios ejecutores en paralelo. Dentro de un mismo turno, las herramientas independientes de solo lectura se ejecutan de forma concurrente; a nivel de tarea, Commander también puede distribuir subtareas independientes entre varios ejecutores en paralelo (véase la sección 3). Paralelizar donde sea seguro es la clave para reducir las "tareas de largo alcance" a un tiempo real de ejecución aceptable.
  • Razonamiento y resolución de tareas de largo alcance. Un bucle capaz de ejecutar decenas de turnos seguidos, gestionar su propio contexto, recuperarse de errores y no quedarse nunca dando vueltas en el mismo sitio: esta es la línea que separa "terminar un trabajo complejo" de "responder una pregunta".

Cómo se preparó para producción desde el punto de vista de la ingeniería

"Escribir tu propio bucle" suena a buscarse problemas, y sí conlleva un costo de mantenimiento. Pero a cambio ofrece un control preciso sobre todo el ciclo de vida del agente. Ese control no es abstracto: es un conjunto de mejoras concretas, cada una de las cuales determina si alguna de las capacidades anteriores "se sostiene" en producción:

  • Ventana de contexto real + compactación solo al 80%. El motor lee la ventana de contexto real de cada modelo, incluidos los modelos con ventanas de un millón de tokens, y activa la compactación solo cuando el uso alcanza el 80%, en lugar de empezar de forma conservadora al 60% y descartar el 40% del contexto útil. También hay una protección contra la "compactación sin ganancia": si el tramo final que se conserva ya llena la ventana —por ejemplo, un resultado muy grande de lectura de un archivo situado en ese tramo—, la compactación no puede liberar nada, así que solo registra una advertencia y se omite, sin desperdiciar nunca una llamada para resumir. De esto depende que una tarea de largo alcance pueda "recordar lo que ocurrió antes".

  • Herramientas consecutivas de solo lectura en paralelo. Cuando el modelo lanza la lectura de un archivo, la búsqueda de archivos y una consulta web —varias herramientas independientes de solo lectura— en un mismo turno, el motor agrupa las consecutivas que se pueden paralelizar para ejecutarlas de forma concurrente; las herramientas de escritura actúan como barreras naturales y mantienen el orden declarado. Las llamadas a herramientas y sus resultados se registran estrictamente en el orden declarado, por lo que la concurrencia nunca rompe el protocolo. Las herramientas de solo lectura más habituales pasan de ejecutarse en serie a hacerlo en paralelo de una sola vez, y el tiempo real de ejecución de todo el lote disminuye notablemente.

  • Lectura antes de escritura + control de concurrencia optimista. Antes de editar un archivo, hay que leerlo; el motor registra un estado de referencia del archivo leído y comprueba que no haya cambiado al editarlo. Cuando varios ejecutores en paralelo modifican el mismo archivo a la vez, el que llega después recibe un error claro de "estado desactualizado", en lugar de sobrescribir silenciosamente los cambios del otro. Con varios ejecutores trabajando en paralelo sobre el mismo espacio de trabajo, esta protección es indispensable.

  • Incorporación inmediata de las interrupciones durante la ejecución. Cuando un usuario añade otra línea mientras el agente está a mitad del trabajo, el motor incorpora ese mensaje en cola a la entrada del turno actual en el límite del bucle de herramientas, en lugar de esperar para iniciarlo como un turno independiente. Esto convierte "corregir el rumbo mientras trabaja" en una interacción natural.

  • Detección de bucles. Cuando una misma llamada a una herramienta se repite de forma consecutiva, el motor primero advierte (en la 3.ª) y después detiene la ejecución por completo (en la 5.ª); cualquier firma diferente reinicia el contador, por lo que las variaciones legítimas, como la paginación o las consultas periódicas, no lo activan por error. Cuando el modelo se atasca, ya no consume tokens silenciosamente.

  • Eliminación del límite estricto de salida del turno principal. La salida del turno principal ya no está sujeta a un límite diminuto, por lo que los informes largos y las ediciones grandes no se truncan silenciosamente; las llamadas auxiliares —compactación y reflexión— siguen utilizando un límite pequeño de forma conservadora.

Hay un detalle muy "local" que merece mencionarse: la estimación de tokens para texto mixto en chino e inglés. Una estimación genérica calcula entre dos y tres veces menos tokens de los reales en una conversación íntegramente en chino; el motor trata de forma distinta los caracteres chinos e ingleses según su clase de carácter, y eso es lo que hace confiable el umbral de compactación. Es el tipo de detalle que un SDK genérico no resolverá por ti.

En conjunto, estas mejoras responden a "por qué no usar simplemente un SDK ya disponible": porque las capacidades más potentes de un agente de escritorio están precisamente en la capa que un SDK no expone; para prepararlas para producción, tienes que controlar el bucle.

2. Mantener el modelo siempre en línea: la envoltura de proveedores en varias capas

El objetivo de la capa de modelos se resume en una frase: sin importar qué falle en una clave, un proveedor o una red determinados, este turno de la conversación del usuario debe sobrevivir siempre que sea posible. Para ello, la capa de adaptación añade varias envolturas sobre la abstracción de proveedores del motor: rotación, períodos de espera, registro y adaptación externa.

La decisión de diseño más importante es que el rotador se sitúa por debajo del ejecutor. El motor escribe el mensaje del usuario en la sesión persistente antes de llamar a un proveedor; si los reintentos y la rotación se realizaran a nivel del motor, habría que volver a enviar el mensaje del usuario o implementar una reversión completa de la sesión. Al colocar el rotador por debajo del motor, el mensaje del usuario se escribe exactamente una vez y "reintentar con otro candidato" resulta totalmente transparente para el estado de la sesión.

El criterio del rotador también es prudente y toma como límite el primer evento de contenido:

  • Un fallo antes de que el modelo emita contenido sustantivo —texto o una llamada a una herramienta—: es seguro cambiar al siguiente candidato;
  • Una vez emitido el primer evento de contenido: detener la rotación y dejar que el error se propague hacia arriba, porque el modelo podría haber ejecutado ya un turno completo y repetirlo duplicaría sus efectos secundarios.

La clasificación de errores determina si se debe "rotar, no rotar o reintentar". Los fallos a nivel de cuenta, como errores de autenticación, saldo insuficiente, límites de frecuencia o suscripciones vencidas, establecen un período de espera y provocan una rotación; los fallos transitorios de red, como el restablecimiento de una conexión, no establecen un período de espera y se reintentan unas cuantas veces con el mismo candidato sin conservar estado; en cambio, las solicitudes mal formadas, los errores por políticas de contenido y los errores 5xx del servidor —que fallarían igualmente con otra clave— se propagan directamente sin rotación. El período de espera es una indicación de diez minutos, dentro del proceso y no persistente: es solo una señal de corto plazo que no merece escribirse en disco tras cada fallo, y reiniciar el proceso es precisamente el momento adecuado para volver a comprobar.

En cuanto a la "lista" de proveedores, la refactorización reúne tres tipos de fuentes en una única abstracción:

  • LLM gestionado por Orkas: un proxy del lado del servidor, listo para usar tras iniciar sesión, con el servidor encargado de enrutar entre modelos de texto e imagen;
  • Clave propia: los principales proveedores estándar de modelos de gran tamaño;
  • Adaptadores externos de conexión directa: un conjunto de modelos que necesitan conexión directa o tienen su propia facturación, adaptados manualmente a la misma interfaz de proveedores.

Para las capas superiores, todo esto aparece como un único par estable (provider, model): la rotación, los períodos de espera y la adaptación externa quedan ocultos dentro de la capa de adaptación.

3. El chat grupal como orquestación: de un plan-DAG estático a Commander dentro del bucle

Esta es la parte de la refactorización que más exige "cambiar de mentalidad".

El modelo anterior era la planificación estática: el modelo generaba primero un plan/DAG y el ejecutor seguía el grafo. El nuevo modelo elimina ese grafo por completo y lo sustituye por una orquestación dinámica mediante chat grupal con Commander dentro del bucle.

Su metáfora es una sala de chat grupal:

  • Commander es el anfitrión de la sala, no una capa intermedia invisible;
  • Los agentes ejecutores son miembros de pleno derecho y en igualdad de condiciones dentro de la sala;
  • Todas las interacciones son mensajes asíncronos, puestos en cola a través de un único bus de mensajes (no existe una vía privada para la distribución en paralelo).

La "asignación" de Commander no es un @somebody escrito en prosa: un LLM que escribe @AgentA en el cuerpo del texto solo está produciendo Markdown procedente de sus datos de entrenamiento, y no es confiable. La señal real de asignación es una llamada estructurada a una herramienta y, tras la refactorización, se concreta en tres acciones con una semántica clara:

  • dispatch_to: enviar a un agente a ejecutar el trabajo hasta completarlo y devolver el resultado, que Commander sintetiza. Varias tareas independientes pueden distribuirse de forma concurrente.
  • run_worker: una subtarea de la que se encarga el propio Commander, con el resultado devuelto de forma síncrona; un ejecutor anónimo es la "mano" de Commander, invisible para el usuario, mientras que un ejecutor con nombre es un especialista visible.
  • hand_off_to: ceder la conversación al agente; Commander se retira y el agente responde directamente al usuario, sin una síntesis adicional en ese turno.

Por qué un chat grupal en lugar de un orquestador o un árbol de subagentes

Convertir el sistema de múltiples agentes en un chat grupal aporta varias ventajas que un orquestador tradicional o un árbol de subagentes no puede ofrecer:

  • Segmentos de visibilidad. Cada mensaje solo se añade al segmento de "quienes pueden verlo". Cuando un agente ejecutor se inicia, reconstruye únicamente su propio segmento, de modo que la salida extensa de otro agente no contamina su contexto. Commander lo ve todo.
  • Estado mínimo. El estado central de toda la orquestación se limita a "quién tiene la palabra en este momento" más un registro ligero de tareas. Sin DAG ni una máquina de estados compleja.
  • Reconstrucción y sincronización naturales. Los mensajes se ordenan de forma natural por marca de tiempo, por lo que tanto la recarga como la sincronización entre dispositivos se apoyan directamente en el flujo de mensajes. El cliente móvil realiza el control remoto precisamente a partir de este flujo: todo el procesamiento de los agentes se ejecuta en el escritorio y el móvil solo muestra una vista reflejada, sin necesidad de un protocolo especial de orquestación.

La revisión de arquitectura del equipo fue igual de tajante en este punto: un bus de chat grupal más Commander dentro del bucle es la estructura de múltiples agentes de Orkas; añadir otra vía paralela de asignación a subagentes dentro del proceso violaría la regla invariable de "una única vía de asignación del chat grupal".

Novedad de esta versión: transferencia interactiva

La incorporación más reciente en este eje es la transferencia interactiva entre agentes.

El problema es concreto: un agente de tipo "tutor" enseña al usuario durante un turno y el usuario quiere seguir haciendo preguntas, pero el sistema devuelve la palabra obligatoriamente a Commander, lo que obliga al usuario a volver a mencionar con @ a ese agente en cada mensaje.

La solución es un control de quién tiene la palabra cuya autoridad reside en el servidor + un destinatario decidido por el modelo:

  • Quién tiene la palabra pasa a ser un campo de estado persistente, que se conserva entre recargas y utiliza el evento de cambio de estado existente para sincronizarse automáticamente con todos los clientes, sin necesidad de un nuevo tipo de evento.
  • Después de que Commander use hand_off_to para dar la palabra a un agente interactivo, los mensajes posteriores del usuario "sin @" van directamente a ese agente, hasta que el agente la devuelva por iniciativa propia o el usuario vuelva a dirigirse a Commander.
  • El agente devuelve el control con un marcador <handback />; el análisis verifica estrictamente que exista una coincidencia real, para que un <handback aislado en la prosa no se interprete erróneamente como una transferencia.
  • Si al devolver el control hay tareas pendientes en el registro, Commander las retoma desde ese registro y continúa.

Esto también incluye una mejora de la experiencia: las burbujas del bucle de Commander. El bucle de "asignar → leer el resultado → volver a asignar" de Commander dentro de un turno antes se comprimía en una única burbuja y, al recargar, incluso podía saltar fuera de orden hasta el final. La refactorización divide un turno en varios segmentos en cada punto de asignación visible, cada uno como un mensaje independiente con una marca de tiempo ascendente: por primera vez, el usuario puede ver a Commander "recorriendo el bucle de orquestación", y el orden al recargar también es correcto.

Por último, dos mecanismos de protección presentes en todo el sistema: la cancelación grupal es la única vía de detención para todos los participantes —en cuanto el usuario pulsa Detener, se activa la señal de cancelación de todos los ejecutores, incluidos los subejecutores anónimos mediante un mecanismo de coincidencia de respaldo—; y la ya mencionada redirección mediante interrupciones, que incorpora al turno actual la intervención del usuario durante la ejecución.

4. De un catálogo cerrado a una plataforma anfitriona abierta

Si los tres primeros ejes buscaban consolidar los cimientos, este consiste en abrir todas las puertas y ventanas: convertir Orkas de un catálogo cerrado en una plataforma anfitriona abierta, manteniendo al mismo tiempo el límite de seguridad sin ceder ni un centímetro.

La refactorización desmanteló sistemáticamente varios puntos de restricción "cerrados":

  • Paquetes externos. El usuario proporciona la dirección de un repositorio y Orkas lo aloja localmente, clonado tal cual en una carpeta: nunca lo normaliza, nunca lo reescribe y nunca lo sincroniza con la nube, porque contiene directorios de dependencias de terceros. Una herramienta independiente de línea de comandos gestiona el ciclo de instalación, actualización, inicio y detención, comprueba si tiene "formato de habilidad" —incluye un archivo de descripción de habilidad— o "formato de CLI" —incluye un punto de entrada ejecutable— y escribe los metadatos en un registro fuera del directorio del paquete, para que las futuras actualizaciones desde el repositorio nunca generen conflictos. La instalación de dependencias pasa por una confirmación en dos pasos de "preguntar una vez y recordar"; se generan ejecutables intermediarios para los puntos de entrada ejecutables y se incorporan al PATH de la herramienta bash, de modo que el modelo pueda invocar directamente estas CLI de terceros.

  • Carga de habilidades desde varias raíces. El único punto de entrada para ejecutar habilidades pasó de reconocer solo dos raíces a cuatro niveles —personalizadas / mercado / paquete externo / globales—, resueltos por prioridad; los scripts de un paquete externo dan preferencia al entorno de dependencias incluido en el propio paquete. Este es el punto de restricción con mayor riesgo de regresiones y está respaldado por una matriz completa de datos de prueba.

  • Interoperabilidad de habilidades globales. Orkas lee directamente de los directorios globales de habilidades que otras herramientas de agentes ya mantienen en la computadora del usuario, logrando interoperabilidad a nivel de habilidades: una habilidad que el usuario haya incorporado en un lugar también puede utilizarse en Orkas. El hecho de que el usuario coloque una habilidad en esos directorios constituye por sí mismo la autorización, por lo que esta función está activada de forma predeterminada, aunque conserva un interruptor general. Estas descripciones de habilidades de terceros son una superficie no confiable de inyección de instrucciones, por lo que pasan por el cargador de "nivel abierto", solo son visibles para Commander y por su estructura no pueden incorporarse a la lista de habilidades permitidas de un agente.

  • MCP configurado por el usuario. Los conectores ya no son un catálogo definido en el código. El usuario puede añadir cualquier servidor MCP, ya sea en modalidad remota por HTTP (riesgo bajo) o como subproceso local (riesgo alto). El propio formulario es el punto donde se otorga el consentimiento —el comando que el usuario escribió manualmente se muestra tal cual—, la configuración del transporte, incluidos los secretos, se guarda íntegramente en almacenamiento cifrado y las instancias personalizadas siempre llevan un prefijo fijo para que nunca puedan hacerse pasar por un conector oficial del catálogo.

  • Puente inverso: permitir que los agentes externos de la computadora también accedan a Orkas. Esta es la parte más interesante. Las herramientas de agentes externos que ya estaban en la computadora del usuario antes eran una caja negra para Orkas; ahora, cuando Orkas les asigna trabajo, incorpora un canal de enlace que les permite, en sentido inverso, listar, leer y ejecutar las habilidades de Orkas, invocar conectores y buscar en la base de conocimientos. El puente funciona a través de un canal local entre procesos, sin abrir ningún puerto de red, y se autentica con una credencial de un solo uso, única para cada ejecución y destruida en cuanto esta termina. Cada llamada a un conector que tenga un efecto externo pasa por un diálogo de confirmación del usuario: no se usa un criterio heurístico de lectura/escritura basado en el nombre de la herramienta, que tendería a ser demasiado permisivo, sino una confirmación por cada par (agente, conector), con la opción de "permitir siempre".

  • Enfoque de programación para tareas poco frecuentes. El árbol de decisiones de Commander incorpora una rama: cuando no hay un agente, una habilidad o un conector que encaje, evaluar si se puede resolver directamente con bash y un script breve, hacerlo en ese turno, verificar el resultado y, de forma opcional, ofrecer convertirlo en una habilidad personalizada. Esto viene acompañado de ejecución de bash en segundo plano —las tareas largas se separan del turno actual y los registros se guardan en un archivo— y directorios autorizados por el usuario.

Abierto, pero con control

Lo que más se teme al abrir puertas y ventanas es una corriente de aire. La disciplina de esta refactorización: no se modifica ni uno solo de los puntos de control de creación de procesos para "acciones peligrosas". MCP se inicia desde un único lugar, la ejecución de habilidades pasa por un único ejecutor y bash pasa por un único ejecutor en un entorno aislado. Además, se superponen varias capas de defensa:

  • Las operaciones con archivos siempre pasan por el entorno aislado de rutas —espacio de trabajo + archivos adjuntos actuales + directorios que el usuario haya autorizado explícitamente—, mientras que los directorios de credenciales, los del sistema y los propios de Orkas no se pueden autorizar;
  • Los comandos peligrosos de bash —exfiltración, eliminación destructiva, escalada de privilegios o rutas sensibles— activan una confirmación de permisos, con las opciones "solo esta vez / durante esta ejecución / denegar", y los registros solo guardan la categoría y la longitud, nunca el texto del comando;
  • La instalación de paquetes externos se bloquea de forma segura y rechaza por completo los paquetes que contienen enlaces simbólicos, para impedir que un enlace simbólico permita leer archivos sensibles fuera del entorno aislado como si estuvieran dentro de su alcance, y el origen de la clonación se restringe a una lista de protocolos permitidos;
  • Todas las configuraciones de transporte que contienen credenciales y todos los secretos se cifran en reposo, y las credenciales del puente se aíslan por ejecución;
  • La distribución de código abierto / alojada elimina las capacidades exclusivas del anfitrión mediante una regla de recorte.

En una frase: cada acción explícita del usuario —instalar / autorizar / enviar un formulario / pulsar confirmar— constituye la prueba del consentimiento, y cada consentimiento queda limitado al alcance que le corresponde.

5. Mejorar entre sesiones: memoria y autoevolución

La renovación de los cimientos también rehízo dos subsistemas que "hacen al agente más inteligente cuanto más se usa", ambos con la misma disciplina de ingeniería: desactivados de forma predeterminada, acotados y observables.

La memoria entre sesiones utiliza recuperación híbrida: búsqueda semántica vectorial + búsqueda por palabras clave (BM25), combinadas mediante RRF (fusión de rangos recíprocos) para evitar que el fallo de uno de los canales perjudique la recuperación; se guarda en almacenamiento local con un índice de texto completo. La memoria tiene dos tipos de contenido —las notas del propio agente y el perfil de preferencias del usuario—, cada uno con un límite de caracteres, analizados en busca de amenazas de inyección antes de guardarse e incorporados como una instantánea fija a las instrucciones del sistema al inicio de cada turno. Todo el sistema de memoria sirve únicamente para que el agente comprenda mejor al usuario actual; los datos siempre permanecen en el equipo local y el usuario puede verlos, editarlos y exportarlos en cualquier momento desde Configuración.

La autoevolución consiste en una biblioteca privada de habilidades del agente, almacenada por separado de la biblioteca compartida de habilidades de la plataforma, más una capa de reflexión metacognitiva. El motor decide si debe reflexionar mediante un conjunto de señales ponderadas: correcciones del usuario, con el mayor peso; recuperación de un error no trivial; complejidad de la tarea; activación o superación de una debilidad conocida; ineficacia de una habilidad... La reflexión solo se activa cuando las señales ponderadas superan un umbral. La reflexión en sí es una tarea periódica en segundo plano —aproximadamente una ronda cada 12 horas, un período de espera de varias horas y una alternativa de respaldo tras varios días— que utiliza un modelo pequeño y económico para leer un resumen de la actividad reciente y decidir si debe crear o modificar una habilidad y actualizar el "perfil de competencias" del agente.

El punto de seguridad más importante: la autoevolución solo se habilita en sesiones que tienen un agente vinculado explícitamente; la sesión predeterminada de Commander no evoluciona. La reflexión tiene un doble límite de tokens —cantidad y total—, el fallo de un agente no bloquea a los demás y el costo por ejecución se mantiene extremadamente bajo. Hacer al agente más inteligente, pero sin dejar que se descontrole.

Filosofía de ingeniería: complejidad justificada, sin eliminarla por simplificar

El equipo realizó varias rondas de revisión de arquitectura durante la refactorización, y una conclusión se repetía y merece destacarse por sí sola: distinguir la "hipertrofia organizativa" de la "complejidad justificada" y modificar únicamente la primera.

  • Las múltiples estrategias de combinación del motor de sincronización, el bucle de agente propio, la envoltura de proveedores en varias capas y el límite del control remoto móvil parecen complejos, pero cada capa justifica su existencia: consistencia eventual entre dispositivos, integración profunda, rotación de varias claves y un límite entre clientes definido por el producto. Forzar su "simplificación" solo provocaría pérdida de datos y confundiría las capas.
  • Lo que realmente debe modificarse son los "módulos omnipotentes" y la duplicación local: extraer las funciones puras sin estado del sobrecargado bus de chat grupal —ensamblado de instrucciones, herramientas de Commander y turno de la CLI— y unificar en un componente compartido el patrón de "diálogo de confirmación" que estaba duplicado varias veces.

Este criterio se apoya en un conjunto de reglas estrictas recogidas en el documento de restricciones del proyecto: límites —un solo proceso, IPC como única vía y carga del entorno de ejecución exclusivamente dinámica—, capas —la dirección de las dependencias de cada una—, una única fuente de verdad —categorías, taxonomía de telemetría y dominios— y una "auditoría de instrucciones" obligatoria en cada confirmación de cambios que afecte a las instrucciones del modelo. Lo que permite renovar los cimientos sin que todo se derrumbe no es un diseño ingenioso, sino mantener continuamente estas reglas invariables.

Cierre

Al reunir los cuatro ejes, esta refactorización desde cero dota a Orkas de unos cimientos para agentes bajo control propio, independientes del proveedor, con orquestación dinámica, abiertos al exterior y capaces de autoevolucionar:

  • Un entorno de ejecución dentro del proceso, con dos capas de motor y adaptación, que lleva al escritorio de forma nativa todas las capacidades de un agente de programación —operaciones con archivos, búsqueda local, herramientas del sistema, varios ejecutores en paralelo y resolución de tareas de largo alcance— y prepara cada una para producción;
  • Una capa de modelos de varios niveles que mantiene viva la conversación en la medida de lo posible ante problemas con claves, proveedores o redes;
  • Una orquestación de múltiples agentes al estilo de un chat grupal, con Commander dentro del bucle, que sustituye la "planificación estática" por la "decisión dinámica" y, por primera vez, hace que las transferencias entre agentes resulten naturales;
  • Un ecosistema que pasa de un catálogo cerrado a una plataforma anfitriona abierta, con apertura a paquetes externos, habilidades globales, MCP personalizados y el puente inverso, mientras los puntos de control de creación de procesos permanecen intactos;
  • Y memoria y autoevolución desactivadas de forma predeterminada, acotadas y observables.

Las funciones se pueden añadir una a una, pero solo vale la pena renovar a fondo los cimientos una vez. Una vez hecho, todo lo que se construya encima avanza más rápido, y ese es exactamente el resultado que buscaba esta refactorización.