Add agent_incidents dedup, overview/incidents/timeline API, mission board UI with fleet rail, kanban, context panel, mobile tabs, poll and keyboard shortcuts. Co-authored-by: Cursor <cursoragent@cursor.com>
143 lines
2.6 KiB
Markdown
143 lines
2.6 KiB
Markdown
# Contract — Agentic UI API v1.1 (Spec 030)
|
|
|
|
Extensão da API Spec 029. Base: `/api/v1/agents`.
|
|
|
|
**Auth:** igual 029 — JWT ops view (`get_current_user` + `_ops_view`).
|
|
|
|
---
|
|
|
|
## GET `/overview`
|
|
|
|
Resumo para status bar.
|
|
|
|
**Response 200:**
|
|
|
|
```json
|
|
{
|
|
"tier": "t1",
|
|
"ollama": true,
|
|
"model": "qwen2.5:7b-instruct",
|
|
"last_tick_at": "2026-06-20T06:32:02.723068+00:00",
|
|
"last_tick_status": "degraded",
|
|
"scenarios_total": 9,
|
|
"scenarios_ok": 5,
|
|
"incidents_open": {
|
|
"critical": 0,
|
|
"high": 2,
|
|
"warn": 2,
|
|
"info": 0
|
|
},
|
|
"worker_interval_sec": 600
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## GET `/incidents`
|
|
|
|
Lista deduplicada para mission board.
|
|
|
|
**Query:**
|
|
|
|
| Param | Tipo | Default |
|
|
|-------|------|---------|
|
|
| `status` | `open` \| `ack` \| `all` | `open` |
|
|
| `severity` | string | — |
|
|
| `agent_id` | string | — |
|
|
| `limit` | int | 50 |
|
|
|
|
**Response 200:**
|
|
|
|
```json
|
|
{
|
|
"incidents": [
|
|
{
|
|
"id": 1,
|
|
"scenario_id": "vm123.finance.stack",
|
|
"title": "FOSSBilling VM123 down",
|
|
"severity": "high",
|
|
"status": "open",
|
|
"primary_agent": "sentinel",
|
|
"agent_name": "Vigia",
|
|
"occurrence_count": 12,
|
|
"first_seen_at": "2026-06-19T23:45:16Z",
|
|
"last_seen_at": "2026-06-20T06:32:02Z",
|
|
"suggested_human_action": "Verificar docker compose VM123 finance stack",
|
|
"thread_id": 47,
|
|
"latest_finding_id": 253
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## GET `/incidents/{id}`
|
|
|
|
Detalhe + runs recentes do cenário.
|
|
|
|
**Response 200:**
|
|
|
|
```json
|
|
{
|
|
"incident": { "...": "..." },
|
|
"recent_runs": [
|
|
{
|
|
"run_id": 758,
|
|
"status": "degraded",
|
|
"started_at": "2026-06-20T06:25:34Z",
|
|
"findings_count": 1
|
|
}
|
|
],
|
|
"thread_id": 47
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## POST `/incidents/{id}/ack`
|
|
|
|
Ack incidente, mensagens inbox associadas, e finding latest.
|
|
|
|
**Response 200:**
|
|
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"incident_id": 1,
|
|
"thread_id": 47,
|
|
"findings_acked": 1
|
|
}
|
|
```
|
|
|
|
**RBAC:** `super_admin`, `ops_lead`, `technician`, `agentic_operator`, `devops`, `security_analyst` (mesmo `_ops_view`).
|
|
|
|
---
|
|
|
|
## Alteração no tick (runner)
|
|
|
|
Pseudo-lógica em `notify_finding_to_operators`:
|
|
|
|
```
|
|
1. Upsert agent_incidents ON scenario_id
|
|
- increment occurrence_count
|
|
- update last_seen_at, latest_finding_id, severity (max)
|
|
2. Reutilizar thread_id do incidente se open
|
|
3. Post message apenas se severity escalou OU first_seen OR human_action mudou
|
|
```
|
|
|
|
Evita 140 threads para 4 cenários.
|
|
|
|
---
|
|
|
|
## Frontend consumption
|
|
|
|
```javascript
|
|
// agentic-ops v2 boot
|
|
const [overview, incidents] = await Promise.all([
|
|
agentsApi('/overview'),
|
|
agentsApi('/incidents?status=open'),
|
|
]);
|
|
```
|
|
|
|
Fallback UI-A (sem backend): agrupar `/findings?open_only=true` por `scenario_id` no JS até UI-B deploy.
|