Files
agents_and_robots/dev/issues/completed/0028-decouple-launcher.md
T
egutierrez dacf241806 docs: cerrar issue 0028 — desacoplar launcher del registro estatico
Mover issue a completed/ y actualizar README con estado completado.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:21:30 +00:00

110 lines
4.1 KiB
Markdown

# 0028 — Desacoplar launcher del registro estatico de agentes
## Objetivo
Eliminar la necesidad de editar `cmd/launcher/main.go` cada vez que se añade un agente. Reemplazar el `rulesRegistry` hard-coded con auto-discovery basado en la convencion de directorios.
## Contexto
- Actualmente `cmd/launcher/main.go` importa cada paquete de agente explicitamente:
```go
import (
assistantagent "github.com/enmanuel/agents/agents/assistant-bot"
asistente2agent "github.com/enmanuel/agents/agents/asistente-2"
)
var rulesRegistry = map[string]func() []decision.Rule{...}
```
- Cada agente nuevo requiere: añadir import + añadir entrada al map + recompilar
- El script `dev-scripts/agent/new-agent.sh` ya modifica el launcher automaticamente, pero es fragil (sed sobre codigo Go)
- Contradiccion: el launcher hace glob de `agents/*/config.yaml` para descubrir configs, pero luego necesita imports estaticos para las reglas
## Arquitectura
```
agents/registry.go NEW → registro global de reglas (init-based)
agents/<id>/agent.go → cada agente se auto-registra via init()
cmd/launcher/main.go → eliminar rulesRegistry, usar agents.GetRules(id)
```
### Patron pure core / impure shell
- `pkg/` — sin cambios
- `shell/` — sin cambios
- `agents/` — nuevo registry global + init() en cada agente
- `cmd/launcher/` — simplificacion
## Tareas
### Fase 1: Crear registry de reglas
- [ ] **1.1** Crear `agents/registry.go` con `Register(id, rulesFn)` y `GetRules(id)`
- [ ] **1.2** Usar sync.Mutex o sync.Map para seguridad en init()
### Fase 2: Migrar agentes a auto-registro
- [ ] **2.1** En `agents/assistant-bot/agent.go` añadir `func init() { agents.Register("assistant-bot", Rules) }`
- [ ] **2.2** Repetir para `asistente-2` y `meteorologo`
- [ ] **2.3** Actualizar `agents/_template/agent.go` con el patron init()
### Fase 3: Simplificar launcher
- [ ] **3.1** Eliminar imports explicitos de agentes en `cmd/launcher/main.go`
- [ ] **3.2** Añadir blank import: `_ "github.com/enmanuel/agents/agents/assistant-bot"` (etc.)
- [ ] **3.3** Reemplazar `rulesRegistry[id]` con `agents.GetRules(id)`
- [ ] **3.4** Si no hay reglas registradas para un agent id, log warning y usar reglas vacias (command-only bot)
### Fase 4: Actualizar scripts
- [ ] **4.1** Simplificar `dev-scripts/agent/new-agent.sh` — ya no necesita editar el map, solo añadir blank import
- [ ] **4.2** Actualizar `.claude/rules/create_agent.md` con el nuevo patron
### Fase 5: Tests
- [ ] **5.1** Test para `agents/registry.go` (register, get, get-missing)
- [ ] **5.2** `go build -tags goolm ./...` compila
- [ ] **5.3** `go test -tags goolm ./...` pasa
### Fase 6: Cleanup
- [ ] **6.1** Actualizar `CLAUDE.md` seccion sobre registro en launcher
- [ ] **6.2** Eliminar codigo muerto del launcher
---
## Ejemplo de uso
Antes (crear agente):
```go
// cmd/launcher/main.go — editar manualmente
import newagent "github.com/enmanuel/agents/agents/new-bot"
var rulesRegistry = map[string]func() []decision.Rule{
"new-bot": newagent.Rules, // añadir esta linea
}
```
Despues:
```go
// agents/new-bot/agent.go — auto-registro
func init() {
agents.Register("new-bot", Rules)
}
// cmd/launcher/main.go — solo blank import
import _ "github.com/enmanuel/agents/agents/new-bot"
```
## Decisiones de diseno
- **init() + blank import**: patron estandar en Go (database/sql drivers, image codecs). Simple y familiar
- **Blank imports en launcher**: siguen siendo estaticos en el codigo, pero son una linea trivial sin logica. El script de scaffolding puede añadirla sin riesgo de romper sintaxis Go
- **No plugin system dinamico**: Go no tiene plugins portables. init() es el mecanismo idomatic
## Prerequisitos
- Ninguno (puede hacerse independiente de otros issues)
## Riesgos
- **Orden de init()**: Go garantiza init() dentro de un paquete, pero no entre paquetes. Mitigacion: el registro es un map simple, el orden no importa
- **Olvidar blank import**: si no se añade el blank import, el agente no se registra y el launcher lo trata como command-only. Mitigacion: el script de scaffolding lo añade automaticamente