# 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.
