1) Nova camada: Interactive Intent-Healing (IIH)
O que ela faz
Quando o sistema:
- captura um erro,
- tenta auto-healing,
- não consegue corrigir ,
ele emite um evento pedindo intervenção humana, recebe um "valor novo" (ou um patch) e aplica diretamente no payload para retentar o passo que falhou.
Isso é a mesma família conceitual de "pausar execução e retomar com input externo" (human-in-the-loop) que frameworks modernos usam via interrupt/resume (LangChain Docs).
Porém, nesse contexto o HITL se torna Human-in-the-Healing-Loop
Contrato
Vamos padronizar como JSON Patch (RFC 6902) , porque:
- é explícito,
- auditável,
- dá pra validar com whitelist de paths,
- vira evidência versionável. (RFC Editor)
Exemplo de request de intervenção (evento AON):
{
"type": "interactive_healing_request",
"sessionId": "aon_s_01H...",
"requestId": "req_01H...",
"error": {
"code": "schema_validation_failed",
"message": "field userId must be uuidv4"
},
"payloadSnapshotHash": "sha256:...",
"suggestedPatches": [
{ "op": "replace", "path": "/userId", "value": "uuidv4_placeholder" }
],
"allowedPatchPaths": ["/userId", "/items/*/quantity"],
"timeoutMs": 60000
}
Resposta do dev (via WS ou webhook)
{
"type": "interactive_healing_response",
"sessionId": "aon_s_01H...",
"requestId": "req_01H...",
"patch": [
{ "op": "replace", "path": "/userId", "value": "7b0b2d32-9db7-4aa7-a7e4-7f8b1e0adf7c" }
],
"reason": "ID veio do CRM legado; normalizei para uuid"
}
2) Como isso entra no pipeline AON
Como já temos healing e error como eventos terminais, o IIH entra assim:
- fail → auto-healing tenta N estratégias
-
falhou → emite
interactive_healing_requestpor atétimeoutMs - se veio patch válido → aplica, emite
interactive_healing_applied, e retry - se não veio/negado → emite
errorterminal (ou "pending" se você quiser assíncrono)
Segurança
-
Só bloquear aguardando dev em
NODE_ENV=developmentoustaging. - Em produção: emitir o evento, gerar um "ticket de healing" , e falhar normalmente (pra não segurar conexão e recursos).
3) "Ao iniciar o AON": criar WebSocket channel único e devolver no primeiro HTTP response
Conceito
No começo de um request AON (qualquer modo), é criado sessionId e computa rotas:
-
WS :
wss://host/aon/ws/<sessionId>?token=<signed>v- interatividade
-
SSE :
https://host/aon/sse/<sessionId>?token=<signed>- logs para o frontend
-
NDJSON : é o próprio response (quando
Accept: application/x-ndjson)- logs para o backend
Como devolver isso na primeira resposta
Modo JSON (black box) : você não tem stream, então devolve como:
- headers:
X-AON-WS,X-AON-SSE - e/ou body com
aon
Exemplo:
{
"data": { "...": "..." },
"_aon": {
"sessionId": "aon_s_01H...",
"ws": "/aon/ws/aon_s_01H...?token=...",
"sse": "/aon/sse/aon_s_01H...?token=..."
}
}
Modo NDJSON (glass box) : primeira linha do stream:
{"type":"channels","sessionId":"aon_s_01H...","ws":"/aon/ws/...","sse":"/aon/sse/...","timestamp":...}
4) Rota única SSE espelhando exatamente o NDJSON
SSE é excelente pra telemetria unidirecional (server → client) (Ably Realtime).
Regra de espelhamento
Cada evento AON que hoje você escreve em NDJSON vira no SSE:
event: <type>
data: <json do evento>
id: <eventId incremental>
Exemplo:
event: healing
data: {"type":"healing","severity":"medium","action":"recover_db_connection",...}
Implementação "limpa": 1 emissor, 3 saídas
Criar um AON Event Hub interno:
-
emit(event)é chamado por middleware/healer - o hub distribui para:
-
NDJSONStreamWriter(quando o request for NDJSON) -
SSE subscribers(por sessionId) -
WS topic(por sessionId)
-
Isso garante 1 fonte de verdade . (E de quebra aproxima do mindset do OpenTelemetry, onde "eventos" são logs estruturados correlacionáveis (OpenTelemetry).)
5) Human-in-the-Healing-Loop: Onde o WebSocket entra (além de "logs")
- Logs: WS pode receber os mesmos eventos do SSE/NDJSON (ok)
- IIH : WS é o canal ideal pro dev responder com o patch (bidirecional). SSE não faz isso.
Então:
- SSE = "observa"
- WS = "observa + intervém"
6) Estrutura
src/aon/
├── hub.ts # Event hub + session registry + buffer
├── sse.ts # handler /aon/sse/:sessionId
├── ndjson.ts # handler /aon/ndjson/:sessionId
├── ws.ts # handler /aon/ws/:sessionId (adapter)
├── iih.ts # Interactive Intent Healing
# IIH: request/await/patch/apply/retry
Extensão de tipos (ex.: types.ts)
Eventos:
channelsinteractive_healing_requestinteractive_healing_applied-
interactive_healing_timeout(opcional)
7) Detalhes
Buffer/replay
Se o dev abrir SSE depois do request começar, ele perde eventos. Soluções:
- ring buffer em memória por sessionId (TTL curto, ex. 5 min)
- ou Redis Streams (se você quer escalar horizontalmente)
Auth
- sessionId sozinho não é segredo
- OAuth2.1 com JWT e DPoP
- UUID Verifiable (identidade verificável de agentes)
- Signal e2e no Websocket (opcional no SSE e NDJSON)
Observabilidade
Obrigatório traceId/spanId/requestId/sessionId nos eventos, porque isso vira navegação perfeita (padrão de correlação é bem estabelecido em observabilidade moderna) (OpenTelemetry).
Fontes, conceitos e tecnologias citadas
- AON - Adaptative Observability Negotiation atual (NDJSON, healing, eventos)
- Human-in-the-loop via "interrupt/resume" (paralelo conceitual) (LangChain Docs)
- JSON Patch (RFC 6902) (RFC Editor)
- SSE vs WebSocket (telemetria unidirecional vs bidirecional) (Ably Realtime)
- Logs/eventos estruturados e correlação (OpenTelemetry(OpenTelemetry)
Top comments (0)