SPEAKER NOTES — diapositiva de título. Bienvenidos de nuevo a la Sesión 3. En la Sesión 1 construimos la base. En la Sesión 2 le dimos manos al agente. Hoy le damos personalidad, un lugar seguro para vivir en disco, y una hoja de ruta para memoria a largo plazo. También lanzamos dos nuevas herramientas de desarrollo que querrás en tu barra de tareas. Gran sesión — vamos.

SPEAKER NOTES — recapitulación. Recapitulación rápida para que los que lleguen tarde puedan ponerse al día. Sesión 1 = una aplicación de chat funcional sobre Aspire/Blazor con cinco proveedores. Sesión 2 = el bucle del agente, dos superficies de herramientas, una puerta de aprobación y los primitivos de seguridad que todo framework de herramientas necesita. Ambas sesiones están grabadas y el código está en el repositorio. Si te las perdiste, las diapositivas y demos están en docs/sessions.

SPEAKER NOTES — alcance. Seis capítulos. Los primeros dos son "lo que se lanzó desde la sesión 2 — calidad de vida y pulido de tool-calling". Los capítulos tres y cuatro son la carne — habilidades y almacenamiento. El capítulo cinco mira hacia adelante: hacia dónde va la memoria. El capítulo seis es práctico. Nos moveremos rápido en las partes de recapitulación y más lento en las decisiones de diseño.

SPEAKER NOTES — modelo mental. Toda la sesión gira en torno a esto. Habilidades = comportamiento, almacenamiento = límites. Ambas tratan de dar más autonomía al agente de forma SEGURA. No puedes lanzar habilidades si el agente puede escribir en cualquier lugar del disco; no puedes confiar en el endurecimiento del almacenamiento si cualquiera puede soltar una habilidad maliciosa. Llegan juntas.

SPEAKER NOTES — divisor Parte 1. Dos nuevas herramientas de desarrollo que lanzamos entre la Sesión 2 y la Sesión 3. Viven en la bandeja del sistema y hacen que el desarrollo diario de OpenClawNet sea mucho menos doloroso. Diez minutos en total.

SPEAKER NOTES — puntos de dolor. Esto es lo que todo desarrollador de LLM local experimenta. Olvidas iniciar Ollama, el agente expira, depuras durante diez minutos antes de darte cuenta de que el servidor del modelo ni siquiera está arriba. O tu aplicación Aspire está corriendo pero cerraste la pestaña del dashboard. Construimos dos aplicaciones de bandeja que ponen las respuestas en tu bandeja del sistema.

SPEAKER NOTES — Ollama Monitor. Primera herramienta: Ollama Monitor. Distribuida como una herramienta dotnet global — un comando para instalar, vive en tu bandeja del sistema. Verde = Ollama está arriba y sirviendo. Amarillo = arriba pero lento. Rojo = caído. Haz clic en el ícono y obtienes detalles del modelo, estadísticas de GPU, solicitudes recientes. Las notificaciones toast son la característica asesina — te enteras antes que tu demo.

SPEAKER NOTES — detalle de características. Cada cinco segundos golpeamos /api/tags y /api/ps. El sparkline muestra tokens/seg agregados a través de solicitudes activas. Detener/iniciar rápido usa el CLI de Ollama bajo el capó. Los colores de estado son deliberados — amarillo no significa roto, significa "tu laptop está en batería y el modelo está paginado". Triple falla antes de mostrar toast para no bombardearte en una red inestable.

SPEAKER NOTES — instalación. Tres líneas para instalar y ejecutar. Auto-start agrega una tarea programada de Windows al inicio de sesión — sobrevive reinicios, sin acceso directo de carpeta de inicio que gestionar. La configuración es JSON, puedes sincronizarla entre máquinas si quieres. El directorio de logs usa el patrón estándar de "datos de aplicación local" — el mismo lugar donde todas las otras aplicaciones Windows modernas ponen logs.

SPEAKER NOTES — demo. Demo en vivo si Ollama está corriendo. Clic derecho en el ícono de la bandeja. Muestra el modelo cargado, el conteo de capas GPU — para un 3B cuantizado eso debería ser 33/33 significando completamente en GPU. El sparkline muestra los últimos 60 segundos. Las solicitudes activas suben cuando disparas una solicitud de chat. El hotkey del dashboard abre una ventana más detallada con línea de tiempo por solicitud.

SPEAKER NOTES — Aspire Monitor. Segunda herramienta. Aspire Monitor resuelve un punto de dolor diferente: estás trabajando en múltiples aplicaciones Aspire, olvidas cuál está corriendo, la URL del dashboard cambia en cada reinicio. Esto se ancla a una carpeta, sabe qué AppHost vive allí, y te da iniciar/detener sin volver a la terminal.

SPEAKER NOTES — características de Aspire. La ventana fijada es la característica de la que la gente se enamora. Fijas "Gateway", "Ollama", y "Abrir Dashboard" — esos tres se quedan en una ventana flotante diminuta en la esquina de tu pantalla. Un clic y estás en cualquiera de ellos. Tras bambalinas estamos golpeando la API de recursos del dashboard de Aspire, así que obtenemos salud gratis.

SPEAKER NOTES — instalación de Aspire. Mismo patrón de instalación que Ollama Monitor — herramienta dotnet, global, no necesita admin. La bandera --auto es para CI / grabación de demo: inicia el AppHost en el momento en que se abre el monitor. Puedes correr múltiples copias apuntando a diferentes carpetas y aparecerán como íconos de bandeja separados.

SPEAKER NOTES — demo. Clic derecho en el ícono de la bandeja. Tres recursos, todos verdes, con sus endpoints. Sección fijada en la parte inferior — las tres URLs que abro diez veces al día. Iniciar/Detener/Reiniciar se aplica a todo el AppHost. Logs abre la página de logs del dashboard directamente, no la raíz del dashboard, así que te saltas un clic.

SPEAKER NOTES — divisor Parte 2. Ahora el trabajo bajo el capó. Entre la Sesión 2 y 3 hicimos un trozo de plomería en tool calling — alineación con el formato de OpenAI, una refactorización de FileSystemTool, y tres nuevos sanitizadores. Nada de esto es glamoroso; todo hace que el agente sea más confiable.

SPEAKER NOTES — por qué. Historia de origen honesta. Probamos principalmente en Ollama en la Sesión 2. Tan pronto como golpeamos Azure OpenAI y Foundry con el mismo agente, vimos diferencias sutiles en cómo se serializaban las llamadas de herramientas — orden de argumentos, comillas JSON, formas de error. Lo mismo con el FileSystemTool: se había convertido en un cajón de sastre. Esta parte de la sesión muestra qué cambiamos y por qué.

SPEAKER NOTES — formato. La forma de llamada de herramienta de OpenAI es el estándar de facto. Arguments-as-string es la verruga histórica que todos soportan porque la API original se lanzó así. Microsoft.Extensions.AI nos da la abstracción correcta (AIFunction) pero los proveedores pueden desviarse. Canonizamos todo internamente para que nunca tengamos que hacer casos especiales de "¿es esto Ollama o Azure?" en el runtime.

SPEAKER NOTES — tabla de diferencias. Qué cambió realmente. La interfaz pública ITool es idéntica — tus herramientas personalizadas de la Sesión 2 todavía compilan y corren. Lo que limpiamos es el interior: un ToolResult basado en record para que los llamadores puedan hacer pattern-match, análisis de argumentos impulsado por esquema, códigos de error estructurados, sanitizadores detrás de una interfaz. La refactorización de FileSystemTool es la que más importa para la siguiente diapositiva.

SPEAKER NOTES — refactorización. Esta es la estructura que repetiremos para las otras herramientas en las próximas sesiones. Un orquestador que elige la operación, un archivo por operación, validadores en su propia carpeta. La ganancia es testabilidad — en lugar de hacer mock de toda la herramienta, pruebas ReadOperation contra un IFileSystem falso. El PathValidator es un envoltorio delgado que delega al nuevo ISafePathResolver, que es el puente hacia la Parte 4.

SPEAKER NOTES — contrato de sanitizador. Los sanitizadores ahora son de primera clase. Cada herramienta declara qué sanitizadores necesita y se ejecutan en orden antes de que el cuerpo de la operación vea la entrada. Este es el patrón que queremos para cualquier herramienta futura: nunca confíes en cadenas suministradas por LLM, siempre sanitiza, siempre ten una razón de rechazo estructurada. La razón de rechazo fluye de vuelta al modelo para que pueda corregirse en el siguiente turno.

SPEAKER NOTES — tres sanitizadores. PathSanitizer es el puente a la Parte 4 — es la capa de cara al usuario sobre ISafePathResolver. UrlSanitizer mantiene las defensas SSRF de la Sesión 2 pero como un componente reutilizable. JsonArgumentSanitizer es el que se paga más rápido: cada vez que el modelo inventa un nombre de propiedad o envía un número como cadena, el sanitizador o lo coerciona correctamente o lo rechaza con un mensaje claro. Los tokens ahorrados en reintentos pagan el esfuerzo de ingeniería en una semana.

NOTAS DEL ORADOR — pipeline. Este es el pipeline ahora. Cuatro puertas explícitas, cada una probable de forma independiente. JsonArgumentSanitizer primero porque es gratis y rechaza la mayor parte de la basura. Luego, cualquier argumento de tipo path pasa por PathSanitizer. Después la política de aprobación. Solo entonces se ejecuta el cuerpo de la operación. Cada puerta emite un registro de auditoría al aceptar y al rechazar — H-8 en la Parte 4.

NOTAS DEL ORADOR — diff. Misma operación, dos mundos distintos. El "antes" está bien para una demo y es un disparo en el pie en producción. El "después" delega todo lo peligroso a un único resolver auditado. Sin Path.GetFullPath crudo sobre input del LLM. Sin verificación por prefijo de cadena que se rompe en C:\openclawnet vs C:\openclawnet-evil. Sin reescritura silenciosa. Este es el patrón que repetiremos para cada herramienta que reciba paths.

NOTAS DEL ORADOR — metadatos sin cambios. Tranquilidad importante. Si escribiste una herramienta personalizada en la Sesión 2, NADA CAMBIA para ti a nivel de API. Mismo ITool, mismos metadatos, misma puerta de aprobación. SÍ obtienes los nuevos sanitizers gratis si optas por usarlos. La compatibilidad hacia atrás fue un requisito firme de esta refactorización.

NOTAS DEL ORADOR — NDJSON. Un nuevo tipo de evento — ToolSanitizationFailed — emitido cuando un sanitizer rechaza una entrada antes de la aprobación. La UI lo muestra como una nota amarilla inline en la conversación para que el usuario vea "el modelo intentó leer C:\Windows\System32 y el sanitizer lo bloqueó". Esa transparencia es oro para depurar intentos de prompt-injection.

NOTAS DEL ORADOR — recompensa. Esta es la diapositiva fundacional. Ni habilidades, ni endurecimiento de almacenamiento, ni memoria podían aterrizar limpiamente sobre las internals de herramientas de la Sesión 2 tal como estaban. Tuvimos que hacer esta refactorización primero. La portabilidad entre proveedores es el gran beneficio externo; el beneficio interno es que las próximas sesiones puedan AGREGAR sin reescribir.

NOTAS DEL ORADOR — divisor de la Parte 3. La parte más grande de la sesión — unas treinta diapositivas. Las habilidades son la característica que la mayoría de los usuarios notarán primero. Archivos Markdown que cambian el comportamiento del agente. Hot-reload. Habilitación por agente. Vamos.

NOTAS DEL ORADOR — qué es una habilidad. Léelo en pantalla. Tres líneas de YAML, un párrafo de Markdown, y el agente ahora se comporta como un arquitecto sénior de .NET. Sin C#. Sin deploy. Sin reinicio. El punto que estamos haciendo toda la sesión: las habilidades son CONTENIDO, no CÓDIGO. Cualquiera del equipo puede escribir una — tu PM, tu QA, tu líder de seguridad.

NOTAS DEL ORADOR — vs herramientas. Mucha gente ve las habilidades y pregunta "¿no es solo un system prompt?" Sí — pero con estructura, ciclo de vida y auditoría. La columna crucial es "autoría". Las herramientas requieren un ingeniero; las habilidades no. Ese único hecho cambia quién en la empresa puede moldear el comportamiento del agente. La superficie de riesgo también es genuinamente distinta — las habilidades no pueden ejecutar código en v1 (S-8) pero pueden hacer prompt-injection al modelo para que haga cosas malas, por eso importan las puertas de aprobación y la habilitación por agente.

NOTAS DEL ORADOR — bug estrella. Doloroso de admitir pero vale la pena mostrarlo. Teníamos dos subsistemas de habilidades que ambos funcionaban, ninguno sabía del otro. Click en disable, el agente sigue usando la habilidad. Click en install, el archivo cae en una carpeta que el agente no escanea. El hot reload recarga el loader que el agente no usa. Esto fue el catalizador de toda la propuesta de habilidades.

NOTAS DEL ORADOR — solución. Eliminamos el cargador paralelo. MAF — Microsoft Agent Framework — ya implementa la especificación completa de agentskills.io, incluyendo divulgación progresiva, parsing de YAML y herramientas de recursos. Nuestro trabajo se vuelve un decorador delgado scoped que agrega tres cosas: atribución de capa, filtrado de habilitación por agente y logging estructurado. La UI llama a nuestro registry; el registry alimenta a MAF; MAF alimenta al agente. Un solo pipeline.

NOTAS DEL ORADOR — 3 capas. Tres capas, una regla de precedencia. System se entrega con la aplicación y es de solo lectura. Installed es compartido por todos los agentes y vive detrás del pipeline de importación. Agents-slash-name son overrides por agente — tanto para habilitación (enabled.json) como para habilidades genuinamente personalizadas. Quarantine es donde caen las importaciones antes de la aprobación. La capa más alta gana en colisiones de nombre, así que un agente puede ocultar una habilidad del sistema con la suya propia.

NOTAS DEL ORADOR — almacenamiento compartido. La decisión de Drummond del review de seguridad. La amenaza es lo que entra al system prompt en runtime, no lo que está en disco. Si copiamos cada habilidad instalada en la carpeta de cada agente, tendríamos N copias para actualizar en cada CVE. Los usuarios saltarían la puerta de aprobación solo para mantener el ritmo. Almacenamiento compartido con habilitación por agente es a la vez más seguro y más sensato.

NOTAS DEL ORADOR — frontmatter. agentskills.io es la spec abierta con la que nos alineamos. Define los campos núcleo — name, description, license — y reserva un namespace metadata para extensiones del proveedor. Nuestros extras (tags, category, examples) se mueven a metadata.openclawnet.* para ser compatibles a futuro con cualquier otro host que hable la spec. MAF parsea YAML correctamente, incluyendo strings multi-línea entrecomillados — nuestro parser hecho a mano se atragantaba con esos.

NOTAS DEL ORADOR — campos antiguos. El gran cambio es eliminar enabled-true del frontmatter mismo. Por qué: la habilitación es por agente, no por habilidad. Ponerlo en el archivo lo hace ver global. Los valores por defecto para "qué built-ins están on por defecto para nuevos agentes" se mueven a un SystemSkillsDefaults.json en el content root del gateway. Separación más limpia entre "qué es la habilidad" y "quién la tiene activada".

NOTAS DEL ORADOR — watcher. FileSystemWatcher es notoriamente ruidoso — VS Code guarda un archivo escribiendo un temp, eliminando el original y renombrando. Tres eventos por un guardado. Coalescemos con un debounce de 500ms: cualquier número de eventos dentro de la ventana colapsa en una sola reconstrucción. Watchers por capa porque las capas pueden vivir en discos o volúmenes distintos y queremos dominios de falla independientes.

NOTAS DEL ORADOR — snapshot. Decisión de diseño importante. Cuando el watcher dispara no metemos la mano en las conversaciones en curso para parchearlas. Reconstruimos un nuevo snapshot inmutable. Los turnos activos terminan en el snapshot viejo; el siguiente turno toma el nuevo. Esta es la respuesta a la pregunta abierta Q2 de Bruno en la propuesta — "¿auto-recarga a mitad de conversación? no — snapshot por turno." Evita lecturas rotas y mantiene una sola conversación determinística.

NOTAS DEL ORADOR — enabled.json. Lógica de tres valores. enabled = encendido explícito. disabled = apagado explícito. use-default = "pregúntale al registry cuál es el default" — útil para habilidades nuevas de las que el agente aún no ha sido informado. El default para habilidades externas recién importadas es disabled. El default para built-ins es enabled. El estado autoritativo vive en SQLite para poder consultar "muéstrame todo agente que tenga la habilidad X habilitada" sin leer cada archivo JSON. El JSON en disco es la proyección amigable para humanos.

NOTAS DEL ORADOR — fail closed. Esto es S-7 de la propuesta — cierre seguro. Es fricción deliberada. No queremos que un usuario acepte un diálogo de importación y que el contenido de la habilidad se cuele en el system prompt de cada agente. Dos gestos: importar y habilitar. El paso de habilitar te hace elegir qué agentes lo reciben. Si importaste por accidente, ningún agente se ve afectado.

NOTAS DEL ORADOR — página de Habilidades. Promovimos las habilidades fuera del submenú de Settings a un ítem de navegación de nivel superior. Dos mitades: Explorar (izquierda) y Actuar (derecha). La columna "Habilitada en" es la clave — de un vistazo ves qué agentes tienen qué habilidades. El modal de asignación por agente es donde cambias la habilitación; lo veremos a continuación.

NOTAS DEL ORADOR — modal de asignación. Diálogo único. Toggle por defecto en la parte superior — qué heredan los nuevos agentes. Dropdowns por agente abajo — encendido explícito, apagado explícito o "usar default". Save persiste a SQLite, la proyección de archivo se actualiza en la próxima reconstrucción de snapshot. El texto "efectivo en el siguiente turno de chat" es importante — establece expectativas sobre la semántica de hot-reload.

NOTAS DEL ORADOR — asistente de importación. Cuatro pasos, deliberadamente. Entrada recolecta la URL. Vista previa es el paso crítico para seguridad: lista completa de archivos, tamaños, SHA-256 por archivo, Markdown renderizado para que veas lo que el modelo verá, y un diff contra cualquier versión instalada previamente. La advertencia "este contenido entra al system prompt" no es descartable — esa única oración es la diferencia entre un usuario informado y un click-through.

NOTAS DEL ORADOR — allowlist. S-12 de la propuesta. v1 se entrega con una fuente confiable. El razonamiento: permitir URLs arbitrarias de GitHub convierte la importación en un primitivo de prompt injection remoto. Anclar a un commit SHA derrota ataques de time-of-check/time-of-use donde el upstream cambia entre vista previa y confirmación. Para agregar una nueva fuente, un admin edita appsettings — fricción deliberadamente alta.

SPEAKER NOTES — autoría manual. Válvula de escape crítica. La tubería de importación es la ruta más segura para compartir habilidades. Pero día a día, tú y tu equipo escribirán habilidades manualmente en su editor, las guardarán bajo agents/{name}/skills/, y el watcher las recogerá automáticamente. Sin reinicio, sin llamadas API. Así es también cómo iteras mientras escribes una habilidad — guardar, probar, guardar, probar.

SPEAKER NOTES — anatomía. Ejemplo concreto que podemos copiar y pegar. Frontmatter en la parte superior — delimitado por triple guion. Cuerpo debajo — Markdown puro. El cuerpo se convierte en parte del prompt del sistema textualmente. El array de ejemplos es solo metadatos — no se inyecta, pero la UI lo usa para mostrar sugerencias "intenta preguntar…". El archivo total suele tener menos de 2KB; el máximo que permitimos es 256 KB (S-11) para que una sola habilidad no explote tu presupuesto de tokens por accidente.

SPEAKER NOTES — limitados. Los presupuestos de tokens son dinero real. Limitamos el tamaño de cada archivo de habilidad y la contribución total al prompt del sistema. Si tres habilidades grandes están habilitadas y exceden el presupuesto, la más antigua por orden de carga se descarta — pero hacemos auditoría WARN para que puedas enterarte. El presupuesto por defecto es 8KB que cabe cómodamente en cualquier ventana de contexto moderna. Configurable por agente.

SPEAKER NOTES — S-1..S-6. Primera mitad de la lista de endurecimiento. S-1 es el manifiesto. S-2 es la lista permitida de tipos de archivo — sin .py, .ps1, .dll, sin bit ejecutable, nada que empiece con MZ o shebang. S-3 delega la resolución de rutas a la capa de almacenamiento. S-4 evita que una habilidad maliciosa reclame ser el shell-exec integrado. S-5 es previsualización/confirmación de dos pasos. S-6 significa que los cambios upstream nunca se aplican silenciosamente — ejecutas nuevamente la puerta.

SPEAKER NOTES — S-7..S-12. Segunda mitad. S-7 ya lo cubrimos. S-8 es "sin contenido ejecutable todavía" — esa es una propuesta futura con su propia caja de arena. S-9 pista de auditoría cubre cada evento del ciclo de vida para que puedas responder "quién instaló qué cuándo" forenseménte. S-10 — deshabilitar toma efecto en el siguiente turno de chat, no en el siguiente reinicio del proceso. S-11 presupuestos de tokens. S-12 lista permitida de fuentes. Doce invariantes, cada PR es revisado contra ellas, sin excepciones para v1.

SPEAKER NOTES — registro. Catorce eventos estructurados que cubren el ciclo de vida completo. Los generadores de código LoggerMessage nos dan registro de asignación cero en las rutas críticas. Ocho campos de correlación significa que una sola consulta SQL puede responder "muéstrame todo lo que pasó durante el último turno de chat de este usuario incluyendo qué habilidades se cargaron, qué funciones se invocaron, qué intentos de importación hubo". Los spans OTel van directamente al panel de Aspire que viste en la Parte 1.

SPEAKER NOTES — qué no registramos. Regla crítica de sensibilidad. Los valores de parámetros pueden contener cualquier cosa — claves API, contraseñas, PII. Valores de retorno también. Los cuerpos de SKILL.md son controlados por el atacante, así que registrarlos amplifica ataques de inyección de log. Registramos ESQUEMA — tipos y formas — más tamaño y un hash parcial. Eso es suficiente para forense, no suficiente para filtrar. Recomendación de Dylan en la propuesta.

SPEAKER NOTES — E2E. Seis pruebas end-to-end son los criterios de aceptación para K-1 (la ola fundacional). Cada una es una solicitud HTTP real contra una gateway en ejecución. La prueba de recarga en caliente suelta un archivo y espera un turno. La prueba por agente afirma aislamiento. La prueba de importación ejercita la tubería completa de previsualización-confirmación-instalación incluyendo verificación SHA y limpieza de cuarentena. Ejecutamos estas en CI en cada PR.

SPEAKER NOTES — olas. Cuatro olas. K-1 es la fundación — eliminar el cargador paralelo, obtener un registro. K-2 es observabilidad. K-3 es la tubería de importación. K-4 es pulido de UX. La flecha de dependencia en la parte inferior es el remate de toda esta sesión: las habilidades dependen del almacenamiento. No podemos escribir contenido proporcionado por el usuario al disco de forma segura hasta que la capa de almacenamiento imponga contención. Que es exactamente la Parte 4.

SPEAKER NOTES — divisor de Parte 4. Veinte diapositivas sobre almacenamiento. Esta es la parte portante de la sesión. Sin H-1..H-8, las habilidades no pueden enviarse de forma segura; sin una raíz predeterminada sensata, los usuarios no pueden encontrar sus archivos. Ambos problemas, un diseño.

SPEAKER NOTES — pregunta de Bruno. Cita directa del issue que empezó esto. Bruno quiere UNA raíz, descubrible, predecible. El predeterminado de hoy está enterrado en bin/Debug/net10.0/ — inútil para usuarios finales. Necesitamos arreglar el predeterminado Y endurecer cada ruta de código que toma una ruta del LLM.

SPEAKER NOTES — qué estaba mal. Seis problemas concretos. Cinco sobre descubribilidad. Uno sobre seguridad. La última viñeta es la peligrosa: incluso después de que arreglamos el predeterminado a C:\openclawnet, el agente TODAVÍA podía escribir en cualquier parte del disco emitiendo una ruta absoluta. Redirección no es restricción. La revisión de endurecimiento hizo eso explícito.

SPEAKER NOTES — predeterminados. Así es como se ve tu C:\openclawnet después de la Sesión 3. Siete subcarpetas bien conocidas, cada una con un propósito claro. Los agentes obtienen su propia carpeta por nombre de agente — base para futura aislación por agente. Los modelos son compartidos. Workspaces son áreas de scratch nombradas por usuario. Uploads y exports separan archivos de usuario entrantes de salientes. Skills viste. Dataprotection-keys lo cubriremos en la diapositiva de ACL.

SPEAKER NOTES — config. Tres fuentes. La variable de entorno gana para que contenedores y CI puedan sobrescribir sin tocar JSON. Appsettings es la respuesta cotidiana. El predeterminado integrado se activa para UX de primera ejecución. AdditionalWritablePaths es la lista permitida explícita para "sí, quiero que el agente también pueda escribir aquí" — usado con cuidado. El log INFO de inicio es la recomendación de endurecimiento: la mala configuración se vuelve visible en el panel, no silenciosa.

SPEAKER NOTES — nombre único. Modelo de amenaza sutil de Drummond. Si respetas tanto OPENCLAWNET_STORAGE_ROOT como OPENCLAW_STORAGE_DIR, un atacante que puede configurar una pero no la otra en un contenedor mal configurado redirige todas tus escrituras. Elige un nombre, documéntalo en voz alta, ignora todo lo demás. El log de inicio incluye la FUENTE del valor — variable de entorno, appsettings, o predeterminado — para que la mala configuración esté a un vistazo del panel de Aspire.

SPEAKER NOTES — resolvedor. El punto único de estrangulamiento. Cada herramienta que toma una ruta delega a este resolvedor. Dentro de él, todos los invariantes de endurecimiento viven en UNA clase comprobable — no cinco copias en cinco herramientas. El parámetro scope es la costura para futura aislación por agente: hoy predetermina a RootPath; mañana podemos pasar agents/{name}/ sin romper la API.

SPEAKER NOTES — H-1. Invariante más importante. Cada escritura — cada una — tiene que aterrizar bajo la raíz de almacenamiento o bajo una lista permitida de rutas adicionales explícitas. Las lecturas pueden ser más amplias porque las lecturas son de menor riesgo y a veces legítimamente necesitas mirar un proyecto hermano. La decisión de diseño crucial: RECHAZAR, no REESCRIBIR. Si el LLM emite C:\Windows\System32, decimos "no" — no decimos "redigiré silenciosamente eso a C:\openclawnet\Windows\System32".

SPEAKER NOTES — H-2. La regla de "detener implementaciones proliferantes". La forma más confiable de asegurar que cada resolución de ruta esté endurecida es tener solo UN lugar que lo haga. Tenemos un elemento de lista de verificación de revisión de código: cualquier herramienta nueva que tome una cadena de ruta debe inyectar ISafePathResolver y delegar. Sin excepciones. Las pruebas unitarias adversarias viven junto a ella.

SPEAKER NOTES — H-3. Sutil. Path.GetFullPath NO sigue puntos de reanálisis — resuelve .. y barras redundantes, pero una unión de directorio dentro de la raíz de almacenamiento apuntando a C:\Windows pasa la verificación de prefijo. Usamos ResolveLinkTarget en la ruta final Y en cada directorio padre. Sí, es costoso en rutas frías; cacheamos. Los enlaces simbólicos creados por el agente están prohibidos de plano — demasiado fácil de usar como escondite.

SPEAKER NOTES — H-4. Bug de prefijo de cadena que muerde a cada biblioteca de manejo de rutas en algún punto. C:\openclawnet vs C:\openclawnet-evil — mismo prefijo, directorio diferente. La corrección es requerir igualdad O startswith de root+separador. Hay una prueba de regresión para este par exacto para que una refactorización futura no pueda reintroducir el bug.

SPEAKER NOTES — H-5. Adiós a la vieja lista de denegación de tres subcadenas. Lista permitida gana a lista de denegación cada vez. Límite de sesenta y cuatro caracteres porque MAX_PATH de Windows se pone feo después de eso. Nombres de dispositivos reservados — CON, PRN, AUX, NUL, COM1-9, LPT1-9 — son especiales en Windows y crearían un directorio que no puedes eliminar. Puntos y espacios finales también: Windows los elimina silenciosamente, así que "foo." y "foo" colisionan de formas sorprendentes.

SPEAKER NOTES — H-6. Con visión de futuro. Hoy el runtime del agente pasa scope=null y el resolvedor usa RootPath. Mañana cuando enviemos aislación multi-agente — agente de Slack vs agente de Telegram vs agente de investigación — el runtime puede pasar agents/SlackAgent/ y esa única invocación de agente solo puede escribir en su propio subárbol. La filtración entre agentes se vuelve imposible. Hoy: solo el parámetro. Mañana: la política.

SPEAKER NOTES — H-7. Endurecimiento de ACL para los directorios que contienen secretos. Por defecto C:\openclawnet hereda de la raíz del volumen, que en la mayoría de las instalaciones de Windows otorga Users(OI)(CI)M — cada usuario local puede leerlo. Ese es el predeterminado incorrecto para un directorio que contiene claves de DataProtection de ASP.NET, tokens OAuth, y futuros bóvedas de claves API. Establecemos una DACL explícita en los subdirectorios de credenciales al inicio: usuario actual + SYSTEM, sin herencia. POSIX obtiene chmod 0700. Si falla la verificación, rechazamos iniciar los servicios que portan credenciales con un mensaje de remediación claro.

SPEAKER NOTES — H-8. Cada escritura al disco deja un rastro. Las escrituras exitosas obtienen la ruta resuelta, conteo de bytes, SHA-256 del contenido, atribución de fuente (¿fue esto sugerido por el LLM o explícito del usuario?), ids de correlación. Las escrituras fallidas — path traversal bloqueado, ACL denegada, fallo de lista permitida de nombres — también son auditadas en WARN con la cadena de entrada original no resuelta para forense. Combinado con auditoría de habilidades (S-9 de la Parte 3) puedes decir exactamente qué pasó durante cualquier turno de chat.

SPEAKER NOTES — resumen. Ocho invariantes en una diapositiva. Memoriza estos — son el contrato que cualquier código que tome rutas debe satisfacer. Igual que la lista de habilidades S-1..S-12, cada PR se revisa contra ellos. Tenemos pruebas unitarias cubriendo cada uno con casos adversarios.

SPEAKER NOTES — conexión. Tres métodos de extensión, en este orden. AddOpenClawStorage vincula StorageOptions, asegura el árbol de directorios y ejecuta el endurecimiento de ACL. AddSafePathResolver registra el resolvedor singleton. AddOpenClawTools conecta cada herramienta incorporada para usar el resolvedor. Las herramientas personalizadas solo inyectan ISafePathResolver y están listas.

SPEAKER NOTES — interfaz de configuración. Hasta ahora tenías que saber sobre Storage:RootPath en appsettings para siquiera verificar dónde iban los archivos. La página Settings ahora tiene una tarjeta Storage mostrando la raíz actual, la FUENTE (para que sepas si vino de env o config), y espacio libre. Mover-raíz requiere un reinicio por diseño — no queremos migrar escrituras en vivo. El estado de ACL expone violaciones de H-7 como puntos rojos.

SPEAKER NOTES — migración. Eliminamos el sufijo /storage entre lanzamientos. Las instalaciones existentes perderían el rastro de sus archivos a menos que manejemos la migración explícitamente. En el primer arranque detectamos el diseño antiguo, preguntamos al usuario, y ya sea movemos atómicamente o mantenemos la raíz antigua fija vía config. El flag de CLI existe para despliegues desatendidos donde no es posible preguntar.

SPEAKER NOTES — divisor de Parte 5. La parte prospectiva. La memoria está mayormente diseñada, parcialmente construida, y la versión de grado de producción es lo que la Sesión 4 recogerá. Ocho diapositivas sobre cuál es el problema, cuál es la estrategia y qué viene después.

SPEAKER NOTES — problema de ventana de contexto. Por qué importa la memoria. Incluso con una ventana de contexto de 128K, cada turno reenvía todo el historial. Después de 100 mensajes tus prompts son enormes, tu latencia es alta, tu GPU está caliente, y el modelo empieza a perder el medio del contexto de todos modos (el problema de atención en forma de U). Truncamiento ingenuo — soltar los N más antiguos — significa que el agente olvida el nombre del usuario. Ambos son malos.

SPEAKER NOTES — estrategia. Estrategia de tres niveles. Los mensajes recientes se mantienen verbatim porque el modelo los necesita palabra por palabra para coherencia. Los mensajes más antiguos colapsan en un resumen de párrafo. Los mensajes muy antiguos están fuera del prompt activo completamente pero almacenados en un índice vectorial — el agente puede recuperarlos por similitud semántica cuando sea relevante. Este es el patrón estándar en todos los frameworks de agentes modernos.

SPEAKER NOTES — entidad. Una entidad pequeña de EF Core. SessionId es la clave foránea, Summary es la prosa real, CoveredMessageCount le dice al compositor de prompt "los primeros N mensajes de esta sesión están resumidos — empieza verbatim desde el mensaje N+1". Cada resumen es inmutable; se agregan nuevos resúmenes en lugar de actualizarse, para que podamos reconstruir cualquier vista histórica de la conversación.

SPEAKER NOTES — interfaz. Tres métodos. Obtener el último resumen para que el compositor pueda inyectarlo. Almacenar un nuevo resumen cuando el umbral se dispara. GetStatsAsync alimenta el panel de memoria de UI. El patrón factory es el correcto para servicios async — servicio singleton, DbContext con alcance por llamada, sin trampas de seguridad de hilos. El umbral de 20 mensajes es configurable por sesión.

SPEAKER NOTES — embeddings. Los embeddings son la primitiva que potencia la búsqueda semántica. Microsoft ofrece APIs de embedding administradas pero para desarrollo local-primero usamos Elbruno.LocalEmbeddings que envuelve ONNX. 384 dimensiones es el tamaño all-MiniLM — diminuto, rápido, suficientemente bueno para recuperación conversacional. El ejemplo muestra la ganancia: "dependency injection" e "IoC container" se embeben a vectores que son 0.82 similar por coseno aunque no comparten palabras superficiales.

SPEAKER NOTES — búsqueda semántica. El eventual tercer nivel. Cada mensaje se embebe una vez y se almacena en caché. Llega una nueva pregunta, la embebemos, ejecutamos un escaneo de similitud de coseno sobre embeddings de mensajes pasados, tomamos los top K, inyectamos esos fragmentos como contexto adicional. SQLite no es una base de datos vectorial pero a escala de historial de conversación (miles de mensajes) es perfectamente adecuado — usamos una columna BLOB serializada y un top-K hecho a mano. Si creces más allá de eso, intercambia DuckDB o un almacén vectorial real sin cambio de API.

SPEAKER NOTES — panel. La transparencia es una característica. Los usuarios entran en pánico cuando una IA afirma "recordar" cosas — quieren saber cómo. El panel muestra mensajes totales, cuántos están resumidos (y en cuántos resúmenes), cuántos están aún verbatim, cuándo se disparó el último resumen, y el impacto en tokens. El número "eran 26 K" es el más poderoso — muestra el ahorro sin resumen en términos concretos.

SPEAKER NOTES — qué viene. Dónde estamos: el diseño está hecho, la entidad existe, las interfaces son estables. Lo que falta: un resumidor robusto que maneje fallas de modelo con gracia, un índice vectorial real, aislamiento de memoria por agente, e importación-exportación. Todo eso llega en Sesión 4 junto con proveedores en la nube y el programador. Para el final de Sesión 4 el agente recordará a través de reinicios y a través de sesiones.

SPEAKER NOTES — divisor de Parte 6. Tres demos, ocho minutos en total. Iniciaremos la pila, golpearemos la API de habilidades, y soltaremos una habilidad autoral manual para probar hot-reload.

SPEAKER NOTES — demo 1. Demo en vivo. aspire run en el repo, observa Aspire Monitor en la bandeja ponerse verde a medida que los recursos suben. Abre el dashboard, desplaza el log para encontrar la línea de almacenamiento que enviamos esta sesión — "Storage root resolved to C:\openclawnet (source: default)". Source es el valor que la revisión de endurecimiento pidió. Si la variable env está configurada, muestra "source: env". Si appsettings, "source: config". Visible de un vistazo.

SPEAKER NOTES — demo 2. Curl al endpoint de habilidades. Dos habilidades, ambas capa de sistema, ambas habilitadas para GptAgent. Nota la forma por agente: enabledFor es un array, no un booleano global. POST disable, luego envía un mensaje de chat — el agente responde sin la habilidad de memoria en su prompt. Verificamos revisando la auditoría de prompt. Esta es la API unificada que la diapositiva de error titular prometió.

SPEAKER NOTES — demo 3. El demo "wow". Crea una habilidad en tiempo real. Guarda el archivo. Observa el log de gateway emitir SkillDiscovered y SkillLoaded — eso es el FileSystemWatcher y la reconstrucción del registro disparándose. Envía un mensaje de chat en la UI y la respuesta es de repente dos oraciones y carece de "aprovechar". Sin reinicio. Sin despliegue. Sin código. Ese es todo el discurso en 60 segundos.

SPEAKER NOTES — divisor de cierre. Dos diapositivas más una diapositiva de pregunta.

SPEAKER NOTES — perspectivas. Cinco conclusiones. Las habilidades son contenido no código — esa es la ganancia más visible para el usuario. El almacenamiento es fail-closed — esa es la ganancia de seguridad. La memoria es transparente — esa es la ganancia de confianza. La portabilidad de llamada de herramientas es la ganancia de ingeniería. Los monitores de bandeja son la ganancia de experiencia de desarrollador. Cada ítem mapea a una de las seis partes de la sesión.

SPEAKER NOTES — lo que construimos. Doce marcas de verificación. La mitad son visibles para el usuario (monitores, página de habilidades, tarjeta de configuración). La mitad son calidad bajo el capó (refactors, sanitizadores, endurecimiento). Las dos mitades van juntas: las características visibles para el usuario solo son seguras PORQUE el trabajo bajo el capó llegó primero. Esa es la lección de la sesión 3.

SPEAKER NOTES — vista previa de Sesión 4. Hacia dónde vamos después. Proveedores en la nube significa que el mismo agente se ejecuta contra Azure OpenAI sin cambios de código — el trabajo de alineación de llamada de herramientas en la Parte 2 es lo que hace eso posible. La programación significa trabajos impulsados por cron que el agente ejecuta autónomamente. La memoria a escala termina el trabajo que esbozamos en la Parte 5. Las pruebas + health checks convierten el demo en un despliegue. La Sesión 4 es el final.

SPEAKER NOTES — cierre. Gracias a todos. El repo es github.com/elbruno/openclawnet, licencia MIT. Todo lo de hoy — diapositivas, script del orador, prompts de copilot, los documentos de propuesta — vive bajo docs/sessions/session-3/. Las dos nuevas herramientas se instalan con un comando dotnet tool install -g y viven en tu bandeja. Si quieres extender algo, el drop-in manual de habilidad es el punto de partida más gratificante: escribe un SKILL.md, guárdalo, ve al agente cambiar. ¿Preguntas?