Files
egutierrez fc86edd94c chore: auto-commit (27 archivos)
- .claude/CLAUDE.md
- .claude/rules/create_agent.md
- agents/_specials/father-bot/prompts/system.md
- agents/_template/config.yaml
- agents/_template_robot/config.yaml
- cmd/agentctl/autoavatar.go
- cmd/launcher/sqlite.go
- dev-scripts/_common.sh
- dev-scripts/agent/create-full.sh
- dev-scripts/agent/delete-full.sh
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 19:38:16 +02:00

368 lines
9.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# new-agent.sh — genera el scaffold de un nuevo agente
#
# Uso:
# ./dev-scripts/agent/new-agent.sh <agent-id> [displayname]
#
# Ejemplo:
# ./dev-scripts/agent/new-agent.sh monitor-bot "Monitor Agent"
#
# Crea:
# agents/<agent-id>/config.yaml (copiado desde agents/_template/)
# agents/<agent-id>/agent.go (copiado desde agents/_template/)
# agents/<agent-id>/prompts/ (copiado desde agents/_template/prompts/)
# agents/<agent-id>/data/ (directorio de datos, en .gitignore)
#
# También te recuerda los dos pasos manuales que quedan.
source "$(dirname "$0")/../_common.sh"
load_env
need_arg "${1:-}"
ID="$1"
DISPLAYNAME="${2:-$ID}"
PACKAGE="$(echo "$ID" | tr '-' '_' | sed 's/_bot//')" # "monitor-bot" → "monitor"
NORM="$(normalize_id "$ID")" # "monitor-bot" → "MONITOR_BOT"
DIR="agents/$ID"
TEMPLATE="agents/_template"
[[ -d "$DIR" ]] && fail "Ya existe agents/$ID — ¿ya fue creado?"
[[ ! -d "$TEMPLATE" ]] && fail "No existe el directorio _template en agents/_template/"
info "Creando scaffold para $ID desde _template..."
mkdir -p "$DIR/prompts" "$DIR/data"
# ── Copiar config.yaml desde template y personalizar ─────────────────────
cp "$TEMPLATE/config.yaml" "$DIR/config.yaml"
sed -i "s/_template/$ID/g" "$DIR/config.yaml"
sed -i "s/Template Agent/$DISPLAYNAME/g" "$DIR/config.yaml"
sed -i "s/template: true/template: false/g" "$DIR/config.yaml"
sed -i "s/enabled: true/enabled: true/g" "$DIR/config.yaml"
sed -i "s/MATRIX_TOKEN_TEMPLATE/MATRIX_TOKEN_${NORM}/g" "$DIR/config.yaml"
sed -i "s/PICKLE_KEY_TEMPLATE/PICKLE_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/SSSS_RECOVERY_KEY_TEMPLATE/SSSS_RECOVERY_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/SSSS_RECOVERY_KEY_ROBOT/SSSS_RECOVERY_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/MATRIX_TOKEN_ROBOT/MATRIX_TOKEN_${NORM}/g" "$DIR/config.yaml"
sed -i "s/PICKLE_KEY_ROBOT/PICKLE_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/@template:matrix.example.com/@$ID:\${MATRIX_SERVER_NAME}/g" "$DIR/config.yaml"
sed -i "s|https://matrix.example.com|\${MATRIX_HOMESERVER}|g" "$DIR/config.yaml"
ok "config.yaml creado desde template"
# DEPRECATED: generacion inline — ahora copiamos desde _template
: <<'YAML'
# ============================================
# IDENTIDAD
# ============================================
agent:
id: $ID
name: "$DISPLAYNAME"
version: "1.0.0"
enabled: true
description: "Descripción del agente $DISPLAYNAME"
tags: [$(echo "$ID" | tr '-' ',')]
# ============================================
# PERSONALIDAD Y COMPORTAMIENTO
# ============================================
personality:
tone: friendly
verbosity: concise
language: es
languages_supported: [es, en]
emoji_style: minimal
prefix: "🤖"
error_style: helpful
templates:
greeting: "Hola, soy $DISPLAYNAME. ¿En qué puedo ayudarte?"
unknown_command: "No reconozco ese comando. Escríbeme directamente."
permission_denied: "No tengo permiso para hacer eso."
error: "Algo salió mal: {{.Error}}"
success: "{{.Summary}}"
busy: "Procesando, dame un momento..."
behavior:
proactive: false
ask_confirmation: false
show_reasoning: false
thread_replies: true
typing_indicator: true
acknowledge_receipt: false
# ============================================
# LLM
# ============================================
llm:
primary:
provider: openai
model: gpt-4o
api_key_env: OPENAI_API_KEY
base_url: ""
max_tokens: 4096
temperature: 0.7
fallback:
provider: ""
model: ""
api_key_env: ""
base_url: ""
max_tokens: 0
temperature: 0
reasoning:
system_prompt_file: "prompts/system.md"
context_window: 16384
memory_messages: 20
tool_use:
enabled: false
max_iterations: 3
parallel_calls: false
rate_limit:
requests_per_minute: 30
tokens_per_minute: 100000
concurrent_requests: 3
# ============================================
# TOOLS — ajustar según necesidades del agente
# ============================================
tools:
ssh:
enabled: false
allowed_targets: []
forbidden_commands: []
timeout: 0s
max_concurrent: 0
require_confirmation: []
http:
enabled: false
allowed_domains: []
timeout: 0s
max_retries: 0
scripts:
enabled: false
scripts_dir: ""
allowed: []
timeout: 0s
sandbox: false
file_ops:
enabled: false
allowed_paths: []
read_only: true
mcp:
enabled: false
servers: []
expose:
port: 0
tools: []
# ============================================
# MATRIX
# ============================================
matrix:
homeserver: "${MATRIX_HOMESERVER}"
user_id: "@$ID:${MATRIX_SERVER_NAME}"
access_token_env: MATRIX_TOKEN_${NORM}
device_id: ""
encryption:
enabled: true
store_path: "./agents/${ID}/data/crypto/"
pickle_key_env: PICKLE_KEY_${NORM}
trust_mode: tofu
recovery_key_env: SSSS_RECOVERY_KEY_${NORM}
rooms:
listen: []
respond: []
admin: []
filters:
command_prefix: "!"
mention_respond: true
dm_respond: true
ignore_bots: true
ignore_users: []
min_power_level: 0
threads:
enabled: true # responder en threads cuando el mensaje viene de un thread
auto_thread: false # true para crear thread automático por cada conversación nueva
# ============================================
# INTER-AGENTES
# ============================================
agents:
peers: []
delegation:
enabled: false
can_delegate_to: []
can_receive_from: []
max_delegation_depth: 1
timeout: 30s
protocol:
format: json
channel: matrix
heartbeat_interval: 60s
# ============================================
# SSH
# ============================================
ssh:
defaults:
user: ""
port: 22
key_file_env: ""
known_hosts: ""
keepalive_interval: 0s
timeout: 0s
targets: {}
# ============================================
# SEGURIDAD
# ============================================
security:
roles:
admin:
users: ["@admin:\${MATRIX_SERVER_NAME}"]
actions: ["*"]
user:
users: ["*"]
actions: ["help"]
audit:
enabled: false
log_file: "./data/audit.log"
log_to_room: ""
include: []
secrets:
provider: env
# ============================================
# SCHEDULING
# ============================================
schedules: []
# ============================================
# OBSERVABILIDAD
# ============================================
observability:
logging:
level: info
format: json
output: stdout
file: "./data/$ID.log"
metrics:
enabled: false
port: 0
path: /metrics
export: prometheus
health:
enabled: true
port: 0
path: /healthz
tracing:
enabled: false
provider: ""
endpoint: ""
# ============================================
# RESILIENCIA
# ============================================
resilience:
circuit_breaker:
failure_threshold: 5
timeout: 30s
half_open_max: 2
retry:
max_attempts: 2
backoff: exponential
initial_delay: 1s
max_delay: 10s
shutdown:
timeout: 10s
drain_messages: true
save_state: false
state_file: ""
queue:
enabled: true
max_size: 50
priority_users: ["@admin:\${MATRIX_SERVER_NAME}"]
# ============================================
# ALMACENAMIENTO
# ============================================
storage:
state:
backend: sqlite
path: "./data/$ID.db"
cache:
enabled: true
backend: memory
ttl: 5m
max_entries: 200
history:
backend: sqlite
path: "./data/history.db"
retention: 168h
YAML
# ── Copiar agent.go desde template y personalizar ────────────────────────
cp "$TEMPLATE/agent.go" "$DIR/agent.go"
sed -i "s/_template/$PACKAGE/g" "$DIR/agent.go"
sed -i "s/Package _template/Package $PACKAGE/g" "$DIR/agent.go"
sed -i "s/AGENT_ID_PLACEHOLDER/$ID/g" "$DIR/agent.go"
ok "agent.go creado desde template"
# ── Copiar prompts/system.md desde template y personalizar ───────────────
cp "$TEMPLATE/prompts/system.md" "$DIR/prompts/system.md"
sed -i "s/Template Agent/$DISPLAYNAME/g" "$DIR/prompts/system.md"
ok "prompts/system.md creado desde template"
ok "Scaffold creado en $DIR/"
echo ""
# ── Actualizar cmd/launcher/main.go — añadir blank import ────────────────
LAUNCHER="cmd/launcher/main.go"
BLANK_IMPORT="_ \"github.com/enmanuel/agents/agents/$ID\""
if grep -q "agents/$ID\"" "$LAUNCHER" 2>/dev/null; then
warn "$ID ya tiene blank import en $LAUNCHER — saltando"
else
TAB=$'\t'
IMPORT_LINE="${TAB}${BLANK_IMPORT}"
# Insertar blank import después del último blank import de agents/
if awk -v new_import="$IMPORT_LINE" '
{
lines[NR] = $0
if ($0 ~ /_ "github\.com\/enmanuel\/agents\/agents\//)
last_import = NR
}
END {
if (!last_import) { for (i=1;i<=NR;i++) print lines[i]; exit 1 }
for (i = 1; i <= NR; i++) {
print lines[i]
if (i == last_import) print new_import
}
}
' "$LAUNCHER" > /tmp/_launcher_tmp; then
mv /tmp/_launcher_tmp "$LAUNCHER"
ok "Blank import añadido en $LAUNCHER"
else
warn "No se pudo insertar el blank import — añádelo manualmente:"
echo -e " ${GRN}${IMPORT_LINE}${RST}"
fi
fi
echo ""
echo -e "${YLW}Quedan 3 pasos:${RST}"
echo ""
echo -e " ${DIM}1. ./dev-scripts/agent/register.sh $ID \"$DISPLAYNAME\"${RST} # registra en Matrix + genera token, password, pickle key"
echo -e " ${DIM}2. ./dev-scripts/agent/verify.sh $ID${RST} # genera cross-signing keys + verifica device"
echo -e " ${DIM}3. ./dev-scripts/server/start.sh $ID${RST} # arranca el agente"
echo ""