# Design Doc: Orquestração Multi-Agente com Amazon Bedrock e Step Functions

Este documento propõe uma arquitetura de orquestração multi-agente usando Amazon Bedrock Agents em topologia supervisor/worker, com Step Functions gerenciando estado, retries e human-in-the-loop. O foco é separar responsabilidades de raciocínio (LLM) das responsabilidades de orquestração (fluxo de estado), aplicar guardrails de segurança e controlar custo operacional de forma determinística.

- URL: https://fernando.moretes.com/studies/design-doc-orquestracao-multi-agente-bedrock

- Markdown: https://fernando.moretes.com/studies/design-doc-orquestracao-multi-agente-bedrock/study.md?lang=pt

- Type: Design Doc / RFC

- Company: Orquestração de agentes (cenário)

- Domain: IA / Agentes

- Date: 2026-03-03

- Tags: bedrock, step-functions, multi-agent, orchestration, guardrails, human-in-the-loop, event-driven, ai

- Reading time: 11 min

---

Agentes de IA são úteis individualmente. Em composição, sem uma camada de orquestração séria, eles viram um problema de engenharia não resolvido: loops infinitos, custos descontrolados, ausência de auditoria e falhas silenciosas. Este documento define como construir essa camada de forma que seja auditável, reversível e com teto de custo garantido.

## O Problema: LLMs Não São Orquestradores

O padrão mais comum que vejo em projetos de agentes é delegar ao próprio LLM a decisão de quando chamar qual ferramenta, em qual ordem, e quando parar. Isso funciona em demos. Em produção, é uma aposta.

O problema central é que um LLM não tem estado persistente, não tem garantias de idempotência, não tem visibilidade de custo acumulado e não tem mecanismo nativo de rollback. Quando você encadeia múltiplos agentes — um supervisor que delega para workers especializados (busca, cálculo, escrita, validação) — cada hop adiciona latência, tokens e superfície de falha. Um worker que trava ou retorna lixo pode fazer o supervisor entrar em loop de re-tentativa sem nenhum circuit breaker.

O cenário que motiva este documento é um sistema de processamento de solicitações complexas em um contexto financeiro-operacional: o usuário submete uma solicitação que exige pesquisa de dados internos, cálculo de risco, geração de rascunho de documento e aprovação humana antes da execução final. Nenhum agente único resolve isso bem. A composição de agentes especializados é a resposta correta — mas a composição precisa de um motor de estado externo, não de mais prompt engineering.

A tese deste design é simples: **o LLM decide o quê, o Step Functions decide o quando e o como**. O Bedrock Agent é o executor de raciocínio dentro de cada nó do fluxo; o Step Functions é o grafo de controle que define transições, timeouts, retries, compensações e pontos de aprovação humana. Essa separação não é apenas arquitetural — ela é a diferença entre um sistema que você consegue operar e um que você torce para funcionar.

## Objetivos e Não-Objetivos

- ✅ OBJETIVO: Definir uma topologia supervisor/worker com responsabilidades claras entre Bedrock Agents e Step Functions
- ✅ OBJETIVO: Garantir idempotência em todas as invocações de agentes e ferramentas (tool calls)
- ✅ OBJETIVO: Implementar human-in-the-loop como ponto de controle nativo no fluxo, não como workaround
- ✅ OBJETIVO: Aplicar Bedrock Guardrails para filtragem de conteúdo, PII e tópicos proibidos em todas as fronteiras de entrada/saída
- ✅ OBJETIVO: Estabelecer teto de custo determinístico via controle de tokens, timeout por execução e limite de iterações
- ✅ OBJETIVO: Observabilidade completa: rastreamento de cada step, cada tool call, cada decisão do supervisor

## Ficha do Cenário

- **Cenário:** Processamento de solicitações complexas com múltiplos agentes especializados
- **Domínio:** IA / Agentes — contexto financeiro-operacional
- **Serviços principais:** Amazon Bedrock Agents, AWS Step Functions (Express + Standard), AWS Lambda, Amazon DynamoDB, Amazon SNS
- **Modelo de orquestração:** Supervisor agent → workers especializados (4 workers: pesquisa, cálculo, redação, validação)
- **Tipo de Step Functions:** Standard Workflows para o fluxo principal (auditoria, human-in-the-loop); Express Workflows para sub-tarefas de curta duração
- **Guardrails:** Bedrock Guardrails aplicados em todas as fronteiras de entrada e saída dos agentes
- **Teto de custo (estimativa):** Controlado por: max_tokens por invocação, timeout por step (120s), máximo de 3 iterações por worker, alarme de custo acumulado via CloudWatch
- **Região alvo:** us-east-1 (disponibilidade de modelos Bedrock) com DR passivo em us-west-2

## Design Proposto: Separação de Planos

A arquitetura é organizada em três planos distintos com responsabilidades não sobrepostas.

**Plano de Controle: Step Functions Standard Workflow**

O fluxo principal é um Standard Workflow — escolha deliberada porque precisamos de histórico de execução completo (até 90 dias), semântica de exatamente-uma-vez para os steps críticos, e suporte nativo a `waitForTaskToken` para o human-in-the-loop. O Standard Workflow tem custo por transição de estado (não por duração), o que é adequado para fluxos que podem aguardar aprovação humana por horas.

Dentro do fluxo principal, sub-tarefas de curta duração (como a invocação de um worker de cálculo que retorna em segundos) são delegadas a Express Workflows aninhados — mais baratos para alta frequência e com throughput maior. A composição Standard → Express é um padrão suportado nativamente e resolve o problema de custo sem abrir mão da auditoria no nível do fluxo principal.

**Plano de Raciocínio: Bedrock Agents**

Cada agente (supervisor e workers) é um Bedrock Agent com um conjunto definido de Action Groups (ferramentas). O supervisor não executa ferramentas diretamente — ele recebe a solicitação, decompõe em sub-tarefas e emite tokens de delegação que o Step Functions interpreta para rotear para os workers corretos. Isso é diferente de deixar o supervisor chamar workers como ferramentas: o Step Functions mantém o controle de qual worker foi invocado, com quais parâmetros, e o resultado retornado — tudo auditável.

Cada worker tem um escopo de ferramenta restrito: o worker de pesquisa acessa apenas a Knowledge Base via Bedrock; o worker de cálculo acessa apenas funções Lambda de cálculo financeiro; o worker de redação não tem acesso a dados externos; o worker de validação acessa apenas regras de compliance em DynamoDB. Esse princípio de menor privilégio no nível do agente é aplicado via IAM roles distintas por agente.

**Plano de Segurança: Guardrails e IAM**

Bedrock Guardrails são configurados como uma camada transversal aplicada em todas as invocações — tanto na entrada do supervisor (sanitização do input do usuário) quanto nas saídas de cada worker antes de serem passadas para o próximo step. Os guardrails cobrem: filtragem de conteúdo por categoria (hate, violence, sexual, insults), detecção e mascaramento de PII (CPF, CNPJ, dados bancários no contexto financeiro), e lista de tópicos negados (instruções de operações fora do escopo do sistema).

A decisão de aplicar guardrails nas saídas dos workers — e não apenas na saída final — é intencional: um worker comprometido ou alucinando não deve contaminar o contexto dos workers subsequentes. O custo adicional de guardrail por invocação é aceitável dado o contexto financeiro.

## Topologia de Orquestração Multi-Agente

Fluxo completo desde a submissão da solicitação até a execução final, incluindo human-in-the-loop, guardrails em todas as fronteiras e controle de estado via Step Functions.

### 👤 Entry

- User / System API caller (user)
- API Gateway REST endpoint (edge)

### 🔀 Orchestration — Step Functions

- Standard Workflow Main orchestration (compute)
- Express Workflow Short sub-tasks (compute)
- waitForTaskToken Human approval (compute)

### 🤖 AI — Bedrock Agents

- Supervisor Agent Decompose & route (ai)
- Worker: Research Knowledge Base (ai)
- Worker: Calculation Financial logic (ai)
- Worker: Drafting Doc generation (ai)
- Worker: Validation Compliance check (ai)

### 🛡️ Security

- Bedrock Guardrails PII / content / topics (security)
- IAM Roles Per-agent least privilege (security)

### ⚙️ Tools & Data

- Lambda Calc functions (compute)
- Bedrock Knowledge Base (data)
- DynamoDB Compliance rules + execution state (storage)
- SNS Approval notification (messaging)

### 📊 Observability

- X-Ray Distributed tracing (compute)
- CloudWatch Metrics + cost alarm (compute)

### Fluxos

- user -> apigw: Submete solicitação
- apigw -> sfn_main: StartExecution
- sfn_main -> guardrails: Input sanitization
- guardrails -> supervisor: Sanitized input
- supervisor -> sfn_main: Delegation tokens
- sfn_main -> sfn_express: Sub-task dispatch
- sfn_express -> worker_research: InvokeAgent
- sfn_express -> worker_calc: InvokeAgent
- sfn_express -> worker_draft: InvokeAgent
- sfn_express -> worker_valid: InvokeAgent
- worker_research -> kb: Retrieve
- worker_calc -> lambda_calc: Tool call
- worker_valid -> dynamo: Rules lookup
- worker_research -> guardrails: Output check
- worker_calc -> guardrails: Output check
- worker_draft -> guardrails: Output check
- sfn_main -> hitl: waitForTaskToken
- hitl -> sns_hitl: Notify approver
- sns_hitl -> sfn_main: SendTaskSuccess/Failure
- sfn_main -> dynamo: Persist execution state
- sfn_main -> xray: Traces
- sfn_main -> cw: Metrics + cost
- iam -> supervisor: Role binding
- iam -> worker_research: Role binding

## Idempotência, Retries e Teto de Custo

Esses três tópicos são inseparáveis em sistemas de agentes e merecem tratamento explícito.

**Idempotência**

Toda invocação de Bedrock Agent via Step Functions recebe um `sessionId` derivado do `executionId` do workflow mais o identificador do step. Isso garante que, se o Step Functions re-executar um step por timeout ou falha transitória, a invocação do agente seja identificável como duplicata. No lado do Bedrock, o `sessionId` permite que a sessão de memória do agente seja reutilizada sem reprocessar o contexto completo — o que também reduz custo de tokens.

Para tool calls que têm efeitos colaterais (escrita em banco, chamada a API externa), as funções Lambda implementam idempotência via chave composta `{executionId}#{stepName}#{toolCallIndex}` persistida em DynamoDB com TTL de 24 horas. Se a Lambda for invocada duas vezes com a mesma chave, retorna o resultado cacheado sem re-executar a operação. Esse padrão é especialmente crítico para o worker de cálculo financeiro, onde uma re-execução pode produzir resultados diferentes por variação de dados de mercado.

**Retries com Backoff Exponencial**

O Step Functions configura retry em cada estado de invocação de agente com: `MaxAttempts: 3`, `IntervalSeconds: 2`, `BackoffRate: 2.0`, `MaxDelaySeconds: 30`. Erros do tipo `Bedrock.ThrottlingException` e `Lambda.TooManyRequestsException` são retentados; erros do tipo `Bedrock.ValidationException` (input inválido após guardrail) são tratados como falhas definitivas e transitam para um estado de compensação sem retry.

O estado de compensação é um ponto crítico: ele não apenas registra a falha, mas executa uma sequência de limpeza — notifica o usuário, persiste o estado parcial em DynamoDB para possível retomada manual, e emite uma métrica de falha categorizada para análise.

**Teto de Custo**

O custo de um sistema de agentes é dominado por tokens de LLM. Controlo isso em três camadas: (1) `maxTokens` configurado por agente — o supervisor tem limite maior (4096 output tokens) porque precisa de raciocínio mais elaborado; workers têm limites menores (1024-2048) porque têm escopo restrito. (2) Limite de iterações por worker: máximo de 3 ciclos de raciocínio (ReAct loops) antes de o Step Functions forçar uma transição para estado de escalação. (3) Alarme de custo no CloudWatch baseado em métrica customizada de tokens consumidos por execução, com threshold configurável por tipo de solicitação.

A métrica de tokens é emitida por uma Lambda de instrumentação que intercepta as respostas do Bedrock antes de retorná-las ao Step Functions — um padrão de interceptor que adiciona menos de 5ms de latência mas fornece visibilidade de custo em tempo real.

## Alternativas de Orquestração Avaliadas

### Bedrock Agent nativo com sub-agentes (Supervisor mode)

**Pros**
- Configuração mais simples — tudo dentro do ecossistema Bedrock
- Integração nativa com Knowledge Bases e Action Groups
- Memória de sessão gerenciada automaticamente

**Cons**
- Sem visibilidade de estado intermediário — caixa preta para auditoria
- Sem suporte nativo a human-in-the-loop com pausa de fluxo
- Sem controle de custo por step — difícil estabelecer teto determinístico
- Retry logic limitada e não configurável por tipo de erro

**Verdict:** Adequado para protótipos. Insuficiente para produção financeira.

### LangChain / LangGraph auto-hospedado em ECS

**Pros**
- Flexibilidade máxima de topologia e lógica de orquestração
- Ecossistema rico de integrações e abstrações
- Controle total sobre o código de orquestração

**Cons**
- Infraestrutura adicional para gerenciar (ECS, escalabilidade, patching)
- Estado de execução requer solução própria (Redis, DynamoDB) — sem managed durability
- Sem integração nativa com Bedrock Guardrails
- Maior superfície de manutenção de dependências e versões

**Verdict:** Válido se o time tem expertise em Python e prefere portabilidade. Custo operacional maior.

### Step Functions + Bedrock InvokeModel direto (sem Bedrock Agents)

**Pros**
- Controle total sobre o prompt e o ciclo de raciocínio
- Sem overhead do framework de Agents
- Mais simples de debugar — cada chamada é explícita

**Cons**
- Tool calling e ReAct loop precisam ser implementados manualmente
- Gestão de contexto e memória de sessão manual
- Sem Guardrails nativos — precisaria de Lambda de pré/pós-processamento

**Verdict:** Boa opção para casos simples. Para topologia multi-agente, o custo de implementação supera o benefício.

### Step Functions + Bedrock Agents (design proposto)

**Pros**
- Separação clara entre orquestração (Step Functions) e raciocínio (Bedrock Agents)
- Human-in-the-loop nativo via waitForTaskToken sem infraestrutura adicional
- Auditoria completa de execução no Step Functions + Guardrails nativos do Bedrock
- Retry, timeout e compensação configuráveis por step sem código adicional

**Cons**
- Maior complexidade de configuração inicial (ASL + Agent definitions)
- Custo de Standard Workflow por transição pode ser relevante em alto volume
- Latência adicional por hop entre Step Functions e Bedrock API

**Verdict:** Design escolhido. Melhor equilíbrio entre controle operacional, auditoria e custo de manutenção.

## Decisão: Standard vs Express Workflow para o Fluxo Principal

**Status:** accepted

**Contexto**

O fluxo principal inclui um ponto de human-in-the-loop que pode aguardar horas por aprovação. Express Workflows têm duração máxima de 5 minutos. Standard Workflows suportam execuções de até 1 ano e têm semântica de exatamente-uma-vez.

**Decisão**

Usar Standard Workflow para o fluxo principal e Express Workflows para sub-tarefas de curta duração invocadas como estados aninhados.

**Consequências**
- Custo por transição de estado no Standard Workflow — aceitável dado o volume esperado (centenas de execuções por dia, não milhões)
- Histórico de execução completo disponível no console e via API por até 90 dias
- waitForTaskToken funciona nativamente sem workarounds
- Sub-tarefas de alta frequência em Express Workflow reduzem custo total em ~60% (estimativa baseada em pricing público AWS)

## Plano de Rollout em Fases

1. **Fase 1 — Fundação (Semanas 1-2)** — Provisionar infraestrutura base via IaC (Terraform ou CDK): IAM roles por agente, DynamoDB para estado e idempotência, configuração de Bedrock Guardrails, Step Functions Standard Workflow com fluxo mínimo (supervisor → 1 worker → resultado). Validar que guardrails bloqueiam inputs sintéticos de teste (PII, tópicos negados). Sem tráfego real.

2. **Fase 2 — Workers e Tool Calling (Semanas 3-4)** — Implementar os 4 workers com seus Action Groups e ferramentas. Configurar Express Workflows para sub-tarefas. Implementar padrão de idempotência nas Lambdas de tool calling. Testes de integração com dados sintéticos cobrindo: retry por throttling, falha de worker com compensação, limite de iterações atingido. Medir latência end-to-end e custo de tokens por tipo de solicitação.

3. **Fase 3 — Human-in-the-Loop e Observabilidade (Semana 5)** — Integrar waitForTaskToken com SNS para notificação de aprovadores. Implementar Lambda de callback para SendTaskSuccess/Failure. Configurar X-Ray tracing em todos os componentes. Criar dashboard CloudWatch com métricas de: execuções por status, latência por fase, tokens consumidos, custo estimado por execução. Configurar alarmes de custo e de taxa de falha.

4. **Fase 4 — Piloto com Tráfego Real (Semanas 6-7)** — Habilitar para 10% do tráfego real via feature flag. Monitorar métricas de qualidade de resposta (avaliação humana amostral), taxa de escalação para human-in-the-loop, custo real vs estimado, e taxa de falha por tipo. Ajustar limites de tokens, timeouts e thresholds de guardrails com base em dados reais. Documentar casos de borda identificados.

5. **Fase 5 — GA e Operação (Semana 8+)** — Rollout completo. Runbook operacional documentado cobrindo: como inspecionar execuções travadas, como forçar falha ou sucesso em waitForTaskToken manualmente, como ajustar guardrails sem redeploy, e procedimento de rollback para versão anterior do workflow. Revisão de custo mensal com base em métricas acumuladas.

> **Riscos Críticos e Mitigações:** **1. Loop infinito entre supervisor e workers:** O Bedrock Agent em modo supervisor pode, em certos prompts ambíguos, continuar delegando para workers sem convergir. Mitigação: Step Functions impõe limite de iterações via contador em contexto de estado; após N ciclos, transição forçada para estado de escalação humana.

**2. Prompt injection via input do usuário:** Um usuário malicioso pode tentar injetar instruções no input para contornar guardrails ou manipular o supervisor. Mitigação: Guardrails aplicados antes de qualquer processamento pelo LLM; validação de schema no API Gateway antes de iniciar o workflow.

**3. Custo de tokens fora de controle em produção:** Solicitações complexas podem consumir muito mais tokens do que o estimado em testes. Mitigação: Alarme de CloudWatch com threshold de custo por execução; circuit breaker que suspende novas execuções se custo acumulado diário exceder limite configurado.

**4. Falha silenciosa de worker com resposta plausível mas incorreta:** Um worker pode retornar uma resposta que passa nos guardrails mas está factualmente errada (alucinação). Mitigação: Worker de validação como step obrigatório antes da execução final; human-in-the-loop para solicitações acima de threshold de risco.

**5. Latência de cold start em Bedrock Agents:** Primeiras invocações após período de inatividade podem ter latência maior. Mitigação: Manter sessões ativas via invocações de aquecimento periódicas; configurar timeout generoso no primeiro step do workflow.

## Avaliação Well-Architected

- **security**: IAM roles com escopo mínimo por agente; Bedrock Guardrails em todas as fronteiras de entrada/saída; sem credenciais em prompts ou variáveis de ambiente; VPC endpoints para Bedrock e DynamoDB onde aplicável.
- **reliability**: Retry com backoff exponencial configurado por tipo de erro; compensação explícita em falhas definitivas; estado persistido em DynamoDB para recuperação manual; Standard Workflow garante exatamente-uma-vez em steps críticos.
- **performance**: Express Workflows para sub-tarefas de curta duração; max_tokens configurado por agente para evitar respostas desnecessariamente longas; sessionId reutilizado para evitar reprocessamento de contexto.
- **sustainability**: max_tokens e limites de iteração reduzem consumo desnecessário de computação de LLM; reutilização de sessão evita reprocessamento; sem recursos ociosos (serverless-first).

## Métricas de Sucesso e Targets

- **Taxa de conclusão bem-sucedida:** >= 95% das execuções concluídas sem intervenção manual de engenharia
- **Latência end-to-end (P95):** < 45 segundos para fluxos sem human-in-the-loop (estimativa baseada em benchmarks de Bedrock API)
- **Custo por execução:** Dentro do teto configurado por tipo de solicitação; desvio > 20% dispara alarme
- **Taxa de ativação de guardrails:** Monitorada por categoria; spike > 2x baseline dispara investigação de possível ataque
- **Cobertura de rastreamento:** 100% das execuções com trace X-Ray completo do API Gateway ao resultado final
- **MTTR (Mean Time to Recover):** < 30 minutos para falhas operacionais com runbook documentado
- **Taxa de escalação para HITL:** Baseline a ser estabelecido no piloto; target de redução de 20% por trimestre via melhoria de prompts

> **Minha Perspectiva: O Erro Mais Comum em Sistemas de Agentes:** A maioria dos projetos de agentes que vi fracassar em produção não falhou por limitação do modelo — falhou por ausência de uma camada de orquestração séria. O time constrói um agente que funciona bem em testes, coloca em produção, e três semanas depois está debugando por que uma execução ficou presa em loop por 40 minutos e custou 15 dólares em tokens.

O instinto de deixar o LLM 'descobrir o caminho' é compreensível — é o que os demos mostram. Mas em sistemas que precisam de auditoria, controle de custo e aprovação humana, você precisa de um grafo de controle externo. O Step Functions não é burocracia — é a diferença entre um sistema que você consegue operar de madrugada quando algo quebra e um que você precisa reiniciar na mão.

O que eu faria diferente do padrão de mercado: aplicaria guardrails nas **saídas dos workers**, não apenas na entrada e saída do sistema. Isso parece excessivo até você ter o primeiro caso de um worker de pesquisa retornando dados de um cliente errado que contamina o contexto do worker de redação. Custo adicional de guardrail é menor do que o custo de um incidente de dados.

Outra coisa que eu enfatizaria: o **worker de validação não é opcional**. Em qualquer contexto com consequências reais (financeiro, saúde, jurídico), a saída do pipeline de agentes precisa passar por um step de validação antes de ser executada. Não confie no supervisor para detectar erros dos workers — ele não tem visibilidade de ground truth, só do que os workers retornaram.

Finalmente: meça custo por execução desde o dia um. Você vai se surpreender com a variância. Solicitações que parecem similares podem diferir 5x em custo de tokens dependendo da complexidade do raciocínio necessário. Sem essa visibilidade, você não consegue otimizar nem prever o bill.

## Veredicto

A topologia supervisor/worker com Bedrock Agents e Step Functions é o design correto para sistemas de agentes com requisitos de auditoria, controle de custo e aprovação humana. A separação entre plano de raciocínio (Bedrock) e plano de controle (Step Functions) não é over-engineering — é o que torna o sistema operável.

Os três princípios que sustentam este design são: (1) **o LLM decide o quê, o Step Functions decide o quando e o como**; (2) **guardrails em todas as fronteiras, não apenas nas extremidades**; (3) **idempotência não é opcional quando há efeitos colaterais**.

O custo adicional de Standard Workflow por transição e de guardrails por invocação é real e deve ser medido. Para volumes de centenas de execuções por dia em contexto financeiro, esse custo é justificado pelo que você ganha em auditabilidade e controle de risco. Para volumes de milhões de execuções simples, a arquitetura precisaria ser revisitada — possivelmente com Express Workflows em todo o fluxo e guardrails seletivos.

O risco mais subestimado neste tipo de sistema é a alucinação silenciosa de worker que passa nos guardrails. O worker de validação e o human-in-the-loop para casos de alto risco são as únicas mitigações efetivas — e ambos precisam estar no design desde o início, não adicionados depois como correção.

## Referências

- [Amazon Bedrock Agents — AWS](https://aws.amazon.com/bedrock/agents/)
- [AWS Step Functions Documentation](https://docs.aws.amazon.com/step-functions/)
- [Bedrock Agents — Multi-agent collaboration](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-multi-agent-collaboration.html)
- [Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html)
- [Step Functions — Standard vs Express Workflows](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-standard-vs-express.html)
- [Step Functions — Wait for a Callback with the Task Token](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token)
- [Bedrock Agents — Action Groups](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-action-group.html)
- [AWS Step Functions — Error Handling](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-error-handling.html)

## Fontes do caso

- [AWS — Amazon Bedrock Agents](https://aws.amazon.com/bedrock/agents/)
- [AWS — Step Functions](https://docs.aws.amazon.com/step-functions/)
