DEV Community

suissAI
suissAI

Posted on

Claude Dynamic Workflows como Comportamentos Semânticos Coreografados

Quando eu li sobre Dynamic Workflows, percebi que eu já usava a maior parte desses padrões antes mesmo de nomeá-los. A diferença é que a minha implementação não começa a partir de um script altamente orquestrado. Ela começa a partir de comportamentos semânticos que publicam e assinam eventos.

Em um workflow tradicionalmente orquestrado, existe um controlador central que conhece a sequência inteira:

  • classificar
  • chamar ferramenta
  • esperar
  • ramificar
  • tentar novamente
  • mesclar
  • finalizar

Isso é útil quando o sistema precisa de previsibilidade, visibilidade centralizada e aplicação rígida de políticas. Mas, na minha arquitetura, muitos fluxos são naturalmente coreografados. Um QuarkBehavior não precisa conhecer o sistema inteiro. Ele só precisa conhecer o contrato semântico que valida, os eventos que emite e os eventos que assina.

Isso cria um modelo híbrido:

  • IntentGraph / graflow define a macrointenção.
  • QuarkBehavior define a menor unidade semântica.
  • AtomicBehavior compõe comportamentos semânticos.
  • SubAgents reagem a eventos.
  • ProofAgents verificam corretude.
  • HealingAgents reparam estados inválidos.
  • BenchmarkAgents medem custo, latência e comportamento de execução.
  • Governor decide se o resultado é aceitável.

Nesse modelo, a orquestração é usada para a intenção de alto nível, enquanto a coreografia é usada para adaptação local. O orquestrador diz o que precisa ser alcançado. Os agentes descobrem como continuar reagindo a eventos semânticos.

1. Classify-And-Act

Esse foi o primeiro padrão que usei com IA, antes mesmo de ter um nome formal para ele. O usuário envia uma mensagem, o sistema classifica a intenção e o runtime roteia o payload para o comportamento correto.

Na minha arquitetura, isso não é apenas “classificação de intenção”. É roteamento semântico.

Uma mensagem pode ser classificada como:

  • CreateEntityIntent
  • UpdateEntityIntent
  • FindEntityIntent
  • SendMessageIntent
  • ValidateFieldIntent
  • HealInvalidPayloadIntent
  • GenerateBehaviorIntent
  • VerifyGeneratedCodeIntent

Depois da classificação, o sistema não apenas chama uma função. Ele seleciona um comportamento semântico, valida o payload, extrai valores primitivos, converte tipos quando necessário e emite success ou error.

Versão orquestrada:

IntentResolver -> Router -> Behavior -> Response
Enter fullscreen mode Exit fullscreen mode

Versão coreografada:

received.message -> classified.intent -> requested.behavior -> validated.behavior -> ended.behavior.in.success | ended.behavior.in.error
Enter fullscreen mode Exit fullscreen mode

A versão coreografada é mais alinhada com meu runtime, porque cada etapa pode ser substituída, observada, curada, medida ou formalmente verificada sem alterar o fluxo inteiro.

2. Fanout-And-Synthesize

Esse padrão já está embutido na forma como meu runtime trata funções sub.

Quando um payload chega a um subscriber, o runtime automaticamente chama a função forge do Semantic QuarkBehavior Type correspondente. O comportamento valida a entrada, extrai o valor primitivo, tenta conversão de tipo se necessário e emite seu próprio evento de erro se a validação falhar.

Isso é uma forma de fanout porque um único payload de entrada pode ser testado por vários comportamentos semânticos independentes:

  • validador de tipo
  • extrator de primitivo
  • validador de schema
  • validador semântico
  • compilador específico de linguagem
  • proof checker
  • benchmark runner
  • self-healing pipeline

A etapa de síntese não é apenas uma mesclagem de texto. É uma redução semântica.

O runtime sintetiza:

  • qual valor é válido
  • qual conversão funcionou
  • qual comportamento falhou
  • qual regra de tipo específica da linguagem causou a falha
  • qual função de healing deve ser adicionada ou reutilizada
  • qual artefato gerado é aceitável

Em um workflow de VibeCoding, isso fica ainda mais forte:

  • um agente gera TypeScript
  • um agente gera Zig
  • um agente gera Haskell
  • um agente gera regras Prolog
  • um agente gera testes
  • um agente verifica equivalência semântica
  • um agente mede custo
  • um agente sintetiza o comportamento final aceito

Isso não é simplesmente geração paralela. É fanout sobre responsabilidade semântica.

3. Adversarial Verification

Esse é o workflow que eu deveria formalizar de forma mais explícita.

Adversarial Verification significa que, depois que um comportamento, função, tradução da DSL ou implementação gerada é produzida, outro agente recebe esse output com o objetivo explícito de provar que ele está errado.

O agente adversarial não deve se comportar como um revisor tentando ser útil. Ele deve se comportar como:

  • atacante
  • compilador
  • type checker
  • property-based tester
  • usuário malicioso
  • simulador de falha em runtime

Na minha arquitetura, isso pode ser implementado assim:

DSL.pub("generated.candidate")

generated.candidate -> request.adversarialVerification.for.candidate
Enter fullscreen mode Exit fullscreen mode

Depois, múltiplos verificadores assinam esse evento:

  • TypeAdversaryAgent
  • SecurityAdversaryAgent
  • SemanticEquivalenceAdversaryAgent
  • LinearUsageAdversaryAgent
  • RuntimeCrashAdversaryAgent
  • PayloadCorruptionAdversaryAgent
  • PromptInjectionAdversaryAgent

Cada um emite um destes resultados:

  • passed.verification
  • found.counterexample
  • found.securityViolation
  • found.semanticDrift
  • found.runtimeFailure

Esse é um workflow naturalmente coreografado. O gerador não precisa chamar cada verificador diretamente. Ele apenas emite um candidato. Qualquer verificador que entende esse evento pode assinar, atacar e tentar quebrar o candidato.

Para o meu sistema, isso é essencial porque eu gero código em várias linguagens a partir de uma DSL semântica. Se implementações em TypeScript, Zig, Haskell e Prolog dizem representar o mesmo comportamento, um verificador adversarial precisa tentar encontrar onde elas divergem.

4. Generate-And-Filter

Generate-And-Filter é uma versão menos agressiva de Adversarial Verification.

Nesse padrão, o sistema gera múltiplas soluções possíveis e depois filtra essas soluções usando gates determinísticos.

Por exemplo, ao gerar um novo QuarkBehavior, o sistema pode produzir vários candidatos:

  • implementação mínima
  • implementação strict
  • implementação rápida
  • implementação segura
  • implementação linear
  • implementação idiomática da linguagem

Depois disso, os filtros removem qualquer coisa que falhe em:

  • validação de schema
  • validação de tipo
  • testes unitários
  • testes de propriedade
  • testes de equivalência semântica
  • compilação
  • linting
  • benchmark de runtime
  • política de segurança
  • regra de consumo linear
  • regra de ZeroTrust

Isso já é muito próximo de como eu trabalho manualmente durante o VibeCoding. Eu peço variações, comparo, mantenho as partes úteis, descarto o que quebra a arquitetura e converto o padrão vencedor em um comportamento reutilizável.

No meu runtime, o filtro não deve ser subjetivo. Ele deve ser um pipeline de gates executáveis de aceitação:

generated.candidate -> filtered.candidate -> accepted.candidate | rejected.candidate
Enter fullscreen mode Exit fullscreen mode

A ideia principal é que geração é barata, mas aceitação precisa ser rígida.

5. Tournament

Tournament é o padrão que eu devo usar quando não existe uma implementação obviamente melhor.

Em vez de gerar uma solução e validá-la, eu gero várias soluções concorrentes e pontuo todas contra a mesma rubrica.

Para a minha arquitetura, um torneio pode comparar:

  • linguagens diferentes
  • codificações de tipo diferentes
  • formatos de serialização diferentes
  • estratégias de healing diferentes
  • estratégias de sharding diferentes
  • janelas diferentes de agregação de eventos
  • planos diferentes de tradução SQL para graflow
  • implementações diferentes do mesmo QuarkBehavior

Um torneio deve produzir um scorecard, não apenas um vencedor.

Exemplos de dimensões:

  • passa nos testes
  • preserva equivalência semântica
  • compila com sucesso
  • tem menor custo de CPU
  • usa menos memória
  • faz menos alocações
  • tem menor custo de healing
  • tem melhor rastreabilidade
  • gera menos código
  • é mais fácil de provar
  • é mais seguro sob regras ZeroTrust
  • não viola consumo linear

O workflow de torneio é naturalmente coreografado:

submitted.candidate -> request.benchmark -> request.proof -> submitted.score -> closed.tournament -> selected.winner
Enter fullscreen mode Exit fullscreen mode

Cada candidato é independente. Cada agente de pontuação é independente. O coordenador do torneio apenas fecha a rodada e seleciona o vencedor depois que pontuações suficientes foram recebidas.

É exatamente assim que eu posso transformar VibeCoding em engenharia. Eu não preciso confiar no primeiro output. Eu posso criar uma competição entre implementações e deixar testes, provas, benchmarks e políticas decidirem.

6. Loop-Until-Done

Loop-Until-Done é a expressão mais clara de Intent-based Healing.

A maioria dos sistemas retorna erro quando um valor não corresponde ao tipo esperado ou à restrição semântica esperada. O meu sistema trata o erro como um novo evento.

Um comportamento que falha emite error.

O mesmo comportamento, ou um agente especializado em healing, assina esse erro.

O pipeline de healing recebe:

  • payload original
  • último estado do payload
  • valor inválido
  • comportamento que rejeitou o valor
  • trace interno

Depois, ele tenta reparar o payload.

Se tiver sucesso, ele emite success.

Se falhar, ele desembrulha o valor recursivamente até uma representação primitiva, tenta conversão de tipo, tenta conversão semântica e emite um novo erro com um estado mais rico.

O loop não é repetição cega. É um loop de convergência.

O workflow é:

AtomicBehavior.pub("execute.{QuarkBehavior}")

execute.{QuarkBehavior}
  -> QuarkBehavior.forge
  -> [
    Ok:pub("ended.{QuarkBehavior}.in.success"),
    Error:pub("failed.{QuarkBehavior}.at.validation")
  ]

failed.{QuarkBehavior}.at.validation
  -> execute.selfHealingPipeline
  -> [
    Ok:pub("ended.{QuarkBehavior}.in.success"),
    Error:pub("failed.{QuarkBehavior}.at.selfHealingPipeline")
  ]

failed.{QuarkBehavior}.at.selfHealingPipeline
  -> unwrapRecursiveToPrimitive
  -> [
    Ok:pub("ended.{QuarkBehavior}.in.success"),
    Error:pub("failed.{QuarkBehavior}.at.unwrapRecursiveToPrimitive")
  ]

failed.{QuarkBehavior}.at.unwrapRecursiveToPrimitive
  -> convertTypePipeline
  -> [
    Ok:pub("ended.{QuarkBehavior}.in.success"),
    Error:pub("failed.{QuarkBehavior}.at.convertTypePipeline")
  ]

failed.{QuarkBehavior}.at.convertTypePipeline
  -> convertSemanticData
  -> [
    Ok:pub("ended.{QuarkBehavior}.in.success"),
    Error:pub("ended.{QuarkBehavior}.in.error")
  ]

AtomicBehavior.sub("ended.{QuarkBehavior}.in.success")
AtomicBehavior.sub("ended.{QuarkBehavior}.in.error")
Enter fullscreen mode Exit fullscreen mode

A regra importante é que esse loop precisa ter memória. Cada iteração precisa adicionar informação:

  • qual conversão falhou
  • qual primitivo foi extraído
  • qual regra semântica rejeitou o valor
  • qual função de healing foi tentada
  • qual regra de tipo específica da linguagem esteve envolvida
  • qual candidato de reparo foi produzido
  • qual reparo nunca deve ser tentado novamente

Sem memória, isso é apenas retry. Com memória, isso vira Intent-based Healing.

Looping VibeCoding Engineering

Looping VibeCoding Engineering é o nome que eu daria para a forma como eu trabalho e para a forma como quero que meus agentes trabalhem.

Não é simplesmente pedir para uma IA programar.

É um loop de:

  • classificar a intenção
  • gerar implementações candidatas
  • fazer fanout para agentes especializados
  • filtrar outputs inválidos
  • atacar outputs aceitos
  • benchmarkar alternativas
  • selecionar vencedores
  • curar falhas
  • transformar o reparo em um comportamento reutilizável

O objetivo final não é evitar erros. O objetivo final é converter cada erro em um novo comportamento semântico que previne que o mesmo erro aconteça novamente.

Foi por isso que essa arquitetura naturalmente se tornou Intent-based Healing. Uma intenção do usuário só deveria falhar quando não existe caminho seguro, válido ou cooperativo para completá-la. Qualquer outra falha é apenas conhecimento ausente esperando para virar um novo comportamento.

Top comments (0)