# agents_and_robots Plataforma en Go para gestionar bots Matrix autónomos. Cada bot combina un **core puro** (personalidad, reglas de decisión, transformaciones) con un **shell impuro** (conexión Matrix, SSH, LLM, side effects), conectados a un servidor Matrix self-hosted. > **CI/CD**: push a Gitea → webhook → deploy_server → `bash build.sh` → `systemctl restart`. --- ## Inicio rápido ```bash # 1. Compilar todo ./build.sh # 2. Cargar variables de entorno source .env # 3. Lanzar la TUI interactiva (dashboard) ./bin/dashboard ``` ### Dashboard TUI El dashboard es una interfaz de terminal interactiva (bubbletea) para gestionar los bots del servidor: ``` ./bin/dashboard ``` Desde la TUI puedes: - **Agents** — ver estado de cada agente, iniciar/detener/reiniciar/kill individual, ver logs - **Server** — operaciones masivas: start all, stop all, restart all, kill all con resumen de estado ### Otros binarios | Binario | Uso | |---------|-----| | `./bin/launcher` | Inicia uno o varios agentes como procesos | | `./bin/agentctl` | CLI: `list`, `start`, `stop`, `remove` | | `./bin/register` | Registra bots en Synapse via admin API | | `./bin/dashboard` | TUI interactiva para gestión de bots | --- ## HTTP API (v0.1) El launcher expone una API REST + SSE cuando se arranca con `--api-port `. ### Arrancar con API habilitada ```bash # Requiere AGENTS_API_KEY en .env (generar con: openssl rand -hex 32) ./bin/launcher --log-level info --api-port 8487 # Con systemd (VPS): sudo systemctl start agents_and_robots.service ``` ### Autenticacion Todos los endpoints (excepto `/health`) requieren: ``` Authorization: Bearer ``` Comparacion con `crypto/subtle.ConstantTimeCompare` — resistente a timing attacks. ### Endpoints REST ```bash # Liveness (sin auth) curl http://localhost:8487/health # Listar agentes curl -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents # Detalle + logs de un agente curl -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot # Control curl -X POST -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot/stop curl -X POST -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot/start curl -X POST -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot/restart # Logs snapshot curl -H "Authorization: Bearer $AGENTS_API_KEY" "http://localhost:8487/agents/assistant-bot/logs?n=50" ``` ### Endpoints SSE ```bash # Stream de cambios de estado (stop/start) — un evento por transicion curl -N -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/sse/status # Tail en vivo del logfile de un agente (< 1s de lag) curl -N -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/sse/agents/assistant-bot/logs ``` ### En produccion (VPS) El VPS expone la API via Traefik con TLS en `agents.organic-machine.com`. Los pasos DNS + Traefik los configura el humano tras el merge (ver `app.md` seccion Traefik). ```bash # Con Traefik configurado: curl -fsS -H "Authorization: Bearer $AGENTS_API_KEY" https://agents.organic-machine.com/agents ``` --- ## Principio de diseño El proyecto usa el patrón **pure core / impure shell**: ``` Mensaje Matrix │ ▼ Parse() ← puro: produce MessageContext │ ▼ Evaluate() ← puro: produce []Action (solo datos, sin efectos) │ ▼ Runner.Execute() ← impuro: interpreta las acciones → envía mensajes, ejecuta SSH, llama LLM ``` Nada dentro de `pkg/` tiene efectos secundarios. Todo el I/O vive en `shell/`. --- ## Estructura ``` agents_and_robots/ │ ├── pkg/ ← PURE CORE — sin side effects │ ├── decision/ engine de reglas: Evaluate(), Rule, Action, MatchFunc │ ├── llm/ tipos LLM: CompleteFunc, CompletionRequest │ ├── tools/ specs declarativas: SSHCommandSpec, HTTPCallSpec... │ ├── message/ parse y format de mensajes │ └── personality/ tipos de personalidad del bot │ ├── shell/ ← IMPURE SHELL — todo el I/O │ ├── llm/ clientes reales: Anthropic, OpenAI/Ollama │ ├── matrix/ cliente mautrix-go: envío, sync, listener │ ├── ssh/ ejecución SSH real (golang.org/x/crypto/ssh) │ ├── effects/ Runner: interpreta []Action → side effects │ ├── bus/ mensajería inter-agente via Go channels │ └── protocols/ MCP server/client (mark3labs/mcp-go) │ ├── agents/ ← definición de cada bot │ ├── runtime.go Agent{}: ensambla core + shell │ └── assistant/ reglas + config del assistant-bot │ ├── internal/config/ esquema YAML completo + loader con env vars │ ├── cmd/ │ ├── launcher/ inicia uno o varios agentes │ ├── agentctl/ CLI: list, start, stop, remove │ └── register/ registra bots en Synapse via admin API │ ├── dev-scripts/ scripts bash para el día a día │ ├── server/ gestión del launcher (start, stop, restart, ps, logs, dashboard) │ └── agent/ gestión de agentes (new, register, verify, avatar, remove, list) ├── config/ configuración global (matrix.yaml, servers.yaml) └── .env.example plantilla de variables de entorno ``` --- ## Requisitos - Go 1.23+ - Servidor Matrix (Synapse) con acceso admin - API key de OpenAI o Anthropic (según el bot) --- ## Setup inicial ```bash # 1. Clonar y entrar al repo git clone cd agents_and_robots # 2. Copiar y rellenar variables de entorno cp .env.example .env # Editar .env con: MATRIX_HOMESERVER, OPENAI_API_KEY, etc. # 3. Descargar dependencias go mod tidy ``` --- ## Registrar y arrancar un bot ```bash # Registrar el bot en el servidor Matrix (necesita MATRIX_ADMIN_TOKEN en .env) ./dev-scripts/agent/register.sh assistant-bot "Assistant" # → imprime el token, copiarlo a .env como MATRIX_TOKEN_ASSISTANT # Ver todos los bots y su estado ./dev-scripts/agent/list.sh # Iniciar ./dev-scripts/server/start.sh assistant-bot # Ver logs en vivo ./dev-scripts/server/logs.sh assistant-bot # Detener ./dev-scripts/server/stop.sh assistant-bot ``` --- ## CLI — agentctl ```bash go run ./cmd/agentctl list # ver todos los bots go run ./cmd/agentctl start assistant-bot # iniciar go run ./cmd/agentctl stop # detener todos go run ./cmd/agentctl remove assistant-bot # deshabilitar (sin borrar datos) ``` O compilando los binarios: ```bash make build # genera bin/launcher, bin/agentctl, bin/register ./bin/agentctl list ``` --- ## Crear un bot nuevo ```bash # 1. Generar el scaffold completo ./dev-scripts/agent/new-agent.sh monitor-bot "Monitor Agent" ``` Genera: ``` agents/monitor-bot/ ├── config.yaml ← configuración completa, lista para editar ├── agent.go ← reglas puras con help + LLM fallback └── prompts/ └── system.md ← system prompt del LLM ``` El script imprime los dos pasos manuales que quedan: ```bash # 2. Añadir al registro en cmd/launcher/main.go: import monitoragent "github.com/enmanuel/agents/agents/monitor-bot" var rulesRegistry = map[string]func() []decision.Rule{ "monitor-bot": monitoragent.Rules, // ← añadir aquí ... } # 3. Registrarlo en Matrix y arrancar ./dev-scripts/agent/register.sh monitor-bot "Monitor Agent" # → añadir token a .env ./dev-scripts/server/start.sh monitor-bot ``` --- ## Configuración de agentes Cada `agents//config.yaml` soporta: | Sección | Qué controla | |---------|--------------| | `agent` | identidad, versión, tags, enabled | | `personality` | tono, verbosidad, idioma, emoji, templates de respuesta, comportamiento | | `llm` | provider (anthropic/openai/ollama), modelo, fallback, rate limits, tool use | | `tools` | SSH, HTTP, scripts, file_ops, MCP (habilitados por bot) | | `matrix` | homeserver, user_id, rooms, filtros de mensajes, E2EE | | `agents` | peers con los que colabora, delegación, protocolo | | `ssh` | inventario de targets con hosts, users, jump host | | `security` | RBAC por roles, audit log, gestión de secrets | | `schedules` | tareas cron automáticas con acciones SSH/script | | `observability` | logging, métricas Prometheus, health check, tracing | | `resilience` | circuit breaker, retry, graceful shutdown, queue | | `storage` | estado SQLite/Redis, caché, historial de conversación | Las variables del sistema se referencian como `${NOMBRE_VAR}` y se expanden en tiempo de carga. --- ## Reglas de decisión Las reglas de cada bot se definen como datos puros en `agents//agent.go`: ```go func Rules() []decision.Rule { return []decision.Rule{ { Name: "deploy-staging", Match: decision.And( decision.MatchCommand("deploy"), func(ctx decision.MessageContext) bool { return len(ctx.Args) > 0 && ctx.Args[0] == "staging" }, ), Actions: []decision.Action{{ Kind: decision.ActionKindSSH, SSH: &tools.SSHCommandSpec{Target: "staging", Command: "..."}, }}, }, // catch-all: DMs y menciones van al LLM { Name: "llm-fallback", Match: func(ctx decision.MessageContext) bool { return ctx.IsDirectMsg || ctx.IsMention }, Actions: []decision.Action{{Kind: decision.ActionKindLLM, LLM: &decision.LLMAction{}}}, }, } } ``` Predicados disponibles: `MatchCommand`, `MatchPrefix`, `MatchMinPowerLevel`, `MatchAny`, `And`, `Or`. Tipos de acción: `reply`, `ssh`, `http`, `script`, `file_ops`, `mcp`, `llm`, `delegate`. --- ## Bots incluidos ### assistant-bot Asistente general con GPT-4o. Responde a DMs y menciones. Sin acceso a herramientas — solo LLM. ``` @assistant-bot:matrix-af2f3d.organic-machine.com ``` --- ## Dependencias | Librería | Versión | Uso | |----------|---------|-----| | `maunium.net/go/mautrix` | v0.21.1 | Cliente Matrix, sync, E2EE | | `github.com/sashabaranov/go-openai` | v1.36.1 | OpenAI API y compatibles (Ollama) | | `github.com/mark3labs/mcp-go` | v0.44.1 | MCP protocol server/client | | `golang.org/x/crypto` | v0.31.0 | SSH | | `github.com/spf13/cobra` | v1.8.1 | CLI | | `gopkg.in/yaml.v3` | v3.0.1 | Config | --- ## Makefile ```bash make build # compila todos los binarios en bin/ make list # agentctl list make start # start todos (AGENT=id para uno) make stop # stop todos (AGENT=id para uno) make tidy # go mod tidy make clean # elimina bin/ y run/ ```