DEV Community

Cover image for FullAgenticStack Intent-based Healing Patterns: Interactive-Intent-Healing
suissAI
suissAI

Posted on

FullAgenticStack Intent-based Healing Patterns: Interactive-Intent-Healing

1) Nova camada: Interactive Intent-Healing (IIH)

O que ela faz

Quando o sistema:

  1. captura um erro,
  2. tenta auto-healing,
  3. 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
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

2) Como isso entra no pipeline AON

Como já temos healing e error como eventos terminais, o IIH entra assim:

  1. fail → auto-healing tenta N estratégias
  2. falhou → emite interactive_healing_request por até timeoutMs
  3. se veio patch válido → aplica, emite interactive_healing_applied, e retry
  4. se não veio/negado → emite error terminal (ou "pending" se você quiser assíncrono)

Segurança

  • Só bloquear aguardando dev em NODE_ENV=development ou staging.
  • 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:

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=..."
  }
}
Enter fullscreen mode Exit fullscreen mode

Modo NDJSON (glass box) : primeira linha do stream:

{"type":"channels","sessionId":"aon_s_01H...","ws":"/aon/ws/...","sse":"/aon/sse/...","timestamp":...}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Exemplo:

event: healing
data: {"type":"healing","severity":"medium","action":"recover_db_connection",...}
Enter fullscreen mode Exit fullscreen mode

Implementação "limpa": 1 emissor, 3 saídas

Criar um AON Event Hub interno:

  • emit(event) é chamado por middleware/healer
  • o hub distribui para:
    1. NDJSONStreamWriter (quando o request for NDJSON)
    2. SSE subscribers (por sessionId)
    3. 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
Enter fullscreen mode Exit fullscreen mode

Extensão de tipos (ex.: types.ts)

Eventos:

  • channels
  • interactive_healing_request
  • interactive_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)