Agrega 8 tests para buildToolRegistry() que verifican: - Config minima: solo tools always-on (current_time, get_weather, matrix_send) - HTTP habilitado/deshabilitado: http_get y http_post - FileOps read-only: registra read_file y list_directory pero NO write/append/delete - FileOps read-write: registra todas las 5 file tools - IMDb habilitado: imdb_search - SSH habilitado: ssh_command - Conteo total: 12 tools con todo habilitado (sin deps externas) Estos tests validan la logica condicional de registro que ahora vive en registry_build.go, separada del runtime principal.
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.
Inicio rápido
# 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 |
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
# 1. Clonar y entrar al repo
git clone <repo-url>
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
# 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
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:
make build # genera bin/launcher, bin/agentctl, bin/register
./bin/agentctl list
Crear un bot nuevo
# 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:
# 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/<id>/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/<id>/agent.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
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/