Bus.Publish now also appends each event to a per-topic ring buffer of
size 100. Bus.Recent(topic, n) returns the tail. New endpoint:
GET /status/recent?n=N → JSON array of last N status-diff events
This lets a fresh client (agents_dashboard launching cold) populate its
Status Feed panel with historical activity before subscribing to
/sse/status for live updates. Until now, new SSE subscribers only saw
events emitted AFTER they connected — making the panel useless for
recent history review.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Manager: RegisterUnifiedAgent/UnregisterUnifiedAgent/StopUnifiedAgent/
IsUnifiedAgentRunning/UptimeSeconds — cancela goroutines individuales sin
matar el launcher
- Manager: UptimeSeconds en AgentStatus via startedAt map
- api/server: AgentController interface + WithController/WithDataDir builders
+ rutas POST /agents/{id}/clear_memory y /agents/{id}/delete_cache
- api/handlers: handleStartAgent/Stop/Restart delegan a controller en modo
unified; Messages24h enriquecido via queryMessages24h (cache 30s)
- api/handlers: handleClearMemory — para la goroutine, borra messages+facts de
memory.db, responde {status,messages_deleted,facts_deleted}
- api/handlers: handleDeleteCache — para la goroutine, elimina crypto/ y cache/,
responde {status,paths_deleted}
- launcher/registry: launchGoroutine extrae goroutine con contexto per-agente;
deps.procMgr hookea RegisterUnified; startAgent permite relanzar via reload
- launcher/main: agentController implementa api.AgentController sobre registry;
mgr compartido entre API y registry; WithController+WithDataDir cableados
Co-Authored-By: fn-orquestador <noreply@fn-registry>
SSE clients (agents_dashboard) consider the stream connected only after
receiving the first byte of body. The previous implementation flushed
headers and then blocked waiting for status diffs (sse_status) or log
lines (sse_agents_logs) — which could be silent for minutes. UI sat
on "connecting" indefinitely.
Fix:
- After WriteHeader + Flush, emit ":ping\n\n" comment (SSE spec, valid
no-op) and flush. Unblocks client fgets immediately → state flips
to "connected" in < 1s.
- Add 15s ticker emitting ":ping\n\n" so idle streams stay alive
through Traefik / CDN proxies and clients detect dead servers.
- Same treatment for /sse/status and /sse/agents/{id}/logs (tail.go).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The logMiddleware wrapper (statusWriter) didn't forward Flush, so
`w.(http.Flusher)` in SSE handlers failed and returned the plain text
"streaming unsupported" with 500. SSE clients (agents_dashboard C++ app)
saw a closed connection with no events.
Add Flush() that delegates to the embedded ResponseWriter when it
implements Flusher. Required for /sse/status and /sse/agents/{id}/logs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
handlers + poller llamaban Manager.StatusAll() siempre. En unified mode (launcher
arranca todos los agents como goroutines bajo 1 PID) no existen PID files
por agente, asi que StatusAll devolvia Running=false aunque los agents estaban
operativos.
Anade Server.statusAllAuto() que chequea IsUnifiedRunning() y delega a
StatusAllUnified() o StatusAll() segun corresponda. Reemplaza las 3 llamadas
directas en handlers.go (handleListAgents, handleGetAgent) y poller.go
(pollStatus seed + checkAndPublishDiffs).
Sin esto el frontend (0129) mostraria running=false universal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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)
- tools/wikipedia/wikipedia.go: tool wikipedia_search que consulta la
API pública de Wikipedia (sin auth). Devuelve resumen del artículo.
- tools/exchange/exchange.go: 4 tools de tipo de cambio usando
exchangerate-api.com: exchange_rate_get, exchange_rate_convert,
exchange_rate_list, exchange_rate_historical.
- internal/config/schema.go: añadir ExchangeRateToolCfg con Enabled,
APIKey, APIKeyEnv y Timeout.
- devagents/registry_build.go: registrar ambas tool families.
wikipedia_search siempre disponible; exchange rate tools requieren
APIKey configurado (deny-by-default con WARN si falta).
- devagents/registry_build_test.go: actualizar test de registry build.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Test con directorio anidado (agents/_specials/father-bot/) que
confirma que ConfigDir se resuelve al directorio padre del config
y que system_prompt_file se puede resolver relativo a el.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Antes, el runtime construia la ruta del system prompt como
agents/<agent-id>/<file>, lo cual fallaba para agentes en
agents/_specials/ (como Father Bot). Ahora:
1. config.Load() guarda el directorio del config en ConfigDir
2. llm.go usa ConfigDir para resolver rutas relativas
Esto corrige que Father Bot operara sin su system prompt completo
(369 lineas de instrucciones, pipeline, seguridad) usando solo la
description de una linea como fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementa la Fase 1 del issue 0036: soporte de streaming en tiempo real
para el provider claude-code.
- Tipos puros de streaming en pkg/llm/types.go: StreamEventKind,
StreamEvent, StreamFunc (pure core, sin side effects)
- Refactor de shell/llm/claudecode.go: nuevo code path executeStreaming
que usa cmd.StdoutPipe + bufio.Scanner para leer linea a linea
- Parser parseStreamLine que mapea eventos JSON del CLI (system, assistant,
result) a StreamEvent del dominio
- buildClaudeArgs ahora selecciona --output-format stream-json cuando
streaming esta habilitado y StreamFunc presente
- Campos Streaming y ShowToolProgress en ClaudeCodeCfg (config schema)
- Backward compatible: streaming=false (default) no cambia comportamiento
- 40 tests (20 existentes + 20 nuevos) pasan sin errores
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- internal/config/loader.go: skip validacion de LLM provider cuando
agent.type es "robot" — los robots no usan LLM
- agents/test-bot/config.yaml: usar command_prefix: "" para que acepte
comandos sin prefijo ! (feature del issue 0033)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cuando command_prefix es "" en el config, el parser trata el primer token
del mensaje como nombre de comando sin requerir el prefijo !. Si el token
empieza con !, se le quita igualmente para retrocompatibilidad.
Cambios:
- pkg/message/parse.go: modo sin prefijo en Parse() (puro, sin side effects)
- agents/robot.go: mensaje "comando desconocido" y !help adaptados al prefijo
- agents/handler.go: mensaje "comando desconocido" adaptado al prefijo
- internal/config/schema.go: documentar command_prefix: "" en FiltersCfg
- agents/_template_robot/config.yaml: ejemplo comentado de command_prefix: ""
El comportamiento con command_prefix: "!" no cambia (retrocompatible).
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>
Tres tests para internal/config:
- TestAgentConfigParseMinimal: config minimo con campos requeridos
- TestAgentConfigIgnoresRemovedSections: YAMLs antiguos con agents/observability/
resilience siguen parseando sin error (yaml.v3 ignora campos desconocidos)
- TestAgentConfigParseFull: config completo con todas las secciones activas
incluyendo personality.communication, tools, security, storage, memory y skills
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Elimina 14 structs nunca referenciados en el codebase:
- ObservabilityCfg y sub-structs (LoggingCfg, MetricsCfg, HealthCfg, TracingCfg)
- ResilienceCfg y sub-structs (CircuitBreakerCfg, RetryCfg, ShutdownCfg, QueueCfg)
- AgentsCfg y sub-structs (PeerCfg, DelegationCfg, ProtocolCfg)
Se eliminan los campos Agents, Observability y Resilience del AgentConfig root.
CommunicationCfg se mantiene porque esta activamente usada por pkg/personality/
y agents/commands.go.
schema.go pasa de 561 lineas / 61 structs a 460 lineas / 47 structs.
El template _template/config.yaml se reduce de 414 a ~220 lineas.
Los configs de assistant-bot y asistente-2 se limpian de secciones muertas.
yaml.v3 ignora campos extra, asi que YAMLs antiguos siguen parseando sin error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementa una nueva tool que permite buscar películas y series en IMDb
usando la API de OMDb. Retorna hasta 5 resultados con título, año, tipo,
poster URL e IMDb ID.
Cambios:
- tools/imdb/imdb.go: tool imdb_search con integración a OMDb API
- internal/config/schema.go: IMDbToolCfg con api_key, api_key_env y timeout
- agents/runtime.go: registro de tool en buildToolRegistry
- agents/asistente-2/config.yaml: habilitación de tool imdb
- .env.example: OMDB_API_KEY para configuración
La tool soporta parámetros:
- query (requerido): título de película/serie a buscar
- year (opcional): año para filtrar resultados
Configuración via api_key directa o variable de entorno OMDB_API_KEY.
API key gratuita disponible en http://www.omdbapi.com/🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <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>
Agregar SkillsCfg y SkillsToolCfg al config schema:
SkillsCfg (nivel agente):
- enabled: activar/desactivar skills
- path: directorio de skills (default: skills/)
- categories: filtro de categorias a cargar
- timeout: timeout de ejecucion de scripts
SkillsToolCfg (nivel tools):
- allowed_interpreters: allowlist de interpreters (bash, python3, etc.)
Permite configurar skills por agente de forma granular.
- Nuevo tipo SharedKnowledgeToolCfg con enabled, dir, db_path
- Agregar campo SharedKnowledge a ToolsCfg
- Issue 0018: Shared Knowledge (fase 1)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implementa el cliente MCP que permite a los agentes conectarse a servidores
MCP externos y usar sus tools como si fueran tools nativas del agente.
Arquitectura implementada:
- shell/mcp/client.go: Cliente MCP con soporte stdio y SSE
- shell/mcp/manager.go: Gestor de múltiples clientes MCP
- tools/mcptools/mcp.go: Bridge que convierte MCP tools → tools.Tool
- shell/mcp/server.go: Movido desde shell/protocols/ para colocación junto al client
Cambios en config:
- MCPServerCfg extendido con campos Transport, Command, Args, Env, Headers,
Prefix, Timeout para soportar stdio y SSE transport
Integración en runtime:
- agents/runtime.go: Inicializa MCP manager si config.Tools.MCP.Enabled
- buildToolRegistry: Registra tools MCP automáticamente con prefijos configurables
- Agent: Campo mcpManager que se cierra en shutdown
Transportes soportados:
- stdio: Lanza subproceso (ej: npx -y @anthropic/mcp-server-brave-search)
- SSE: Se conecta a servidor HTTP MCP
Las tools MCP son indistinguibles de tools nativas desde el punto de vista
del LLM. Auto-discovery via ListTools(), conversión de JSON Schema a tools.Param.
🤖 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>
Se añaden tres campos nuevos a ScheduledAction en internal/config/schema.go:
- Message: texto inline para send_message
- Template: ruta a archivo .md para send_message o llm_prompt
- Prompt: texto inline del prompt para llm_prompt
Se agrega github.com/robfig/cron/v3 v3.0.1 como dependencia.
No hay cambios de ruptura: los campos son opcionales y el schema existente
sigue siendo compatible.
Implementa el soporte completo de threads de Matrix:
- Listener extrae ThreadID de m.relates_to con rel_type=m.thread
- Client.SendThreadMarkdown envia mensajes como parte de un thread
usando SetThread de mautrix con fallback m.in_reply_to
- Runner detecta ThreadID en ReplyAction y rutea a SendThreadMarkdown
- MatrixSender interfaz actualizada con SendThreadMarkdown
- runtime.go propaga ThreadID en todas las respuestas (comandos, LLM, RBAC)
- sendReply helper centraliza la logica de envio con/sin thread
- Auto-thread: si matrix.threads.auto_thread=true, crea thread nuevo
para cada conversacion que no esta ya en un thread
- Memoria por thread: usa ThreadID como clave de window cuando el mensaje
esta en un thread, permitiendo conversaciones paralelas independientes
- Config: matrix.threads.enabled y matrix.threads.auto_thread en ThreadsCfg
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Añade BasePath a StorageCfg y resolveDataBase() en runtime.go para
centralizar la resolucion del directorio base de datos del agente.
Prioridad: config storage.base_path > $AGENTS_DATA_DIR/<id> > agents/<id>/data
Esto permite mover los datos de runtime fuera del arbol del proyecto,
evitando que herramientas de desarrollo lean bases de datos, logs o
crypto stores por accidente.
Los paths de memory.db y knowledge.db ahora usan el base resuelto.
Los configs existentes no se rompen (fallback al path original).
Tareas 1.1 y 1.2 del issue 0019.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Añade rate limiting de tool calls por room usando sliding window:
- tools/ratelimit.go: RateLimiter con sliding window per key (room),
Allow() para verificar/registrar llamadas, Cleanup() para limpiar
entries expiradas
- tools/registry.go: SetRateLimiter() y ExecuteForRoom() que verifica
el rate limit antes de ejecutar, logueando tool_rate_limited si excede
- internal/config/schema.go: ToolRateLimitCfg en SecurityCfg con
enabled, max_calls_per_min y cleanup_interval_s
- agents/runtime.go: inicializa rate limiter desde config y arranca
goroutine de cleanup periodico
- agents/commands.go: usa ExecuteForRoom en !tool command
Config YAML:
security:
tool_rate_limit:
enabled: true
max_calls_per_min: 10
Parte de issue 0019c (prompt injection hardening — rate limiting).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- agents/runtime.go: campo sanitizeOpts en Agent, sanitizeInput() que
llama a sanitize.Sanitize() y loguea warnings. Integrado en
executeActions() y handleTaskEvent() antes de enviar al LLM.
En modo reject, responde al usuario y corta el flujo.
- internal/config/schema.go: nuevo tipo SanitizeCfg dentro de SecurityCfg
con campos enabled, mode, min_severity, disabled_patterns.
Protegido por feature flag prompt-injection-hardening (OFF).
Se activa por agente via security.sanitize.enabled en config.yaml.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cambios de seguridad en las 4 herramientas de agentes:
- tools/file: deny-by-default (AllowedPaths vacío = todo denegado),
resolución de symlinks con EvalSymlinks, protección contra path
traversal (../) y confusión de prefijos (/opt vs /opt1234)
- tools/ssh: nuevo AllowedCommands allowlist (complementa ForbiddenCommands),
validación de sintaxis shell (bloquea pipes, subshells, redirects, chains)
- tools/http: protección SSRF bloqueando IPs privadas, loopback, link-local,
metadata (169.254.169.254). Validación de dominio case-insensitive.
- tools/matrix: nuevo parámetro AllowedRooms para restringir rooms destino
- internal/config/schema: AllowedCommands en SSHToolCfg, MatrixToolCfg nueva
- agents/runtime: pasa MatrixToolCfg al constructor de matrix_send
Parte de issue 0019 (prompt injection hardening). Feature flag OFF.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cambios en 3 archivos:
- agents/runtime.go: construye ACL desde config de roles, verifica permisos
antes de ejecutar comandos (command:<name>), interacción LLM (ask) y
ejecución de tools (tool:<name>). Mensajes denegados se loguean y
responden al usuario.
- shell/matrix/listener.go: filtra invites y mensajes de usuarios no
autorizados cuando se configura allowed_users (allowlist vacía = todos).
- internal/config/schema.go: añade campos AllowedUsers y
UnauthorizedResponse a FiltersCfg para soportar la allowlist en config.
Esto conecta el paquete pkg/acl con el runtime para dar soporte completo
a control de acceso por rol, sin romper la compatibilidad (ACL vacío
permite todo como antes).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementa una base de conocimiento persistente por agente siguiendo
el patrón pure core / impure shell:
- pkg/knowledge/: tipos puros (Document, Store interface)
- shell/knowledge/: FileStore con SQLite para indexación y archivos .md
- tools/knowledge.go: 4 tools LLM (search, read, write, list)
- tools/knowledge_test.go: tests unitarios de las tools
- internal/config/schema.go: nuevo KnowledgeToolCfg en ToolsCfg
- agents/runtime.go: inicialización del store y registro de tools
- agents/*/knowledge/about-me.md: documentos semilla para cada agente
Cada agente puede buscar, leer, crear y actualizar documentos de
conocimiento. Los archivos .md viven en agents/<id>/knowledge/ y se
indexan en SQLite (agents/<id>/data/knowledge.db).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementa un nuevo proveedor LLM que ejecuta 'claude -p' como subproceso,
permitiendo usar Claude Code como backend de cualquier agente Matrix.
Cambios:
- pkg/llm/types.go: nueva constante ProviderClaudeCode
- pkg/llm/router.go: routing de 'claude-code' antes de 'claude*' (Anthropic API)
- internal/config/schema.go: nuevo tipo ClaudeCodeCfg con campos para binary,
timeout, disable_tools, allowed/disallowed tools, permission_mode, model,
fallback_model, session_id y add_dirs
- shell/llm/claudecode.go: provider completo — buildClaudeArgs(), flattenMessages(),
parseClaudeOutput() y filterEnv() para limpiar ANTHROPIC_API_KEY del entorno
y que claude use su propia auth OAuth
- shell/llm/factory.go: case 'claude-code' en FromConfig(), WithFallback() ahora
recibe fallbackCfg para sobreescribir model/max_tokens al hacer fallback
- agents/runtime.go: actualizado para pasar fallbackCfg a WithFallback()
No se tocó: los proveedores existentes (anthropic.go, openai.go), el core puro
de decision ni el listener de Matrix.
Se añade un mecanismo de detección de repetición para cortar conversaciones
circulares entre agentes cuando hablan sin parar.
- Nuevo campo RepetitionThreshold en OrchestrationCfg (schema.go).
- Función detectRepetition() compara cada nueva respuesta con las anteriores
usando similitud de bigramas (Dice coefficient).
- Si la similitud supera el umbral (default 0.6), el pipeline se detiene
inmediatamente con un log de warning, antes de gastar una llamada LLM
en la evaluación de calidad.
- Funciones auxiliares: similarity() y makeBigrams() para el cálculo.
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>
- 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.