# dev-scripts/agent Scripts para crear, registrar, verificar y gestionar agentes individuales en el sistema Matrix. ## Scripts ### new-agent.sh Genera el scaffold completo para un nuevo agente: `config.yaml`, `agent.go` (reglas puras), directorio de prompts y data. También registra automáticamente el import y la entrada en `rulesRegistry` de `cmd/launcher/main.go`. ```bash ./dev-scripts/agent/new-agent.sh "Display Name" ./dev-scripts/agent/new-agent.sh monitor-bot "Monitor Agent" ``` ### register.sh Registra un nuevo bot en el servidor Matrix via Synapse admin API. Genera y guarda en `.env`: access token (`MATRIX_TOKEN_*`), password (`MATRIX_PASSWORD_*`) y pickle key (`PICKLE_KEY_*`). Requiere `MATRIX_ADMIN_TOKEN` y `MATRIX_HOMESERVER` en `.env`. ```bash ./dev-scripts/agent/register.sh "Display Name" ./dev-scripts/agent/register.sh assistant-bot "Assistant" ``` ### verify.sh Verifica o regenera los dispositivos E2EE de los agentes. Genera cross-signing keys, firma el device y guarda el recovery key en `.env`. Sin este paso, los mensajes del bot aparecen como "not verified by its owner". ```bash ./dev-scripts/agent/verify.sh # verifica todos los habilitados con E2EE ./dev-scripts/agent/verify.sh assistant-bot # verifica uno específico ``` ### avatar.sh Sube una imagen como avatar del bot en Matrix y sincroniza el displayname desde el `config.yaml`. ```bash ./dev-scripts/agent/avatar.sh ./dev-scripts/agent/avatar.sh assistant-bot static/assistant.jpg ``` ### reset-password.sh Resetea la contraseña de un bot existente via Synapse admin API sin crear nueva sesión ni cambiar el device ID. El access token actual sigue siendo válido. ```bash ./dev-scripts/agent/reset-password.sh ./dev-scripts/agent/reset-password.sh assistant-bot ``` ### remove.sh Deshabilita un agente marcándolo como `enabled: false` en su `config.yaml`. No borra datos — los preserva en `agents//data/`. ```bash ./dev-scripts/agent/remove.sh ``` ### list.sh Muestra todos los agentes registrados con su estado (running/stopped/disabled), versión y descripción en una tabla formateada. ```bash ./dev-scripts/agent/list.sh ``` ## Flujo típico para un nuevo agente ```bash # 1. Crear scaffold ./dev-scripts/agent/new-agent.sh mi-bot "Mi Bot" # 2. Editar config, reglas y prompt # agents/mi-bot/config.yaml # agents/mi-bot/agent.go # agents/mi-bot/prompts/system.md # 3. Registrar en Matrix ./dev-scripts/agent/register.sh mi-bot "Mi Bot" # 4. Verificar E2EE ./dev-scripts/agent/verify.sh mi-bot # 5. Arrancar ./dev-scripts/server/start.sh ``` --- ## provision-agent-user.sh (issue 0144b) Provisiona un **agent LLM per machine** del flow 0009 — Matrix user + scaffold completo (config.yaml + agent.go + prompts/system.md) listo para ser lanzado por `cmd/launcher/`. Issue 0144 introduce dos agents por PC: `agent-` (user-scope) y `agent--sudo` (sudo-scope con approval gate). ```bash ./dev-scripts/agent/provision-agent-user.sh # agent-id ^agent-[a-z0-9-]+$ # host identificador fisico (home-wsl, aurgi-pc, rpi-garage, ...) # mode user | sudo # Ejemplos: ./dev-scripts/agent/provision-agent-user.sh agent-home-wsl home-wsl user ./dev-scripts/agent/provision-agent-user.sh agent-home-wsl-sudo home-wsl sudo ``` **Diferencia con `new-agent.sh`**: `new-agent.sh` copia el `_template` generico (LLM standard, sin device mesh). `provision-agent-user.sh` aplica plantillas especificas del flow 0009 con: - bloque `device_mesh:` declarado (manifest_id, tools_allowed, rate_limit) - system prompt host-specific (manifest, capability whitelist, sudo policy) - `agent.go` minimal que delega TODA decision al LLM (no rules) - secrets persistidos en `.env` con upsert idempotente y `chmod 0600` ### Que crea ``` agents// config.yaml ← rendered from dev-scripts/agent/templates/config..yaml.tmpl agent.go ← rendered from dev-scripts/agent/templates/agent..go.tmpl prompts/system.md ← rendered from dev-scripts/agent/templates/prompts/system..md.tmpl data/ ← mode 0700, gitignored, alberga crypto/ + memory.db .env (append/upsert): MATRIX_TOKEN_ MATRIX_PASSWORD_ PICKLE_KEY_ MATRIX_DEVICE_ID_ _DEVICE_MESH_URL ``` ### Env vars requeridos en `.env` | Var | Para que | Como obtener | |---|---|---| | `MATRIX_HOMESERVER` | URL completa del homeserver Synapse | ej. `https://matrix-af2f3d.organic-machine.com` | | `MATRIX_SERVER_NAME` | server_name (sin `https://`) | ej. `matrix-af2f3d.organic-machine.com` | | `MATRIX_ADMIN_TOKEN` | Bearer token de un user admin | Synapse `registration_shared_secret` + `register_new_matrix_user`, o login como admin existente y copiar token. Element → Settings → Help & About → Advanced → Access Token | | `OPERATOR_MATRIX_ID` | Matrix ID del humano dueno del device | ej. `@lucas:matrix-af2f3d.organic-machine.com` | | `_DEVICE_MESH_URL` | URL HTTP del `device_agent` en la mesh | opcional; default `http://10.42.0.10:7474` | ### Idempotencia Si `agents//config.yaml` ya existe, el script imprime `Already provisioned` y sale con exit 0 sin tocar nada. Para re-provisionar (Matrix user recreado, plantillas cambiadas, etc.), revoca primero con el flujo de cleanup mas abajo y vuelve a correr. ### Idempotencia interna del Synapse PUT `PUT /_synapse/admin/v2/users/` es idempotente por contrato Synapse: 200 si el user ya existe + se actualiza, 201 si es nuevo. Esto evita races cuando dos PCs corren el script casi a la vez. ### Templates Las plantillas viven en `dev-scripts/agent/templates/`. Editarlas afecta a TODO agente futuro provisionado — los existentes no se tocan (no es regenerador, es scaffolder). ``` dev-scripts/agent/templates/ config.user.yaml.tmpl ← user-scope (DM/mention → LLM con tools user|both) config.sudo.yaml.tmpl ← sudo-scope (approval flow obligatorio) agent.user.go.tmpl ← rules: LLM-all on DM/mention agent.sudo.go.tmpl ← rules: LLM-all on DM/mention/delegation prompts/system.user.md.tmpl ← system prompt user prompts/system.sudo.md.tmpl ← system prompt sudo ``` Variables que el script interpola (sed `s#token#value#g`): | Token | Ejemplo | |---|---| | `{{AGENT_ID}}` | `agent-home-wsl` | | `{{AGENT_ID_UPPER}}` | `AGENT_HOME_WSL` | | `{{HOST}}` | `home-wsl` | | `{{MODE}}` | `user` o `sudo` | | `{{PACKAGE}}` | `agenthomewsl` (sin guiones) | | `{{DISPLAY_NAME}}` | `Agent Home Wsl` | | `{{MATRIX_HOMESERVER}}` | `https://matrix-af2f3d.organic-machine.com` | | `{{MATRIX_SERVER_NAME}}` | `matrix-af2f3d.organic-machine.com` | | `{{MATRIX_DEVICE_ID}}` | `IVECMVQWNZ` (devuelto por `/v3/login`) | | `{{OPERATOR_MATRIX_ID}}` | `@lucas:matrix-af2f3d.organic-machine.com` | ### Tests ```bash ./dev-scripts/agent/provision-agent-user_test.sh ``` 20+ assertions cubriendo: - provision exitoso `user` + `sudo` - idempotencia (re-run sale 0 sin tocar) - validacion de `agent-id` regex y `mode` enum - `MATRIX_ADMIN_TOKEN` requerido - permisos `.env = 0600` - tags correctos en config por mode - `requires_approval: true` solo en sudo Mockea `PUT /_synapse/admin/v2/users` y `POST /_matrix/client/v3/login` con un servidor python local. No toca Matrix real. ### Que NO hace este script (delegado a otros) | Tarea | Script | |---|---| | Cross-signing E2EE (recovery key) | `./dev-scripts/agent/verify.sh ` | | Avatar + displayname final en Matrix | `./dev-scripts/agent/avatar.sh ` | | Blank import en `cmd/launcher/main.go` | issue 0144c (wiring multi-agent) | | Invitar al operador al room `#` | manual via Element o futura tool del bot dispatcher | | Build + start del binario | `go build -tags goolm ./... && ./dev-scripts/server/start.sh` | ### Como revocar / eliminar un agent provisionado Checklist de cleanup (revierte todos los efectos del script): ```bash AGENT_ID=agent-home-wsl AGENT_ID_UPPER=$(echo "$AGENT_ID" | tr '[:lower:]-' '[:upper:]_') # 1. Stop the launcher si esta corriendo ./dev-scripts/server/stop.sh || true # 2. Desactivar Matrix user (soft delete) ./dev-scripts/agent/deactivate-matrix.sh "$AGENT_ID" # o hard: # curl -X POST "${MATRIX_HOMESERVER}/_synapse/admin/v1/deactivate/@${AGENT_ID}:${MATRIX_SERVER_NAME}" \ # -H "Authorization: Bearer $MATRIX_ADMIN_TOKEN" -d '{"erase": true}' # 3. Eliminar env vars for var in MATRIX_TOKEN_${AGENT_ID_UPPER} MATRIX_PASSWORD_${AGENT_ID_UPPER} \ PICKLE_KEY_${AGENT_ID_UPPER} MATRIX_DEVICE_ID_${AGENT_ID_UPPER} \ SSSS_RECOVERY_KEY_${AGENT_ID_UPPER} ${AGENT_ID_UPPER}_DEVICE_MESH_URL; do sed -i "/^${var}=/d" .env done # 4. Eliminar scaffold rm -rf "agents/$AGENT_ID/" # 5. Eliminar blank import del launcher (si se anadio) ./dev-scripts/agent/remove-launcher-import.sh "$AGENT_ID" # 6. Rebuild go build -tags goolm ./... ``` ### Decisiones de diseno - **Idempotencia por presencia de `config.yaml`** y no por hash: si re-provisionas, los secrets nuevos en `.env` se actualizarian via upsert pero las plantillas locales podrian no reflejar cambios. Soft contract: re-provisionar requiere cleanup primero. - **Password persistida en `.env` con MATRIX_PASSWORD_*`**: necesaria para recovery (`reset-password.sh` reusa el flow). Si el operador prefiere zero-knowledge, puede borrarla manualmente del `.env` despues — el agent solo necesita el `access_token`. - **No BIP39 recovery_key**: el script original §5.1 del 0144 listaba `SSSS_RECOVERY_KEY_<...>` BIP39. La generacion real de cross-signing keys ocurre en `verify.sh` (cmd Go con cliente Matrix completo), no aqui. Mantenemos separacion limpia. - **No invita al room**: el dispatcher del bot (0144c) gestiona invites a `#` cuando el agent arranca. Hacerlo aqui requeriria login + join + check de room existence, fuera del scope de "provisioning de identidad". - **Templates en `dev-scripts/agent/templates/`** (no en `agents/_template_devicemesh/`) para no contaminar el listado de agents reales. El scaffolder es metadata del proceso, no un agente. - **`{{PACKAGE}}` sin guiones**: Go no acepta `-` en nombres de paquete. `agent-home-wsl` → `package agenthomewsl`. ### Output JSON Al final, el script imprime un JSON con: `agent_id`, `matrix_user`, `device_id`, `host`, `mode`, `ts`. Util para pipelining.