2756557498
Se estandariza la numeración de todos los issues de 3 dígitos a 4 dígitos (e.g. 005 → 0005, 010 → 0010) para mantener consistencia con la convención definida en create_issue.md. Se actualiza el README con los nuevos nombres y links. No hay cambios de contenido en los issues, solo renombrado. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
465 lines
20 KiB
Markdown
465 lines
20 KiB
Markdown
# 014 — Agente plantilla + sistema de personalidades + estandarizacion
|
|
|
|
## Objetivo
|
|
|
|
Crear un agente plantilla (no lanzable) que sirva como referencia canonica para la configuracion de todos los agentes. Incluir un sistema de personalidades rico que permita definir agentes con caracteres distintos. Enriquecer `!info` para mostrar metadata completa. Estandarizar los config.yaml existentes integrando las nuevas capacidades del proyecto: skills, shared-knowledge, cron jobs.
|
|
|
|
## Contexto
|
|
|
|
- El launcher descubre agentes via `agents/*/config.yaml` (glob en cmd/launcher/main.go)
|
|
- `!info` existe como built-in en `agents/commands.go` pero solo muestra: nombre, ID, version, descripcion
|
|
- No hay herencia de configs ni template base — cada config.yaml es autocontenido
|
|
- Agentes actuales: assistant-bot, asistente-2
|
|
- La seccion `personality` actual es basica: tone, verbosity, emoji_style, templates, behavior
|
|
- Nuevas capacidades en desarrollo: skills (016), shared-knowledge (018), cron jobs (005)
|
|
|
|
---
|
|
|
|
## Tareas
|
|
|
|
### Fase 1: Sistema de personalidades enriquecido
|
|
|
|
El sistema actual (`pkg/personality/traits.go` + `PersonalityCfg` en schema.go) define tone, verbosity, emoji, error_style, templates y behavior. Esto es funcional pero plano — todos los agentes terminan sonando igual con variaciones menores.
|
|
|
|
El objetivo es ampliar la personalidad para que cada agente tenga un **caracter unico** que se refleje en como habla, piensa y actua.
|
|
|
|
- [ ] **1.1** Ampliar `PersonalityCfg` en `internal/config/schema.go` con nuevos campos:
|
|
|
|
```go
|
|
type PersonalityCfg struct {
|
|
// --- campos existentes (sin cambios) ---
|
|
Tone string `yaml:"tone"`
|
|
Verbosity string `yaml:"verbosity"`
|
|
Language string `yaml:"language"`
|
|
LanguagesSupported []string `yaml:"languages_supported"`
|
|
EmojiStyle string `yaml:"emoji_style"`
|
|
Prefix string `yaml:"prefix"`
|
|
ErrorStyle string `yaml:"error_style"`
|
|
Templates TemplatesCfg `yaml:"templates"`
|
|
Behavior BehaviorCfg `yaml:"behavior"`
|
|
|
|
// --- NUEVOS campos ---
|
|
// Identidad narrativa
|
|
Role string `yaml:"role"` // rol principal: "asistente general", "devops engineer", "analista de datos"
|
|
Backstory string `yaml:"backstory"` // breve historia/contexto del personaje (1-3 frases)
|
|
Expertise []string `yaml:"expertise"` // areas de experiencia: ["linux", "docker", "monitoring"]
|
|
Limitations []string `yaml:"limitations"` // que NO sabe o no debe intentar
|
|
|
|
// Estilo de comunicacion
|
|
Communication CommunicationCfg `yaml:"communication"`
|
|
|
|
// Directivas de comportamiento en texto libre
|
|
CustomDirectives []string `yaml:"custom_directives"` // instrucciones adicionales para el system prompt
|
|
}
|
|
|
|
// CommunicationCfg define como se expresa el agente mas alla del tone basico.
|
|
type CommunicationCfg struct {
|
|
Formality string `yaml:"formality"` // formal | semiformal | casual | coloquial
|
|
Humor string `yaml:"humor"` // none | subtle | moderate | frequent
|
|
Personality string `yaml:"personality"` // analytical | creative | pragmatic | empathetic | assertive
|
|
ResponseStyle string `yaml:"response_style"` // structured | conversational | bullet_points | narrative
|
|
Quirks []string `yaml:"quirks"` // rasgos unicos: ["usa analogias de cocina", "cita a Linus Torvalds"]
|
|
AvoidTopics []string `yaml:"avoid_topics"` // temas que evita o redirige
|
|
Catchphrases []string `yaml:"catchphrases"` // frases tipicas que usa ocasionalmente
|
|
}
|
|
```
|
|
|
|
- [ ] **1.2** Ampliar tipos puros en `pkg/personality/traits.go`:
|
|
|
|
```go
|
|
type Formality string
|
|
const (
|
|
FormalityFormal Formality = "formal"
|
|
FormalitySemiformal Formality = "semiformal"
|
|
FormalityCasual Formality = "casual"
|
|
FormalityColoquial Formality = "coloquial"
|
|
)
|
|
|
|
type Humor string
|
|
const (
|
|
HumorNone Humor = "none"
|
|
HumorSubtle Humor = "subtle"
|
|
HumorModerate Humor = "moderate"
|
|
HumorFrequent Humor = "frequent"
|
|
)
|
|
|
|
type PersonalityType string
|
|
const (
|
|
PersonalityAnalytical PersonalityType = "analytical"
|
|
PersonalityCreative PersonalityType = "creative"
|
|
PersonalityPragmatic PersonalityType = "pragmatic"
|
|
PersonalityEmpathetic PersonalityType = "empathetic"
|
|
PersonalityAssertive PersonalityType = "assertive"
|
|
)
|
|
|
|
type ResponseStyle string
|
|
const (
|
|
ResponseStructured ResponseStyle = "structured"
|
|
ResponseConversational ResponseStyle = "conversational"
|
|
ResponseBulletPoints ResponseStyle = "bullet_points"
|
|
ResponseNarrative ResponseStyle = "narrative"
|
|
)
|
|
```
|
|
|
|
Ampliar el struct `Personality` con los nuevos campos correspondientes.
|
|
|
|
- [ ] **1.3** Crear funcion `BuildPersonalityPrompt(cfg PersonalityCfg) string` en `pkg/personality/` que genere un bloque de system prompt a partir de la config de personalidad. Esta funcion es **pura** — recibe config, devuelve string. El runtime la usa para inyectar personalidad en el prompt del LLM.
|
|
|
|
El prompt generado debe incluir:
|
|
- Rol y backstory
|
|
- Expertise y limitaciones
|
|
- Estilo de comunicacion (formality, humor, personality, response_style)
|
|
- Quirks y catchphrases
|
|
- Custom directives
|
|
- Todo redactado como instrucciones naturales para el LLM
|
|
|
|
Ejemplo de output:
|
|
```
|
|
## Tu personalidad
|
|
|
|
Eres un ingeniero DevOps senior con 10 anos de experiencia en Linux y containers.
|
|
|
|
**Rol**: DevOps engineer especializado en infraestructura y monitoring.
|
|
**Expertise**: Linux, Docker, Kubernetes, Prometheus, bash scripting.
|
|
**Limitaciones**: No das consejos de frontend ni diseno UI.
|
|
|
|
**Como te comunicas**:
|
|
- Tono semiformal, directo pero amable
|
|
- Humor sutil — algun comentario ironico cuando algo falla de forma obvia
|
|
- Estilo pragmatico — siempre priorizas la solucion sobre la teoria
|
|
- Respuestas estructuradas con comandos claros
|
|
- A veces citas a Linus Torvalds o usas analogias mecanicas
|
|
|
|
**Directivas especiales**:
|
|
- Siempre sugiere verificar con un dry-run antes de ejecutar cambios destructivos
|
|
- Cuando algo falla, muestra el log relevante antes de diagnosticar
|
|
```
|
|
|
|
- [ ] **1.4** Integrar `BuildPersonalityPrompt` en `agents/runtime.go` — concatenar el bloque de personalidad al system prompt leido del archivo. El orden debe ser: system prompt del archivo + bloque de personalidad generado.
|
|
|
|
### Fase 2: Agente plantilla con personalidades de ejemplo
|
|
|
|
- [ ] **2.1** Anadir campo `Template bool` a `AgentMeta` en `internal/config/schema.go`
|
|
|
|
- [ ] **2.2** Filtrar agentes template en `cmd/launcher/main.go` — skip si `cfg.Agent.Template == true`
|
|
|
|
- [ ] **2.3** Crear `agents/_template/config.yaml` — referencia canonica con TODAS las secciones. Incluir:
|
|
|
|
**Identidad**:
|
|
```yaml
|
|
agent:
|
|
id: "_template"
|
|
name: "Template Agent"
|
|
version: "0.0.0"
|
|
enabled: true
|
|
template: true # el launcher ignora este agente
|
|
description: "Agente plantilla. No se lanza. Sirve como referencia para crear nuevos agentes."
|
|
tags: [template]
|
|
```
|
|
|
|
**Personalidad completa** (con todos los campos nuevos documentados):
|
|
```yaml
|
|
personality:
|
|
# --- Identidad narrativa ---
|
|
role: "asistente general"
|
|
backstory: "Un asistente amigable creado para ayudar con tareas cotidianas."
|
|
expertise: [general]
|
|
limitations: []
|
|
|
|
# --- Estilo basico ---
|
|
tone: friendly # direct | friendly | formal | casual | technical
|
|
verbosity: concise # minimal | concise | detailed | verbose
|
|
language: es
|
|
languages_supported: [es, en]
|
|
emoji_style: minimal # none | minimal | moderate | heavy
|
|
prefix: ""
|
|
error_style: helpful # terse | helpful | detailed
|
|
|
|
# --- Comunicacion avanzada ---
|
|
communication:
|
|
formality: semiformal # formal | semiformal | casual | coloquial
|
|
humor: none # none | subtle | moderate | frequent
|
|
personality: pragmatic # analytical | creative | pragmatic | empathetic | assertive
|
|
response_style: structured # structured | conversational | bullet_points | narrative
|
|
quirks: [] # rasgos unicos del personaje
|
|
avoid_topics: [] # temas a evitar
|
|
catchphrases: [] # frases tipicas
|
|
|
|
# --- Directivas libres ---
|
|
custom_directives: [] # instrucciones extra para el system prompt
|
|
|
|
# --- Templates de respuesta ---
|
|
templates:
|
|
greeting: "Hola, soy {name}. En que puedo ayudarte?"
|
|
unknown_command: "No entiendo ese comando. Usa !help."
|
|
permission_denied: "No tienes permiso para eso."
|
|
error: "Algo salio mal: {{.Error}}"
|
|
success: "{{.Summary}}"
|
|
busy: "Estoy procesando otra solicitud, un momento..."
|
|
|
|
# --- Comportamiento ---
|
|
behavior:
|
|
proactive: false
|
|
ask_confirmation: false
|
|
show_reasoning: false
|
|
thread_replies: true
|
|
typing_indicator: true
|
|
acknowledge_receipt: false
|
|
```
|
|
|
|
**Skills** (nueva seccion):
|
|
```yaml
|
|
skills:
|
|
enabled: false
|
|
path: "skills/" # ruta base de skills (relativa al proyecto)
|
|
categories: [] # vacio = todas las categorias | ["devops", "system"] = filtradas
|
|
```
|
|
|
|
**Shared knowledge** (nueva seccion):
|
|
```yaml
|
|
# Dentro de tools:
|
|
tools:
|
|
# ... tools existentes ...
|
|
|
|
shared_knowledge:
|
|
enabled: false
|
|
dir: "knowledges" # directorio compartido
|
|
db_path: "knowledges/data/knowledge.db"
|
|
```
|
|
|
|
**Schedules con ejemplos**:
|
|
```yaml
|
|
schedules:
|
|
# - name: "buenos-dias"
|
|
# cron: "0 9 * * 1-5"
|
|
# action:
|
|
# kind: llm_prompt
|
|
# target: "Buenos dias equipo. Dame un resumen rapido del estado de los servicios."
|
|
# output_room: "!roomid:server.com"
|
|
# on_failure:
|
|
# notify_room: ""
|
|
# escalate_to: ""
|
|
```
|
|
|
|
Incluir TODAS las demas secciones (llm, matrix, agents, ssh, security, observability, resilience, storage, memory) con valores por defecto documentados.
|
|
|
|
- [ ] **2.4** Crear `agents/_template/agent.go` minimo con `Rules()` retornando slice vacio
|
|
|
|
- [ ] **2.5** Crear `agents/_template/prompts/system.md` con un system prompt plantilla que muestre donde va cada seccion (instrucciones base, personalidad inyectada automaticamente, tools disponibles, etc.)
|
|
|
|
- [ ] **2.6** Actualizar `dev-scripts/agent/new-agent.sh` para copiar desde `_template/` en lugar de generar inline
|
|
|
|
### Fase 3: Ejemplos de personalidades distintas
|
|
|
|
Para demostrar que el sistema funciona, definir perfiles de personalidad que se puedan usar como punto de partida. Estos van como comentarios/documentacion en el template, NO como agentes reales.
|
|
|
|
- [ ] **3.1** Documentar en `agents/_template/PERSONALITIES.md` al menos 4 perfiles de ejemplo:
|
|
|
|
**Perfil: DevOps pragmatico**
|
|
```yaml
|
|
personality:
|
|
role: "ingeniero DevOps senior"
|
|
backstory: "Veterano de infraestructura con cicatrices de guerra de incidentes en produccion."
|
|
expertise: [linux, docker, kubernetes, monitoring, bash, networking]
|
|
limitations: ["no da consejos de frontend", "no hace diseno UI"]
|
|
tone: direct
|
|
verbosity: concise
|
|
communication:
|
|
formality: semiformal
|
|
humor: subtle
|
|
personality: pragmatic
|
|
response_style: structured
|
|
quirks: ["usa analogias mecanicas", "siempre pide ver los logs primero"]
|
|
catchphrases: ["primero los logs, despues las teorias", "en produccion no se experimenta"]
|
|
custom_directives:
|
|
- "Siempre sugiere dry-run antes de cambios destructivos"
|
|
- "Incluye el comando exacto, no solo la descripcion"
|
|
```
|
|
|
|
**Perfil: Analista meticuloso**
|
|
```yaml
|
|
personality:
|
|
role: "analista de datos"
|
|
backstory: "Obsesionado con los patrones y las anomalias. Nada escapa a su atencion."
|
|
expertise: [analisis de logs, metricas, estadistica, patrones de errores]
|
|
limitations: ["no ejecuta cambios en produccion", "no toma decisiones operativas"]
|
|
tone: technical
|
|
verbosity: detailed
|
|
communication:
|
|
formality: formal
|
|
humor: none
|
|
personality: analytical
|
|
response_style: structured
|
|
quirks: ["siempre cuantifica", "pide rango de fechas antes de analizar"]
|
|
catchphrases: ["los datos no mienten", "correlacion no implica causalidad"]
|
|
```
|
|
|
|
**Perfil: Asistente amigable**
|
|
```yaml
|
|
personality:
|
|
role: "asistente personal"
|
|
backstory: "Siempre dispuesto a ayudar, paciente y claro en sus explicaciones."
|
|
expertise: [tareas generales, redaccion, organizacion, resumen]
|
|
limitations: ["no tiene acceso a servidores", "no ejecuta codigo"]
|
|
tone: friendly
|
|
verbosity: concise
|
|
communication:
|
|
formality: casual
|
|
humor: subtle
|
|
personality: empathetic
|
|
response_style: conversational
|
|
quirks: ["pregunta si quieres mas detalle", "celebra cuando termina una tarea"]
|
|
catchphrases: ["listo!", "algo mas en lo que pueda ayudar?"]
|
|
```
|
|
|
|
**Perfil: Guardian de seguridad**
|
|
```yaml
|
|
personality:
|
|
role: "especialista en seguridad"
|
|
backstory: "Paranoico profesional. Asume que todo esta comprometido hasta demostrar lo contrario."
|
|
expertise: [seguridad, auditoria, permisos, CVEs, hardening]
|
|
limitations: ["no implementa features", "no optimiza performance"]
|
|
tone: formal
|
|
verbosity: detailed
|
|
communication:
|
|
formality: formal
|
|
humor: none
|
|
personality: assertive
|
|
response_style: bullet_points
|
|
quirks: ["siempre menciona el principio de minimo privilegio", "pide MFA para todo"]
|
|
catchphrases: ["confiar pero verificar", "eso necesita un CVE review"]
|
|
custom_directives:
|
|
- "Nunca sugieras deshabilitar firewalls o SELinux como solucion"
|
|
- "Siempre recomienda rotar credenciales despues de un incidente"
|
|
```
|
|
|
|
### Fase 4: Enriquecer `!info`
|
|
|
|
- [ ] **4.1** Modificar el handler de `!info` en `agents/commands.go` para que devuelva:
|
|
- Nombre, ID, version, descripcion
|
|
- Personalidad: role, tone, formality, personality type, humor
|
|
- LLM: provider + modelo
|
|
- Tools habilitadas (lista de nombres)
|
|
- Skills habilitadas (si/no + categorias + cantidad)
|
|
- Knowledge: privado (si/no), compartido (si/no)
|
|
- Memoria: si/no + window size
|
|
- Schedules: cantidad de cron jobs configurados
|
|
- Uptime del agente
|
|
|
|
- [ ] **4.2** Formatear como markdown legible con secciones
|
|
|
|
- [ ] **4.3** No exponer datos sensibles (tokens, API keys, paths internos, passwords)
|
|
|
|
### Fase 5: Estandarizar configs existentes
|
|
|
|
- [ ] **5.1** Definir convenciones estandar obligatorias para todo config.yaml:
|
|
- `agent.version` siempre presente (semver)
|
|
- `agent.tags` siempre presente (al menos un tag)
|
|
- `personality.role` siempre presente
|
|
- `personality.language` y `personality.languages_supported` siempre explicitos
|
|
- `personality.communication` siempre presente (al menos formality y personality)
|
|
- `personality.behavior` siempre con las 6 claves
|
|
- `llm.tool_use` siempre explicito (enabled true/false, max_iterations)
|
|
- `tools.memory` y `tools.knowledge` siempre presentes (enabled true/false)
|
|
- `matrix.homeserver` y `matrix.encryption` siempre presentes
|
|
- `observability.logging.level` siempre explicito
|
|
- Si `skills.enabled: true`, al menos `skills.path` definido
|
|
- Si `schedules` tiene entradas, cada una con `name` y `cron` validos
|
|
|
|
- [ ] **5.2** Actualizar `agents/assistant-bot/config.yaml` — anadir personalidad rica:
|
|
```yaml
|
|
personality:
|
|
role: "asistente general"
|
|
backstory: "Asistente polivalente, siempre listo para ayudar con cualquier tarea."
|
|
expertise: [general, redaccion, resumen, consultas]
|
|
limitations: []
|
|
communication:
|
|
formality: semiformal
|
|
humor: subtle
|
|
personality: empathetic
|
|
response_style: conversational
|
|
quirks: []
|
|
avoid_topics: []
|
|
catchphrases: []
|
|
custom_directives: []
|
|
# ... mas secciones nuevas (skills, shared_knowledge, etc.)
|
|
```
|
|
|
|
- [ ] **5.3** Actualizar `agents/asistente-2/config.yaml` — idem, personalidad diferenciada
|
|
|
|
- [ ] **5.4** Validar que ambos agentes arrancan correctamente tras los cambios
|
|
|
|
### Fase 6: Integracion con nuevas capacidades en config
|
|
|
|
Las tasks 005 (cron), 016 (skills) y 018 (shared-knowledge) definen nuevos sistemas. El template debe incluir sus secciones de config para que nuevos agentes ya las tengan disponibles.
|
|
|
|
- [ ] **6.1** Anadir `SkillsCfg` al `AgentConfig` en schema.go (si no lo hizo la task 016):
|
|
```go
|
|
type SkillsCfg struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Path string `yaml:"path"` // default: "skills/"
|
|
Categories []string `yaml:"categories"` // filtro de categorias
|
|
}
|
|
```
|
|
|
|
- [ ] **6.2** Anadir `SharedKnowledgeCfg` al `ToolsCfg` en schema.go (si no lo hizo la task 018):
|
|
```go
|
|
type SharedKnowledgeCfg struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Dir string `yaml:"dir"` // default: "knowledges"
|
|
DBPath string `yaml:"db_path"` // default: "knowledges/data/knowledge.db"
|
|
}
|
|
```
|
|
|
|
- [ ] **6.3** Verificar que `ScheduleCfg` soporta los 3 tipos de accion (send_message, run_tool, llm_prompt) — el schema actual ya los tiene pero validar completitud
|
|
|
|
- [ ] **6.4** Actualizar el template con las secciones de skills, shared_knowledge y schedules de ejemplo
|
|
|
|
### Fase 7: Documentacion y tooling
|
|
|
|
- [ ] **7.1** Anadir validacion en `internal/config/loader.go` que emita warnings si faltan secciones recomendadas (no bloquear, solo log):
|
|
- personality.role vacio
|
|
- personality.communication sin definir
|
|
- skills.enabled true pero sin path
|
|
- schedules con entradas sin name
|
|
|
|
- [ ] **7.2** Actualizar `.claude/rules/create_agent.md` para:
|
|
- Referenciar el template como punto de partida
|
|
- Incluir paso de definir personalidad rica
|
|
- Incluir paso de decidir skills y shared-knowledge
|
|
|
|
- [ ] **7.3** Actualizar `docs/creating-agents.md` con la seccion de personalidades
|
|
|
|
- [ ] **7.4** Actualizar `CLAUDE.md` — agregar `SkillsCfg` y `SharedKnowledgeCfg` a la descripcion del schema
|
|
|
|
---
|
|
|
|
## Orden de ejecucion recomendado
|
|
|
|
1. **Fase 1** (sistema de personalidades) — tipos puros + BuildPersonalityPrompt + integracion runtime
|
|
2. **Fase 2** (template) — config.yaml canonica con todo documentado
|
|
3. **Fase 3** (ejemplos de personalidades) — PERSONALITIES.md como referencia
|
|
4. **Fase 5** (estandarizar configs) — aplicar nuevos campos a agentes existentes
|
|
5. **Fase 4** (info) — mostrar la metadata enriquecida
|
|
6. **Fase 6** (nuevas capacidades) — integrar skills/knowledge/cron en schema si no existen
|
|
7. **Fase 7** (docs) — cuando todo este estable
|
|
|
|
## Dependencias con otras tasks
|
|
|
|
| Task | Relacion |
|
|
|------|----------|
|
|
| 005 (cron) | El template incluye schedules de ejemplo. Si 005 no esta implementado, los schedules son solo config sin efecto. |
|
|
| 016 (skills) | El template incluye `skills:` config. Si 016 no esta implementado, el runtime ignora la seccion. |
|
|
| 018 (shared-knowledge) | El template incluye `shared_knowledge:` config. Si 018 no esta implementado, el runtime la ignora. |
|
|
|
|
Esta task puede ejecutarse **antes** que 005/016/018 — solo define el schema y template. Las otras tasks implementan la funcionalidad real.
|
|
|
|
## Decisiones de diseno
|
|
|
|
- **Personalidad en config, no en codigo**: la personalidad se define 100% en YAML y se transforma a prompt via `BuildPersonalityPrompt`. Cero logica de personalidad en Go.
|
|
- **BuildPersonalityPrompt es pura**: vive en `pkg/personality/`, recibe datos, devuelve string. Sin side effects.
|
|
- **Personalidad se concatena al system prompt**: no reemplaza el archivo `prompts/system.md`, se anade despues. El archivo define instrucciones base, la personalidad anade caracter.
|
|
- **Template parseable**: el config.yaml del template es YAML valido con `template: true`. Sirve como test de que el schema esta completo.
|
|
- **Backwards compatible**: los campos nuevos son opcionales. Agentes existentes sin `communication` o `role` siguen funcionando — `BuildPersonalityPrompt` genera un bloque vacio/minimo si no hay datos.
|
|
- **PERSONALITIES.md como catalogo**: no son agentes reales, son perfiles de referencia. Al crear un agente nuevo, se copia un perfil y se ajusta.
|