Por que padrões de design para agentes de voz escaláveis importam
Organizações que precisam entregar experiências de voz rápidas, naturais e confiáveis enfrentam desafios recorrentes: alta latência, gerenciamento de áudio em tempo real e coordenação de múltiplos agentes em fluxos complexos. A AWS publicou um guia detalhado mostrando como usar Amazon Nova Sonic, Amazon Bedrock AgentCore e Strands BidiAgent para construir agentes de voz escaláveis e manuteníveis que lidam com esses desafios de forma eficiente, resultando em interações mais responsivas e inteligentes com o cliente.
O artigo explora três padrões arquiteturais populares para agentes de voz, destacando seus trade-offs e melhores práticas para minimizar latência.
Os blocos fundamentais
Antes de mergulhar nos padrões de arquitetura, vale entender os três componentes-chave utilizados como solução de exemplo.
Amazon Nova Sonic é um modelo fundacional que cria conversas naturais de fala para fala (speech-to-speech) em aplicações de IA generativa. Os usuários podem interagir com a IA por voz em tempo real, com capacidades de entender tom, fluxo conversacional natural e executar ações.
Amazon Bedrock AgentCore Runtime é um ambiente de hospedagem serverless para agentes de IA. Você empacota seu agente como um container, faz o deploy no AgentCore Runtime e ele cuida de escalabilidade, isolamento de sessão e cobrança. Para agentes de voz, oferece:
- Streaming bidirecional via WebSocket com autenticação SigV4
- Isolamento de sessão em nível de microVM para evitar picos de latência por vizinhos ruidosos
- AgentCore Gateway para hospedagem compartilhada de ferramentas usando o protocolo open source Protocolo de Contexto de Modelo (MCP)
- Memória persistente entre sessões
- Telemetria para métricas específicas de voz como time-to-first-audio
Strands Agents é um framework open source para construção de agentes de IA. Sua classe BidiAgent é uma opção de integração entre o Nova Sonic e sua aplicação. Ela gerencia o ciclo de vida do stream bidirecional, roteia chamadas de ferramentas e cuida do gerenciamento de sessão, simplificando a aplicação do agente de voz através da interface SDK do modelo.
Três padrões de integração: ferramenta, agente-como-ferramenta (sub-agente) e segmentação de sessão
Em vez de construir um agente único e todo-poderoso, sistemas de voz modernos são cada vez mais compostos por agentes orientados a ferramentas, sub-agentes atuando como ferramentas e estratégias de segmentação de sessão que isolam prompts, memória e permissões. Esses padrões permitem decompor assistentes grandes em componentes menores, especializados e reutilizáveis, mantendo fronteiras claras de segurança.
Antes de executar os exemplos, é necessário instalar Python e as dependências necessárias, incluindo strands-agents e boto3, além de garantir que sua configuração IAM tenha as permissões necessárias para os serviços requeridos. Para o exemplo completo, consulte o repositório no GitHub.
Padrão 1: AgentCore Gateway – seleção de ferramenta para baixa latência
Uma chamada de ferramenta (tool call) é quando um agente de voz envia entrada para uma função ou serviço externo, que processa e retorna a saída. Isso permite que o agente execute tarefas como consultar um banco de dados ou acionar um serviço de forma rápida e segura, sem etapas adicionais de raciocínio.
Com o AgentCore Gateway, você expõe sua lógica de negócio existente como ferramentas — funções discretas que o Nova Sonic pode chamar diretamente durante uma conversa. O modelo de voz seleciona qual ferramenta invocar, passa os parâmetros, obtém o resultado e fala de volta. Não há camada intermediária de raciocínio entre o modelo e a ferramenta.

O AgentCore Gateway hospeda servidores MCP como endpoints gerenciados. MCP é o protocolo; AgentCore Gateway é a funcionalidade da AWS que os executa. O agente de voz se conecta via ARNs do Gateway:
# Nova Sonic calls tools directly via AgentCore Gateway
model = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=[
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/auth-tools",
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/banking-tools",
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/mortgage-tools",
],
)
Quando um usuário diz “Qual é o meu saldo?”, o Nova Sonic:
- Entende a intenção a partir da fala
- Seleciona
get_account_balancedas ferramentas MCP disponíveis - Chama a ferramenta com os parâmetros corretos
- Fala o resultado de volta
Trade-off: O Nova Sonic toma todas as decisões. Se uma chamada de ferramenta requer validação em múltiplas etapas, lógica condicional ou encadeamento de múltiplas operações, essa carga de raciocínio recai inteiramente sobre o system prompt do modelo de voz. Para ferramentas simples funciona bem. Para fluxos complexos, torna-se frágil.
Padrão 2: Sub-agente – raciocínio adicional com agentes desacoplados
No padrão sub-agente (ou agente-como-ferramenta), sua lógica de negócio existente roda em agentes autônomos, cada um com seu próprio modelo, system prompt, ferramentas e capacidades de raciocínio. O orquestrador de voz delega tarefas inteiras a esses sub-agentes em vez de chamar ferramentas individuais.
Existem diversas formas de conectar um sub-agente ao seu agente de voz. Agente-para-Agente (A2A) e Strands Agent-as-Tool são duas abordagens comuns:
- Agent-as-tool local: O sub-agente roda no mesmo processo, encapsulado como uma função
@toolusando o padrão Agents as Tools no Strands. É a abordagem mais direta — sem hop de rede e sem deploy separado. O trade-off é que o sub-agente compartilha o mesmo processo e escala junto com o orquestrador. - Agente remoto via protocolo A2A: O sub-agente é implantado como um servidor A2A independente no AgentCore Runtime (ou servidor remoto) e invocado pela rede. A2A é um protocolo aberto para comunicação agente-a-agente. Assim como o MCP conecta agentes a ferramentas, o A2A conecta agentes a outros agentes. Conforme o blog da AWS sobre suporte ao protocolo A2A no AgentCore Runtime explica, agentes construídos com diferentes frameworks (Strands, OpenAI, LangGraph, Google ADK) podem compartilhar contexto e raciocínio em um formato comum.

O Strands Agents tem suporte nativo para ambos os protocolos — MCP para acesso a ferramentas e A2A para comunicação agente-a-agente. Para um tutorial prático, consulte o guia da comunidade sobre Agent Collaboration: Strands Agents, MCP, and the Agent2Agent Protocol.
Veja a abordagem local agent-as-tool, onde cada sub-agente é um @tool encapsulando um Agent completo do Strands:
# sub_agents.py — Define sub-agents as Strands tools using the Agents-as-Tools pattern
from strands import Agent, tool
from strands.models import BedrockModel
# Each sub-agent is a full Strands Agent wrapped as a @tool
# The BidiAgent orchestrator calls these via Nova Sonic's tool use
@tool
def authenticate_customer(account_id: str, date_of_birth: str) -> str:
"""Authenticate a customer using their account ID and date of birth.
Handles the full verification flow including identity checks and retry logic.
Returns authentication status and token."""
auth_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""You are an authentication agent. Verify the customer's identity
using the provided account ID and date of birth. Call verify_identity to check
credentials. Return a clear auth status in 1-2 sentences.""",
tools=[verify_identity, check_account_exists], # Sub-agent's own tools
)
result = auth_agent(f"Authenticate account {account_id}, DOB: {date_of_birth}")
return str(result)
@tool
def handle_banking_inquiry(query: str, auth_token: str) -> str:
"""Handle banking questions — balances, transactions, transfers.
Validates permissions and returns a conversational summary."""
banking_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""You are a banking agent. Use the provided tools to answer
the customer's query. Summarize results in 2-3 natural sentences.
Do not return raw JSON.""",
tools=[get_account_balance, get_recent_transactions, transfer_funds],
)
result = banking_agent(query)
return str(result)
@tool
def handle_mortgage_inquiry(query: str) -> str:
"""Handle mortgage questions — rates, calculations, eligibility, application status.
Performs its own calculations and reasoning."""
mortgage_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""You are a mortgage specialist. Help with rate inquiries,
payment calculations, and eligibility assessments. Keep responses concise
and conversational — this will be spoken aloud.""",
tools=[get_mortgage_rates, calculate_payment, check_eligibility],
)
result = mortgage_agent(query)
return str(result)
O orquestrador de voz então usa o BidiAgent com essas ferramentas de sub-agente:
# voice_orchestrator.py — BidiAgent with sub-agents as tools
from strands.experimental.bidi.agent import BidiAgent
from strands.experimental.bidi.models.nova_sonic import BidiNovaSonicModel
from sub_agents import authenticate_customer, handle_banking_inquiry, handle_mortgage_inquiry
model = BidiNovaSonicModel(
region="us-east-1",
model_id="amazon.nova-2-sonic-v1:0",
provider_config={"audio": {"voice": "tiffany", "input_sample_rate": 16000, "output_sample_rate": 16000}},
)
agent = BidiAgent(
model=model,
tools=[authenticate_customer, handle_banking_inquiry, handle_mortgage_inquiry],
system_prompt="""You are a banking voice assistant. Route customer requests to the
appropriate specialist. Always authenticate before accessing account data.
Keep your own responses brief — the sub-agents handle the details.""",
)
await agent.run(inputs=[ws_input], outputs=[ws_output])
O sub-agente faz seu próprio raciocínio. O Nova Sonic não precisa orquestrar os passos individuais — ele delega e fala o resultado.
Trade-off: Cada chamada de sub-agente adiciona latência: a inferência do modelo do sub-agente mais suas chamadas de ferramenta. Em uma conversa por voz, isso significa silêncio mais longo enquanto o sub-agente raciocina. O blog da AWS sobre assistentes de voz multi-agente recomenda começar com modelos menores e eficientes como Amazon Nova 2 Lite para sub-agentes, reduzindo latência enquanto ainda lida com tarefas especializadas de forma eficaz.
O Amazon Nova 2 Sonic suporta chamada assíncrona de ferramentas, de modo que a conversa continua naturalmente enquanto ferramentas rodam em segundo plano. Ele continua aceitando entrada, pode executar múltiplas ferramentas em paralelo e se adapta graciosamente se o usuário mudar seu pedido no meio do processo.
Padrão 3: Segmentação de sessão para latência ultra-baixa
Existe uma terceira abordagem que vale considerar. Ela não se encaixa perfeitamente nos padrões MCP ou sub-agente, mas é construída especificamente para cenários de voz onde latência é a preocupação principal.
Em vez de delegar ferramentas externas ou sub-agentes, você segmenta a conversa em fases lógicas, cada uma com sua própria sessão Nova Sonic, system prompt e conjunto de ferramentas. Quando a conversa transiciona de uma fase para a próxima (por exemplo, de autenticação para consulta de conta), você fecha a sessão atual e abre uma nova com prompt e ferramentas diferentes, dentro da mesma conexão WebSocket.

Pense em um assistente bancário de voz com três fases de conversa: autenticação, gerenciamento de conta e consulta de hipoteca. Em vez de carregar um system prompt massivo com todas as ferramentas, você executa cada fase como uma sessão focada do Nova Sonic:
# Phase 1: Authentication
auth_session = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=["arn:...gateway/auth-tools"], # Only auth tools
)
auth_agent = BidiAgent(
model=auth_session,
tools=[],
system_prompt="""You are an authentication assistant. Collect the user's account ID
and date of birth. Call verify_identity to authenticate.
Once verified, say 'You're all set' and stop.""",
)
# Run until authentication completes
await auth_agent.run(inputs=[ws_input], outputs=[ws_output])
# Phase 2: Account management (new session, new prompt, new tools)
banking_session = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=["arn:...gateway/banking-tools"], # Only banking tools
)
banking_agent = BidiAgent(
model=banking_session,
tools=[],
system_prompt="""You are a banking assistant. The user is already authenticated.
Help with balance inquiries, transactions, and transfers.
Keep responses to one or two sentences.""",
)
await banking_agent.run(inputs=[ws_input], outputs=[ws_output])
Cada fase obtém uma sessão limpa do Nova Sonic com:
- System prompt focado: Mais curto, mais específico, menos espaço para o modelo se confundir.
- Apenas as ferramentas relevantes: via MCP gateways, ferramentas locais ou ambos. O modelo não desperdiça ciclos de raciocínio escolhendo entre 15 ferramentas quando precisa de apenas 3.
- Opcionalmente seus próprios sub-agentes: uma fase que requer raciocínio mais profundo pode usar o Padrão 2 internamente, enquanto fases mais simples ficam apenas com ferramentas.
O contexto da sessão anterior pode ser passado para a nova sessão como histórico de chat, mantendo a continuidade da conversa geral.
Comparação entre os padrões
Resumo comparativo dos três padrões em relação a fatores-chave:
- Latência: Ferramenta (baixa) | Sub-agente (mais alta) | Segmentação de sessão (mais baixa, com latência durante transições)
- Conjunto de ferramentas por turno: Ferramenta (ferramentas carregadas) | Sub-agente (ferramentas do sub-agente) | Segmentação (apenas ferramentas da fase)
- System prompt: Ferramenta (um prompt grande) | Sub-agente (orquestrador + prompts dos sub-agentes) | Segmentação (prompts pequenos por fase)
- Profundidade de raciocínio: Ferramenta (apenas modelo de voz) | Sub-agente (modelo de voz + sub-agente) | Segmentação (apenas modelo de voz por fase)
- Reuso de agentes existentes: Ferramenta (alto) | Sub-agente (mais alto) | Segmentação (médio)
- Continuidade da conversa: Ferramenta (transparente) | Sub-agente (transparente) | Segmentação (requer lógica de handoff entre fases)
Melhores práticas de latência para agentes de voz
Latência é uma consideração fundamental ao construir agentes de voz em comparação com agentes de texto. Seguem técnicas práticas para manter tempos de resposta rápidos:
Comece com modelos pequenos para sub-agentes. O orquestrador de voz usa Nova Sonic para a conversa, mas sub-agentes não precisam de um modelo grande. Comece com Amazon Nova 2 Lite ou Nova 2 Micro. São rápidos, otimizados em custo e lidam bem com a maioria das tarefas especializadas. Você sempre pode fazer upgrade de um sub-agente específico para um modelo maior se a qualidade exigir.
Projete sub-agentes stateful com cache. Um sub-agente stateless que consulta banco de dados ou API a cada chamada adiciona latência toda vez. Em vez disso, projete sub-agentes para cachear resultados de fontes de dados (APIs, funções AWS Lambda, bancos de dados) dentro de uma sessão. Se o sub-agente bancário busca detalhes da conta uma vez, ele deve manter esses dados em memória e servir perguntas subsequentes (saldo, transações, resumo) a partir do cache.
Faça prefetch de dados após autenticação. Isso é especialmente valioso para cenários de contact center. Após um cliente se autenticar, você já sabe quem ele é. Não espere que ele pergunte antes de puxar seus dados. Busque imediatamente saldos de conta, transações recentes, alertas pendentes e status de hipoteca em segundo plano.
Paralelize chamadas de ferramenta independentes. Se o usuário pedir “Me dê uma visão geral das minhas contas”, não chame get_checking_balance, depois get_savings_balance, depois get_credit_card_balance sequencialmente. Use execução concorrente para que três chamadas aconteçam de uma vez. O Strands suporta isso nativamente — o executor de ferramentas do agente roda chamadas independentes em paralelo por padrão.
Use frases de preenchimento para mascarar latência de ferramentas. Quando uma chamada de ferramenta ou delegação de sub-agente é inevitável, instrua o modelo de voz a falar um breve preenchimento enquanto espera: “Deixe-me verificar isso para você…” ou “Um momento enquanto eu consulto…” Isso mantém a conversa viva em vez de cair em silêncio.
Minimize a contagem de ferramentas por sessão. A seleção de ferramentas fica mais lenta conforme o número de ferramentas disponíveis cresce. Se seu agente tem 15 ferramentas mas uma conversa típica usa apenas 3 a 4, considere o padrão de segmentação de sessão para carregar apenas as ferramentas relevantes por fase.
Limpeza de recursos
Após finalizar os testes do exemplo, lembre-se de limpar os recursos criados para evitar custos desnecessários. Siga as instruções do repositório para parar serviços e deletar qualquer infraestrutura implantada.
Conclusão
Migrar um chatbot de texto para um assistente de voz não é um simples trabalho de wrapper. O modelo de interação é fundamentalmente diferente — desde o design de respostas até orçamentos de latência e comportamento de turn-taking. Mas com uma arquitetura multi-agente bem estruturada e o Amazon Bedrock AgentCore, a camada de lógica de negócio permanece intacta. Os sub-agentes já construídos são o maior ativo — reutilize-os.
Para um exemplo funcional de um assistente de voz Strands BidiAgent implantado no AgentCore Runtime com streaming WebSocket, consulte o exemplo de streaming bidirecional do AgentCore.
Próximos passos e recursos
É possível estender o exemplo para seu próprio caso de uso, integrar suas ferramentas de negócio, refinar prompts para interações por voz e testar o agente em cenários reais para preparar para deploy em produção. Para aprender mais sobre agentes de voz na AWS:
- Amazon Nova 2 Sonic Service Card
- Amazon Bedrock AgentCore Runtime Bidirectional Streaming
- Strands BidiAgent
- Amazon Bedrock AgentCore Bidirectional Streaming Sample Code
Fonte
Scalable voice agent design with Amazon Nova Sonic: multi-agent, tools, and session segmentation (https://aws.amazon.com/blogs/machine-learning/scalable-voice-agent-design-with-amazon-nova-sonic-multi-agent-tools-and-session-segmentation/)
Leave a Reply