ligbox-ops-platform/projects/ops-desk/api/app/agents/catalog.py
Ligbox Spec Hub 2a5273201b Name Agentics A0-A7, add inter-agent messaging and operator inbox UI.
Adds catalog with Maestro/Pulso/Trilho etc., agent_threads/messages bus,
inbox and context window API, and complete Desk Agentic Ops panel for
human operators to read, reply, and chat with agents.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-19 23:24:48 +00:00

208 lines
6.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Catálogo nomeado dos Agentics A0A7 — Spec 027 + 029."""
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True)
class AgentProfile:
id: str
codename: str
name: str
role: str
reads: tuple[str, ...]
actions: tuple[str, ...]
approval: str
scenarios: tuple[str, ...] = ()
AGENT_CATALOG: dict[str, AgentProfile] = {
"A0": AgentProfile(
id="A0",
codename="orchestrator",
name="Maestro",
role="Orquestrador multi-agente",
reads=("todos os feeds", "action_log", "findings abertos", "threads activas"),
actions=(
"Delegar cenários aos agentes especializados",
"Sintetizar estado global do ambiente Ligbox",
"Abrir thread de coordenação entre agentes",
"Escalar para humano quando confiança < limiar",
),
approval="agentic_operator / ops_lead",
scenarios=(),
),
"A1": AgentProfile(
id="A1",
codename="node_health",
name="Pulso",
role="Saúde de nós e serviços Carbonio",
reads=("métricas VM112", "CPU/RAM Proxmox", "status containers"),
actions=(
"Detectar serviço Carbonio/wizard down",
"Criar finding + alerta ticket",
"Sugerir restart (info auto; restart com ops_lead)",
),
approval="auto (info) · ops_lead (restart)",
scenarios=("wizard.vm112.bundle", "proxmox.cluster"),
),
"A2": AgentProfile(
id="A2",
codename="infra_mail",
name="Trilho",
role="DNS, certificados, Traefik, nginx",
reads=("DNS Cloudflare", "certs LE", "Traefik CT114", "SNI"),
actions=(
"Validar propagação DNS pós-onboard",
"Detectar cert expirado ou mismatch SNI",
"Propor fix DNS/Traefik (nunca aplicar sem devops/ops_lead)",
),
approval="devops ou ops_lead antes de aplicar",
scenarios=("pfsense.api.system",),
),
"A3": AgentProfile(
id="A3",
codename="deliverability",
name="Carta",
role="SPF, DKIM, DMARC, reputação mail",
reads=("registos DNS mail", "relatórios entregabilidade"),
actions=(
"Auditar SPF/DKIM/DMARC por domínio tenant",
"Gerar relatório de entregabilidade",
"Abrir finding para seo/technician revisão",
),
approval="seo / technician revisão",
scenarios=(),
),
"A4": AgentProfile(
id="A4",
codename="security_mail",
name="Escudo Mail",
role="amavis, spam, clamav, filas mail",
reads=("filas mail", "logs amavis/clamav", "quarentena"),
actions=(
"Detectar pico spam ou fila bloqueada",
"Sugerir quarentena / release",
"Correlacionar com alertas segurança VM112",
),
approval="security_analyst",
scenarios=(),
),
"A5": AgentProfile(
id="A5",
codename="wazuh_soc",
name="Sentinela SOC",
role="Correlação SIEM Wazuh VM104",
reads=("alertas Wazuh", "webhooks vm104", "tickets correlacionados"),
actions=(
"Correlacionar alerta L≥10 com domínio/sessão",
"Enriquecer timeline do chamado",
"Propor runbook R0/R1 segurança",
),
approval="security_analyst / noc",
scenarios=(),
),
"A6": AgentProfile(
id="A6",
codename="support_copilot",
name="Copiloto",
role="Assistência tickets e janela humana",
reads=("tickets Desk", "timeline onboarding", "findings", "KB specs"),
actions=(
"Rascunhar resposta ao cliente/ticket",
"Responder janela /chat do operador humano",
"Resumir contexto para technician enviar",
),
approval="technician envia · agentic_operator vê tudo",
scenarios=("funnel.stuck.onboarding",),
),
"A7": AgentProfile(
id="A7",
codename="remediation",
name="Remediador",
role="Runbooks aprovados pós-incidente",
reads=("playbooks aprovados", "findings critical/high", "aprovações pendentes"),
actions=(
"Propor runbook com confiança %",
"Executar R0 auto (poll/refresh)",
"Executar R1+ apenas após OK humano",
"Registar action_executed na timeline",
),
approval="agentic_operator obrigatório (R2/R3 dupla)",
scenarios=(),
),
"sentinel": AgentProfile(
id="sentinel",
codename="sentinel",
name="Vigia",
role="Health checks T0 — APIs e infra",
reads=("endpoints HTTP", "integrações health", "Ollama", "VM123 stack"),
actions=(
"Executar cenários desk/wizard/pfsense/proxmox/ollama/VM123",
"Criar findings com severidade",
"Disparar e-mail em high/critical",
),
approval="automático (detecção) · humano trata finding",
scenarios=(
"desk.api.health",
"wizard.vm112.bundle",
"pfsense.api.system",
"integration.webhook.gap",
"proxmox.cluster",
"ollama.vm123.health",
"vm123.finance.stack",
"vm123.openpanel.bridge",
),
),
"curator": AgentProfile(
id="curator",
codename="curator",
name="Curador",
role="Base de conhecimento (RAG)",
reads=("specs/**/*.md", "agent_kb_chunks"),
actions=("Indexar specs no SQLite", "Fornecer snippets ao Copiloto/Advisor"),
approval="automático",
scenarios=(),
),
}
# Map legacy agent_id in scenarios → A* principal
SCENARIO_AGENT_MAP = {
"desk.api.health": "sentinel",
"wizard.vm112.bundle": "A1",
"pfsense.api.system": "A2",
"funnel.stuck.onboarding": "A6",
"integration.webhook.gap": "sentinel",
"proxmox.cluster": "A1",
"ollama.vm123.health": "sentinel",
"vm123.finance.stack": "sentinel",
"vm123.openpanel.bridge": "sentinel",
}
def resolve_agent(scenario_id: str, agent_id: str | None = None) -> AgentProfile:
key = SCENARIO_AGENT_MAP.get(scenario_id) or agent_id or "sentinel"
return AGENT_CATALOG.get(key, AGENT_CATALOG["sentinel"])
def roster_public() -> list[dict]:
order = ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "sentinel", "curator"]
out = []
for k in order:
if k not in AGENT_CATALOG:
continue
p = AGENT_CATALOG[k]
out.append(
{
"id": p.id,
"codename": p.codename,
"name": p.name,
"role": p.role,
"reads": list(p.reads),
"actions": list(p.actions),
"approval": p.approval,
"scenarios": list(p.scenarios),
}
)
return out