Files
agents_and_robots/docs/creating-agents.md
T
egutierrez bcbbd974e3 docs: add agent creation guide and LLM policies index
Documentación y políticas para la creación de agentes:

- docs/creating-agents.md: guía completa paso a paso para humanos
  (scaffold, config, registro Matrix, avatar, verificación E2EE, arranque,
  troubleshooting)
- .claude/policies/create_agent.md: policy para LLMs con estructura de
  archivos, convenciones y reglas a seguir al crear agentes
- .claude/policies/index.md: índice de todas las policies disponibles
- .claude/policies/create_tool.md: movido desde .claude/rules/ (misma policy)
- CLAUDE.md: añadida sección de políticas, actualizada tabla de agentes
  con asistente-2, y actualizado el flujo de "Cómo añadir un nuevo bot"
  con pasos de avatar y verificación E2EE

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:39:11 +00:00

323 lines
9.3 KiB
Markdown

# 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 <agent-id> "Display Name"
# Ejemplo: ./dev-scripts/new-agent.sh mi-bot "Mi Bot"
```
Esto crea la estructura base en `agents/<agent-id>/`.
### Opción B: Manual
Crear la estructura de directorios:
```
agents/<agent-id>/
├── 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-id>/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/<agent-id>/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: "@<agent-id>:matrix-af2f3d.organic-machine.com"
access_token_env: MATRIX_TOKEN_<AGENT_UPPER> # nombre de la env var
device_id: "<se obtiene al registrar>"
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/<agent-id>/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 <agent-id> "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_<AGENT>` 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_<AGENT>=<password_generada>
```
**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/<agent-id>/config.yaml`:
```yaml
matrix:
device_id: "<DEVICE_ID del output de register>"
```
## 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 <agent-id> static/<imagen>.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 "<agent-id>" \
--password "<password_del_bot>" \
--token "<access_token>" \
--store "./agents/<agent-id>/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_<AGENT>` 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 <agent-id>
```
Verificar que arrancó correctamente:
```bash
# Ver logs
tail -f run/<agent-id>.log
# Verificar proceso
./dev-scripts/ps.sh <agent-id>
# 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":"<agent-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: `@<agent-id>: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 <id> "Nombre"
# 2. Editar reglas, config, prompt
# agents/<id>/agent.go
# agents/<id>/config.yaml
# agents/<id>/prompts/system.md
# 3. Registrar en launcher
# Editar cmd/launcher/main.go → import + rulesRegistry
# 4. Registrar en Matrix
./dev-scripts/register.sh <id> "Nombre"
# 5. Avatar y displayname
./dev-scripts/avatar.sh <id> static/<imagen>.jpg
# 6. Verificación E2EE
go run -tags goolm ./cmd/verify \
--homeserver "$MATRIX_HOMESERVER" \
--username "<id>" \
--password "$MATRIX_PASSWORD_<AGENT>" \
--token "$MATRIX_TOKEN_<AGENT>"
# 7. Arrancar
./dev-scripts/start.sh <id>
# 8. Verificar
tail -f run/<id>.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/<id>.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
```