Nuevo paquete internal/api con servidor HTTP stdlib (sin gin/echo):
- Auth Bearer via AGENTS_API_KEY con subtle.ConstantTimeCompare
- REST: GET /health (sin auth), GET/POST /agents, /agents/{id}, /{id}/{start,stop,restart,logs}
- SSE: /sse/status (broadcast diffs cada 2s) y /sse/agents/{id}/logs (tail -f)
- Pubsub in-memory (TODO: NATS cuando haya 2do cliente)
- Tail de logfiles: retroalimenta ultimos 50KB + poll 200ms para streaming
Integracion en cmd/launcher/main.go:
- Flag --api-port (0=desactivado, 8487 en produccion)
- Flag --api-key (override de AGENTS_API_KEY env var)
- Si apiPort>0 y sin clave, WARN y deshabilita en vez de fallar
Systemd unit en systemd/agents_and_robots.service:
- Restart=always (no on-failure — evita que exit limpio mate el service)
- EnvironmentFile para AGENTS_API_KEY y demas tokens
- WorkingDirectory=/home/ubuntu/CodeProyects/agents_and_robots
app.md v0.2.0:
- port: 8487, health_endpoint: /health (fix drift anterior donde era null)
- e2e_checks: build, tests, smoke_health, smoke_auth
- Documentacion Traefik+DNS pendiente humano post-merge
Tests: 12 tests unitarios en internal/api (auth, health, bus, agents, logs)
Smoke: /health 200, /agents sin auth 401, /agents con key 200 — verificado local
Co-Authored-By: fn-constructor (agent)
El launcher salia con status=0 cuando todos los runners (Agent/Robot)
terminaban su Run() de forma natural — por ejemplo tras una rotacion de
token de Matrix o un drop del sync. systemd, configurado con
Restart=on-failure, no relanzaba el proceso al ver salida limpia y los
bots quedaban caidos hasta una intervencion manual.
Solucion: nueva rutina superviseUntilCanceled en agentRegistry que
bloquea sobre waitAll, y si el ctx padre sigue vivo, espera un backoff
y llama reloadAll para recrear los runners. Solo cuando el ctx padre
se cancela (SIGINT/SIGTERM) la rutina retorna y el launcher sale.
main.go pasa a invocar este supervisor en lugar de waitAll directo.
Tests:
- TestSuperviseUntilCanceled_ReturnsWhenCtxCanceledFirst — empty registry
- TestSuperviseUntilCanceled_ReturnsAfterCtxCancelDuringBackoff — cancel
durante el backoff debe desbloquear inmediatamente
- TestSuperviseUntilCanceled_CallsReloadOnAgentExit — supervisor sigue
vivo todo el deadline aunque reload falle por cfgPath invalido
Diagnostico: tras varias horas el journalctl mostraba "Deactivated
successfully" sin "Stopping" previo (Apr 13 18:22 tras 23h corriendo)
y el log del agent registraba "context canceled" tras "starting matrix
sync" — sintoma de que mautrix.SyncWithContext salio limpiamente y el
ctx.cancel se propago al cerrar la goroutine sin que systemd hubiera
enviado SIGTERM. El bucle supervisado lo arregla recreando los runners
sin tocar la unit ni depender del Restart de systemd.
Agente LLM (GPT-4o) especializado en crear, listar, completar y buscar
recordatorios con fechas y horarios. Almacena los datos en JSON usando
file_ops (read_file/write_file) con allowlist a /tmp/reminder-bot-data/.
Incluye tool_use habilitado con file_ops y current_time. System prompt
con seccion de seguridad anti-injection. Registrado en el launcher.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminar el early-return `if len(loadedSpecials) == 0 { return false }`
que causaba que el config del orchestrator (disabled/fallido) se intentara
cargar como agente normal, fallando con "agent.id is required".
Ahora la función parsea el YAML con LoadSpecial y devuelve true si
cfg.Special.ID != "" — independientemente de si el agente arrancó.
Esto silencia el error recurrente en cada inicio del launcher.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TestResolveACL_PrivilegedVsGeneral: verifica que father-bot solo
es accesible por admins y que agentes generales son accesibles
por todos. Reproduce la config real de produccion.
- TestIsSpecialConfig_*: 3 tests para la funcion que detecta
configs de SpecialConfig ya cargados (orchestrator) y los salta
en el loop de discovery normal del launcher.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
El launcher ahora escanea agents/_specials/*/config.yaml ademas de
agents/*/config.yaml para descubrir agentes del sistema con identidad
Matrix (ej: father-bot). Los SpecialConfig ya cargados (orchestrator)
se detectan y saltan via isSpecialConfig() para evitar errores de
validacion.
Tambien actualiza dev-scripts/_common.sh para que config_path_for()
y list_agents_raw() incluyan _specials/ en la busqueda.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nuevo sistema de generacion automatica de avatares:
- pkg/avatar/ — tipos puros y URL builders para proveedores gratuitos:
DiceBear (bottts, pixel-art, etc.), RoboHash (robots, monsters),
Multiavatar (multicultural). Sin I/O.
- shell/avatar/ — fetcher impuro: descarga imagen por HTTP a temp file.
- agentctl auto-avatar <id> — genera, descarga, sube y activa avatar
con un solo comando. Soporta --provider, --style, --set, --dry-run.
Respeta pure core / impure shell. El seed del avatar es el agent ID,
asi cada bot obtiene una imagen unica y determinista.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Expone las funciones separadas de profile.go como CLI:
- agentctl upload-media <id> <path> — sube sin activar avatar
- agentctl set-avatar-url <id> <mxc://...> — activa un mxc ya subido
Complementa la refactorizacion de shell/matrix/profile.go.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Establece la convención de que directorios con prefijo _ en agents/
son del sistema (templates, specials), no agentes desplegables.
Cambios:
- Renombrar agents/specials/ → agents/_specials/
- Actualizar path en cmd/launcher/main.go (startOrchestrator)
- Documentar convención _ en CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- !echo <texto>: repite el texto recibido (util para assertions exactas)
- !dice / !dado: lanza un dado aleatorio (1-6)
- Registro en cmd/launcher/main.go via testbot.Commands()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Crea shell/audit/ con Writer que escribe eventos de auditoria a archivo
JSONL y opcionalmente a un room Matrix. Integra la emision de eventos
en los puntos clave del runtime:
- message_received: al recibir cualquier evento Matrix (handler.go)
- command_exec: al ejecutar un comando (handler.go)
- tool_exec: al ejecutar una tool (tools/registry.go via AuditFunc callback)
- llm_request / llm_error: al llamar al LLM (llm.go)
El Writer se inicializa en agents/runtime.go si security.audit.enabled=true.
Usa patron de inyeccion de dependencias (MatrixSender como funcion,
AuditFunc como callback) para evitar acoplamiento entre packages.
Incluye tests completos para el Writer: escritura JSONL, filtrado por
Include, modo solo-file, modo solo-room, auto-set de timestamp.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce la separacion Robot vs Agent en el sistema:
- agents/types.go: interfaz Runner comun (Run, Stop, Done, RegisterCommand)
que tanto Agent como Robot satisfacen
- agents/robot.go: struct Robot — runtime minimo que solo conecta a Matrix
y despacha comandos. Sin LLM, reglas, memoria, knowledge, skills ni tools.
Mensajes normales se ignoran silenciosamente
- internal/config/schema.go: campo Type en AgentMeta ("agent"|"robot")
- cmd/launcher: usa Runner interface para manejar ambos tipos uniformemente.
Si cfg.Agent.Type == "robot" crea NewRobot en vez de New (tanto en
arranque como en hot-reload)
- agents/_template_robot/config.yaml: plantilla minima (~55 lineas) para
robots command-only
El Robot soporta built-in commands reducidos (help, ping, status, info,
version) y comandos custom via RegisterCommand. No incluye tools, tool,
clear ni prompts ya que no tiene LLM ni memoria.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce un registro global de reglas en agents/registry.go con
Register() y GetRules(). Cada paquete de agente se auto-registra
via init(), eliminando la necesidad de editar manualmente el map
rulesRegistry en cmd/launcher/main.go.
Cambios:
- agents/registry.go: nuevo registro global con sync.RWMutex
- agents/*/agent.go: cada agente llama agents.Register() en init()
- agents/_template/agent.go: placeholder AGENT_ID_PLACEHOLDER para scaffold
- cmd/launcher/main.go: elimina rulesRegistry, usa blank imports +
agents.GetRules() para obtener reglas por agent ID
Patron: init() + blank import (estandar Go: database/sql, image codecs)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fase 1: Sistema de personalidades enriquecido
- Ampliar PersonalityCfg con role, backstory, expertise, limitations
- Añadir CommunicationCfg (formality, humor, personality, response_style, quirks, catchphrases)
- Crear tipos puros en pkg/personality/traits.go
- Implementar BuildPersonalityPrompt() para generar bloque de system prompt
- Integrar personalidad en agents/runtime.go (FromConfig + concatenacion al system prompt)
Fase 2: Agente plantilla
- Añadir campo Template bool a AgentMeta
- Filtrar agentes template en launcher (skip si template: true)
- Crear agents/_template/ con config.yaml completo y documentado
- Incluir TODAS las secciones (skills, shared_knowledge, schedules, security)
- agent.go minimo + prompts/system.md plantilla
- Actualizar dev-scripts/agent/new-agent.sh para copiar desde _template/
Fase 3: Ejemplos de personalidades
- Crear agents/_template/PERSONALITIES.md con 4 perfiles:
* DevOps pragmatico
* Analista meticuloso
* Asistente amigable
* Guardian de seguridad
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Migrar admin a security/user-groups.yaml (admins group)
- agents.New() ahora acepta acl.ACL pre-resuelta como parámetro;
elimina construcción interna desde cfg.Security.Roles
- cmd/launcher: carga shellsecurity.Load("security/") al arranque;
si falla, WARN + política vacía (open access). Para cada agente
llama pksecurity.ResolveACL y pasa la ACL a agents.New()
- cmd/launcher/registry.go: stores secPolicy en launchDeps para
que reload() también resuelva ACL centralmente
- shell/matrix/listener.go: elimina invite gating y allowlist check
basados en AllowedUsers; el control de acceso lo hace el runtime
- internal/config/schema.go: depreca campos Roles y AllowedUsers
(backward compat, no eliminados)
- agents/*/config.yaml: elimina bloques security.roles y allowed_users
- dev/feature_flags.json: activa centralized-security-groups (enabled: true)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- shell/bus/bus_test.go: tests de Subscribe/Send/Unsubscribe incluyendo
idempotencia, canal cerrado tras unsubscribe y resubscribe posterior.
- cmd/launcher/registry_test.go: tests para readReloadTarget (archivo
ausente, vacío, '*', agentID, whitespace).
- agents/lifecycle_test.go: tests para Agent.Stop()/Done() verificando
que Stop() desbloquea Run y que es seguro llamarlo múltiples veces o
con cancel nil.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nuevo subcomando: agentctl reload [agent-id]
- Sin argumento: elimina run/reload.txt y envía SIGHUP → todos los
agentes se recargan.
- Con agent-id: escribe run/reload.txt con el ID y envía SIGHUP → solo
ese agente se recarga.
Si el launcher no está corriendo, muestra error claro.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implementa el mecanismo de hot-reload descrito en el issue 0013:
- agents/runtime.go: añade Agent.Stop() y Agent.Done() para ciclo de vida
individual. Run() crea un contexto hijo cancelable y cierra el canal
done al retornar.
- cmd/launcher/registry.go (nuevo): agentRegistry rastrea agentes vivos
por ID. Métodos: register, stopAndWait, reload, reloadAll, waitAll,
cleanupLogs. reload() sigue el flujo completo: stop→wait→unsubscribe
→reload config→recreate→rewire bus/orch→start nueva goroutine.
- cmd/launcher/main.go: usa agentRegistry en lugar de sync.WaitGroup.
Añade handler de SIGHUP en goroutine separada que lee run/reload.txt
para determinar el agente objetivo (* o vacío = todos). Tras leer,
borra run/reload.txt para no afectar el siguiente SIGHUP.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nuevo agente Matrix especializado en consultas meteorológicas.
Usa la API pública Open-Meteo (sin API key) para obtener
condiciones actuales y previsión de 3 días para cualquier ciudad.
Incluye:
- agents/meteorologo/ — reglas puras, config.yaml, system prompt
- tools/weather.go — tool get_weather (geocoding + forecast)
- Registro en runtime.go (tool registry) y launcher (rulesRegistry)
El agente responde a DMs y menciones delegando al LLM con tool_use
habilitado. No tiene comandos directos (!xxx).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Registra un connection hook en el driver modernc/sqlite que ejecuta
PRAGMA journal_mode=WAL y PRAGMA busy_timeout=5000 en cada conexión nueva.
Esto previene errores SQLITE_BUSY cuando múltiples goroutines escriben
concurrentemente (crypto sync de mautrix + memory store + knowledge store).
Incluye tests que verifican:
- Pragmas aplicados correctamente en cada conexión
- Escrituras concurrentes sin error (mismo sql.DB y conexiones separadas)
- Archivo -wal creado en disco confirmando WAL activo
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Se propaga *slog.Logger a todos los componentes impuros del shell:
- shell/bus/ — logs de subscribe, send, reply, timeout, unsubscribe
- shell/effects/ — duración y resultado de cada action ejecutada
- shell/llm/ (anthropic, openai, factory) — request/response con tokens, duración, fallback
- shell/memory/sqlite — open, save, recall, close con detalles
- shell/ssh/ — inicio, fin, errores y duración de comandos SSH
- tools/registry — registro, ejecución y errores de herramientas
Se usa el paquete shell/logger para field names consistentes (FieldDurationMS, FieldTokensUsed, etc.).
Cada componente recibe el logger por inyección de dependencias, sin globals.
Las firmas de New/FromConfig se actualizan para aceptar *slog.Logger.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Se integra shell/logger en cmd/launcher para que cada agente escriba
sus logs en logs/<agent-id>/YYYY-MM-DD.jsonl. Nuevo flag --log-dir
(default: "logs", "stdout" para consola). El launcher y cada agente
tienen su propio logger con cleanup automático al apagar. Se actualiza
dev-scripts/logs.sh para leer desde la nueva estructura de directorios.
Se corrige .gitignore: "launcher" → "/launcher" para no ignorar cmd/launcher/,
y se añade logs/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementa el sistema de orquestación para salas Matrix con múltiples bots.
El orquestador es un "special agent" sin identidad Matrix que coordina qué bot
responde y cuándo, usando LLM (Claude) para routing y evaluación de calidad.
Cambios principales:
- pkg/orchestration/task.go: tipos puros (TaskEvent, BotResponse, QualityScore, RoutingDecision)
- shell/orchestration/: runtime del orquestador (orchestrator.go, router.go, evaluator.go)
- agents/specials/orchestrator/: config + prompts (routing, quality, refinement)
- internal/config/: SpecialConfig, OrchestrationCfg, LoadSpecial()
- shell/bus/bus.go: protocolo request-reply (SendAndWait, Reply) para delegación
- shell/matrix/listener.go: InterceptFunc para interceptar eventos en salas orquestadas
- agents/runtime.go: SetBus, listenBus, handleTaskEvent para recibir tareas del orquestador
- cmd/launcher/main.go: creación de bus compartido, arranque del orquestador antes de bots
Incluye deduplicación para evitar que múltiples listeners en la misma sala
disparen el orquestador más de una vez por mensaje.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Renombrar directorios de agentes para que coincidan exactamente con el
agent.id del config.yaml, eliminando la disonancia entre nombres:
- agents/assistant/ → agents/assistant-bot/ (ID: assistant-bot)
- agents/asistente2/ → agents/asistente-2/ (ID: asistente-2)
Se actualizan los imports en cmd/launcher/main.go, los store_path de
crypto, los paths de storage/logs/audit en ambos configs para que
apunten a ./agents/<agent-id>/data/. También se corrige el memory.db
que se creaba en directorios fantasma fuera del directorio real del
agente.
Se eliminan las referencias a devops-bot en el config de assistant-bot
(peers, delegation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nuevo agente asistente-2 con herramienta current_time habilitada para
demostrar el flujo completo de tool-use (LLM → tool call → resultado → respuesta).
Incluye:
- agents/asistente2/: reglas puras, config con tool_use.enabled, system prompt
- tools/time.go: herramienta current_time (siempre disponible para todos los agentes)
- cmd/verify/: comando para subir cross-signing keys y eliminar el warning
"Encrypted by a device not verified by its owner"
- Registro en runtime.go (current_time) y launcher/main.go (rulesRegistry)
El cmd/verify usa mautrix GenerateAndUploadCrossSigningKeysWithPassword
para configurar cross-signing via UIA con la password del bot.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Añade avatar.go que implementa los subcomandos avatar y displayname
de agentctl. Ya existía en el proyecto pero no estaba commiteado.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementa un dashboard interactivo con bubbletea siguiendo el patrón
pure core / impure shell del proyecto:
- pkg/tui/ (PURE): Model, Update, View — solo fmt y strings, cero I/O.
Update produce Intent[] (datos puros) en vez de side effects.
- shell/tui/ (IMPURE): Adapter convierte Intent[] en tea.Cmd[] con I/O real
(process management, /proc stats, log tail).
- cmd/dashboard/ (composición): Bridge conecta pure Update con shell Adapter
usando la Elm Architecture de bubbletea.
Pantallas: Main Menu → Agent List → Agent Actions (start/stop/restart/kill) → Logs.
Navegación: flechas ↑↓, Enter seleccionar, 0 volver, q salir.
Dependencias añadidas: bubbletea, lipgloss.
Actualiza .gitignore para anclar binarios a raíz (/agentctl, /dashboard).
Documenta nuevos scripts en CLAUDE.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extrae toda la lógica de gestión de procesos (scan, start, stop, kill, stats,
log tail) de cmd/agentctl/main.go a shell/process/manager.go como paquete
reutilizable siguiendo el patrón impure shell del proyecto.
agentctl queda como thin wrapper sobre process.Manager — misma funcionalidad,
mismo comportamiento. El nuevo paquete será compartido por el TUI dashboard.
Añade funcionalidad nueva al Manager: Stats() para métricas de /proc,
LogTail() para últimas N líneas, Stop() con espera graceful + SIGKILL fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Implemented the assistant bot with basic command handling and LLM routing.
- Created configuration file for the assistant bot with personality, behavior, and LLM settings.
- Added system prompt for the assistant bot to define its capabilities and limitations.
- Developed registration script for creating Matrix bot users via Synapse admin API.
- Introduced common development scripts for agent management (start, stop, list, logs).
- Scaffolded new agent creation script to streamline the addition of new agents.
- Implemented agent removal script to disable agents without deleting data.