# Guía completa: Crear un nuevo agente Esta guía documenta todos los pasos para crear, registrar, configurar y poner en marcha un nuevo bot/agente en el sistema. ## Requisitos previos - Go 1.23+ instalado (`/usr/local/go/bin`) - Acceso al homeserver Matrix (`MATRIX_HOMESERVER` y `MATRIX_ADMIN_TOKEN` en `.env`) - Variables de entorno cargadas (`.env` con todos los secretos) ## Paso 1: Crear el scaffold del agente ### Opción A: Script automático ```bash ./dev-scripts/new-agent.sh "Display Name" # Ejemplo: ./dev-scripts/new-agent.sh mi-bot "Mi Bot" ``` Esto crea la estructura base en `agents//`. ### Opción B: Manual Crear la estructura de directorios: ``` agents// ├── agent.go # Reglas puras de decisión ├── config.yaml # Configuración completa del agente ├── prompts/ │ └── system.md # System prompt para el LLM └── data/ # Runtime (auto-generado, en .gitignore) └── crypto/ # Store E2EE ``` ### 1.1 Crear `agents//agent.go` Archivo de reglas puras. El package debe exportar una función `Rules() []decision.Rule`. ```go package mibot import ( "github.com/enmanuel/agents/pkg/decision" ) // Rules returns the decision rules for this agent. func Rules() []decision.Rule { return []decision.Rule{ // !help — comando de ayuda explícito { Name: "help", Match: decision.MatchCommand("help"), Actions: []decision.Action{{ Kind: decision.ActionKindReply, Reply: &decision.ReplyAction{ Content: "Soy mi-bot. Escríbeme lo que necesitas.", }, }}, }, // Catch-all: DMs y menciones → LLM { Name: "llm-all", Match: func(ctx decision.MessageContext) bool { return ctx.IsDirectMsg || ctx.IsMention }, Actions: []decision.Action{{ Kind: decision.ActionKindLLM, LLM: &decision.LLMAction{}, }}, }, } } ``` **Reglas importantes:** - Este archivo es **puro** — sin imports de I/O, sin side effects - Solo usa types de `pkg/decision` - Las reglas se evalúan en orden; la primera que matchea gana ### 1.2 Crear `agents//config.yaml` Configuración completa del agente. Referencia: `internal/config/schema.go`. Secciones principales: | Sección | Descripción | |---------|-------------| | `agent` | Identidad: id, name, version, enabled, description, tags | | `personality` | Tono, verbosidad, idioma, templates, comportamiento | | `llm` | Provider (openai/anthropic), modelo, tokens, temperature, tool_use | | `tools` | SSH, HTTP, scripts, file_ops, MCP — cada uno con su enabled/config | | `matrix` | Homeserver, user_id, token, device_id, encryption, rooms, filters | | `agents` | Peers conocidos, delegación, protocolo inter-agente | | `ssh` | Configuración SSH (solo si aplica) | | `security` | Roles, audit, secrets provider | | `schedules` | Tareas programadas (cron) | | `observability` | Logging, metrics, health, tracing | | `resilience` | Circuit breaker, retry, shutdown, queue | | `storage` | State backend, cache, history | **Campos críticos en `matrix`:** ```yaml matrix: homeserver: "https://matrix-af2f3d.organic-machine.com" user_id: "@:matrix-af2f3d.organic-machine.com" access_token_env: MATRIX_TOKEN_ # nombre de la env var device_id: "" encryption: enabled: true store_path: "./data/crypto/" trust_mode: tofu ``` **Para habilitar tool-use:** ```yaml llm: tool_use: enabled: true # DEBE ser true max_iterations: 5 parallel_calls: false ``` ### 1.3 Crear `agents//prompts/system.md` System prompt que recibe el LLM. Debe incluir: - Identidad y rol del bot - Capacidades disponibles - Herramientas disponibles (si tool_use está habilitado) - Estilo de respuesta - Limitaciones Usar como referencia: `agents/assistant/prompts/assistant-system.md` o `agents/asistente2/prompts/system.md`. ## Paso 2: Registrar el agente en el launcher Editar `cmd/launcher/main.go`: 1. Añadir import del package del agente: ```go mibotAgent "github.com/enmanuel/agents/agents/mibot" ``` 2. Añadir entrada en `rulesRegistry`: ```go var rulesRegistry = map[string]func() []decision.Rule{ "assistant-bot": assistantagent.Rules, "mi-bot": mibotAgent.Rules, // ← nuevo "devops-bot": devopsagent.Rules, } ``` **Nota:** El ID aquí debe coincidir exactamente con `agent.id` en el `config.yaml`. ## Paso 3: Registrar en Matrix ```bash ./dev-scripts/register.sh "Display Name" ``` Este comando: 1. Crea el usuario en Synapse via admin API 2. Genera una contraseña aleatoria 3. Hace login para obtener un access token 4. Guarda `MATRIX_TOKEN_` en `.env` **Guardar la contraseña manualmente** — se necesita para la verificación E2EE: ```bash # Añadir al .env manualmente si no se guardó: MATRIX_PASSWORD_= ``` **Importante:** El script `register.sh` imprime la password en la salida. Copiarla y guardarla. ### Actualizar device_id en config.yaml El registro crea un `device_id` nuevo. Actualizarlo en `agents//config.yaml`: ```yaml matrix: device_id: "" ``` ## Paso 4: Configurar avatar y display name Colocar la imagen del bot en `static/`: ```bash # Subir avatar y sincronizar displayname desde el config ./dev-scripts/avatar.sh static/.jpg ``` Esto hace: 1. Sube la imagen al homeserver Matrix (obtiene una URL `mxc://`) 2. Establece el avatar del usuario bot 3. Sincroniza el displayname desde `agent.name` del `config.yaml` **Formatos soportados:** JPG, PNG. Recomendado: cuadrado, 256x256 o superior. ## Paso 5: Verificación E2EE (cross-signing) Sin este paso, los mensajes del bot mostrarán: **"Encrypted by a device not verified by its owner"**. ```bash go run -tags goolm ./cmd/verify \ --homeserver "https://matrix-af2f3d.organic-machine.com" \ --username "" \ --password "" \ --token "" \ --store "./agents//data/crypto/" ``` **Qué hace:** 1. Inicializa el crypto helper de mautrix 2. Genera claves de cross-signing (master + self-signing) 3. Las sube al homeserver usando UIA con la password del bot 4. Firma el device del bot con la self-signing key **Después de verificar:** Limpiar el crypto store temporal si se usó uno diferente al del agente. **Importante:** Si se cambia la password del bot (admin API), el token anterior se invalida. Hay que: 1. Re-login para obtener nuevo token 2. Actualizar `MATRIX_TOKEN_` en `.env` 3. Actualizar `device_id` en `config.yaml` 4. Borrar el crypto store viejo (`data/crypto/`) 5. Re-ejecutar `cmd/verify` ## Paso 6: Arrancar el agente ```bash ./dev-scripts/start.sh ``` Verificar que arrancó correctamente: ```bash # Ver logs tail -f run/.log # Verificar proceso ./dev-scripts/ps.sh # Estado general ./dev-scripts/list.sh ``` **Logs esperados al arrancar correctamente:** ``` {"level":"INFO","msg":"initializing e2ee","store":"data/crypto/crypto.db"} {"level":"INFO","msg":"e2ee ready"} {"level":"INFO","msg":"agent starting","id":"","tools":["current_time","matrix_send"]} {"level":"INFO","msg":"starting matrix sync"} ``` ## Paso 7: Verificar funcionamiento 1. Abrir Element u otro cliente Matrix 2. Enviar un DM al bot: `@:matrix-af2f3d.organic-machine.com` 3. Verificar que responde 4. Verificar que no aparece el warning de "device not verified" 5. Si tiene tools, probar que las usa (e.g., preguntar la hora) ## Resumen de comandos (en orden) ```bash # 1. Crear scaffold ./dev-scripts/new-agent.sh "Nombre" # 2. Editar reglas, config, prompt # agents//agent.go # agents//config.yaml # agents//prompts/system.md # 3. Registrar en launcher # Editar cmd/launcher/main.go → import + rulesRegistry # 4. Registrar en Matrix ./dev-scripts/register.sh "Nombre" # 5. Avatar y displayname ./dev-scripts/avatar.sh static/.jpg # 6. Verificación E2EE go run -tags goolm ./cmd/verify \ --homeserver "$MATRIX_HOMESERVER" \ --username "" \ --password "$MATRIX_PASSWORD_" \ --token "$MATRIX_TOKEN_" # 7. Arrancar ./dev-scripts/start.sh # 8. Verificar tail -f run/.log ``` ## Troubleshooting | Problema | Causa | Solución | |----------|-------|----------| | `env var ... is not set` | La regex del `.env` loader no matchea | Verificar que el nombre de la var solo usa `[A-Z0-9_]` | | `M_UNKNOWN_TOKEN` | Token invalidado (password cambiada) | Re-login, actualizar `.env` | | `mismatching device ID` | Crypto store con device viejo | Borrar `data/crypto/`, actualizar `device_id` en config | | `"Encrypted by device not verified"` | Falta cross-signing | Ejecutar `cmd/verify` | | Bot no responde | Reglas no matchean | Verificar que hay regla catch-all para DMs/mentions | | `no rules registered for agent` | ID no está en `rulesRegistry` | Añadir en `cmd/launcher/main.go` | | Bot muere al arrancar | Revisar logs | `tail -f run/.log` | ## Compilación Siempre usar la tag `goolm` para soporte E2EE puro (sin CGO): ```bash go build -tags goolm ./cmd/launcher go build -tags goolm ./cmd/verify go run -tags goolm ./cmd/verify --help ```