Serviços que somam ao Bedrock IV: canais e borda
- ⬜📈 Serviços que somam ao Bedrock III: observabilidade, FinOps e entrega(AWS Bedrock — GenAI em Produção)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
A borda parece detalhe de encanamento e é uma das decisões mais difíceis de reverter da arquitetura inteira. O motivo: uma resposta de LLM com raciocínio pode levar dezenas de segundos, e vários caminhos de borda cortam a conexão antes disso. O sintoma é cruel — funciona nos testes com perguntas curtas e falha em produção justamente nas perguntas difíceis, que são as que importam. Este módulo percorre os 14 serviços do caminho entre o humano e o modelo: canais de atendimento, canais assíncronos e as cinco formas de expor a borda HTTP.
Como escolher nesta camada
- Tem gente esperando a resposta? Se sim, streaming e latência mandam na escolha. Se não, você está no mundo assíncrono e a borda pode ser um evento, não um endpoint.
- Precisa de quota, autorizador e plano de uso? Isso elimina os caminhos mais simples de streaming e aponta para a borda gerenciada com governança.
- O canal é texto ou voz? Voz soma transcrição e síntese ao orçamento de tempo — e o usuário sente a soma das etapas, não a média.
A regra que resolve a maior parte dos casos
Síncrono e curto: borda HTTP simples com função. Síncrono com resposta longa: conexão persistente ou resposta em fluxo. Assíncrono: evento com fila e notificação do desfecho. Comece por aí e só troque quando um limite concreto empurrar — mas escolha antes de construir, porque trocar depois é refazer a camada.
Canais de atendimento
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| Amazon Connect | Contact center gerenciado: telefonia, fila, roteamento, gravação e métricas de atendimento | Entrega a operação de atendimento inteira em volta do assistente — fila, transferência para humano e as métricas que o negócio já acompanha | É plataforma opinativa; integrar com contact center existente costuma ser mais trabalhoso que adotar o fluxo dele |
| Amazon Lex | Reconhecimento de intenção e captura de campos, com fluxo conversacional declarado | Resolve o caminho determinístico — número de pedido, CPF, data — sem gastar uma chamada de modelo, e passa ao Bedrock só o que é aberto | Fluxo declarado fica rígido quando a conversa foge do roteiro; a divisão de trabalho com o LLM precisa ser desenhada |
| Amazon Chime SDK | Áudio e vídeo embutidos no seu próprio produto | Quando a experiência de comunicação é parte do produto, em vez de um contact center separado | Você constrói a experiência inteira; é o caminho mais longo, e só se justifica se a comunicação for o produto |
Em voz, o orçamento de latência é somado
Transcrição, retrieval, inferência, guardrail e síntese acontecem em série, e o usuário sente a soma. É por isso que o caso público de contact center por voz com latência na casa de poucos segundos impressiona: cada etapa precisou caber num orçamento apertado. Regra prática: meça o tempo de cada etapa separadamente desde o primeiro dia, porque quando o total estourar você vai precisar saber quem consumiu o quê.
A divisão de trabalho entre Lex e Bedrock
Campo com formato conhecido não deveria passar por modelo generativo: número de pedido, CPF, data e valor têm validação determinística, e errar a coleta contamina tudo depois. Deixe o Lex coletar e validar o estruturado, e o Bedrock responder o que é aberto. Além de mais barato, é mais confiável — e dá ao usuário a chance de corrigir um dígito antes de a conversa seguir.
Canais assíncronos e front
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| Amazon SES | Envio e recebimento de e-mail em escala | Canal de entrada (recebe a mensagem, dispara o pipeline) e de saída (responde ou notifica o desfecho) | Reputação de envio precisa ser cuidada; e-mail recebido exige regra de processamento e antispam |
| End User Messaging | Entrega em SMS, push e canais de mensagem | Notifica o desfecho de um processamento assíncrono — o documento foi analisado, o chamado foi resolvido | Custo por mensagem e regras por país; não é canal de conversa, é de notificação |
| AWS Amplify | Hospedagem de front e SDK de integração | Acelera o app que consome o assistente, sem você montar pipeline de build e distribuição | Opinativo sobre stack de front; projeto com esteira própria ganha pouco |
Canal assíncrono muda a arquitetura, não só o transporte
Quando o canal é e-mail ou notificação, o timeout de borda deixa de existir como problema — e isso libera decisões melhores: você pode usar batch e pagar cerca de metade, pode escalar para o tier de raciocínio sem preocupação com latência, e pode enfileirar picos sem que ninguém perceba. Vale perguntar em todo projeto se o caso de uso realmente exige resposta imediata; com frequência, exige apenas resposta confiável.
A borda HTTP: cinco formas, e o timeout que decide
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| API Gateway (REST) | Borda gerenciada completa: autorizador, chave de API, plano de uso, cache e validação de payload | É onde a quota por consumidor e o autorizador corporativo vivem — a governança da camada 2 da arquitetura de referência | Timeout de integração é o inimigo do LLM lento; confirme o vigente e configure explicitamente |
| API Gateway (HTTP) | Versão enxuta e mais barata da borda gerenciada | Backend do seu próprio app, quando você não precisa dos extras do REST | Menos recursos de governança: sem plano de uso e com autorização mais simples |
| API Gateway (WebSocket) | Conexão persistente bidirecional, com rotas de conexão e mensagem | É o caminho que elimina o timeout: o primeiro token chega quase imediato e a conexão fica viva durante a geração | Conexão e ociosidade têm teto; reconexão é obrigação do cliente, e rede móvel derruba com frequência |
| Lambda Function URL (streaming) | Endpoint direto da função, com resposta em fluxo | O caminho mais curto para streaming, sem intermediário nem custo de borda gerenciada | Você perde autorizador, plano de uso, quota e cache — que em ambiente corporativo costumam ser requisito |
| AppSync | GraphQL gerenciado com subscriptions e canais de evento | Front que já é GraphQL, ou muitos clientes ouvindo o mesmo canal de atualização | Modelar streaming de token como subscription exige desenho próprio; é uma stack a mais se o front não for GraphQL |
| Application Load Balancer | Balanceador para alvo de longa duração | Borda para agent em container, que mantém conexão e ultrapassa o teto da função | Não tem autorizador nativo: a autenticação passa a ser sua responsabilidade |
O erro nº 1 desta camada: timeout na borda
Uma resposta de LLM com raciocínio pode levar dezenas de segundos, e vários caminhos de borda cortam a conexão antes disso. O sintoma é cruel: funciona nos testes com perguntas curtas e falha em produção justamente nas perguntas difíceis, que são as que importam. As saídas são três — streaming (o primeiro token chega em menos de um segundo e a conexão fica viva), assíncrono com notificação, ou uma borda sem esse teto. Escolha antes de construir, porque trocar depois é refazer a camada inteira.
📋 Chat corporativo no navegador, respostas longas, com efeito de digitação, autenticação pelo IdP da empresa e quota por área.
A conexão persistente resolve o problema de tempo de resposta na origem: o primeiro token chega quase imediatamente e nada é cortado por timeout. E você mantém autorizador e quota da API Gateway, que é justamente o que o requisito de governança por área pede.
Alt: Function URL com resposta em fluxo — Streaming mais simples de montar, mas você perde autorizador, plano de uso e quota — que aqui são requisito, não conveniência.
Alt: API Gateway REST sem streaming — A resposta longa esbarra no teto de integração e a experiência fica de tela parada por dezenas de segundos.
Alt: AppSync com subscription — Excelente se o frontend já for GraphQL; caso contrário, é uma stack a mais para resolver o que o WebSocket resolve direto.
import os, json, boto3
br = boto3.client("bedrock-runtime")
ddb = boto3.resource("dynamodb").Table(os.environ["TABELA_SESSAO"])
def handler(event, _ctx):
ctx = event["requestContext"]
conexao = ctx["connectionId"]
# O endpoint de gerenciamento e derivado do proprio evento: e por ele
# que a Lambda EMPURRA dados de volta para o navegador.
api = boto3.client(
"apigatewaymanagementapi",
endpoint_url=f"https://{ctx['domainName']}/{ctx['stage']}",
)
corpo = json.loads(event["body"])
sessao = corpo["sessao"]
historico = carregar_historico(sessao)
resp = br.converse_stream(
modelId=os.environ["MODEL_ID"],
system=[
{"text": SYSTEM_PROMPT},
{"cachePoint": {"type": "default"}}, # prefixo estavel cacheado
],
messages=historico + [{"role": "user",
"content": [{"text": corpo["texto"]}]}],
inferenceConfig={"maxTokens": 900},
)
completa, uso = [], {}
for ev in resp["stream"]:
if "contentBlockDelta" in ev:
pedaco = ev["contentBlockDelta"]["delta"].get("text", "")
completa.append(pedaco)
try:
api.post_to_connection(
ConnectionId=conexao,
Data=json.dumps({"delta": pedaco}).encode(),
)
except api.exceptions.GoneException:
# Usuario fechou a aba no meio da resposta: pare de gerar.
# Sem este tratamento voce paga a resposta inteira para ninguem.
break
elif "metadata" in ev:
uso = ev["metadata"].get("usage", {})
salvar_turno(sessao, corpo["texto"], "".join(completa), uso)
return {"statusCode": 200}
Detalhes que só aparecem em produção
Conexão fechada no meio da geração precisa interromper o laço — sem isso você paga a resposta inteira para uma aba que já foi embora, e em escala isso é dinheiro real. O registro da conexão precisa de expiração automática, ou a tabela acumula conexões mortas. E reconexão tem que ser tratada no cliente: rede móvel derruba WebSocket o tempo todo, e o usuário não pode perder o turno por causa disso.
Um chat corporativo funciona nos testes e, em produção, falha exatamente nas perguntas mais complexas, com erro de tempo esgotado. Qual é a causa e a correção estrutural?
Entrega e proteção na borda
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| Amazon CloudFront | Rede de entrega na borda global, com cache e integração de firewall | Reduz latência de tudo em volta da inferência e protege a origem — e é onde o firewall de aplicação se encaixa | Não acelera a inferência em si; resposta de modelo não é cacheável no CDN (a menos que você materialize) |
| Amazon Route 53 | DNS gerenciado com políticas de roteamento e verificação de saúde | Roteamento por latência ou por região quando o assistente é multirregião | É DNS: o tempo de propagação e o cache do resolvedor limitam a velocidade de failover |
O CDN não resolve latência de IA — e ainda pode enganar
É comum alguém propor CloudFront esperando acelerar as respostas. Ele acelera o estático, o handshake e a rota até a origem, mas a inferência acontece atrás de tudo isso e não é cacheável: a mesma pergunta gera resposta nova. Onde o cache de borda realmente entra é sobre resposta materializada de pergunta frequente — que é outra alavanca, do playbook de custo, não da camada de rede.
- → abre conexão e envia a mensagem
- → dispara a função com o connectionId
- → carrega histórico em janela deslizante
- → ConverseStream com cachePoint no prefixo estável
- → empurra cada pedaço pela conexão
- Fora da AWS
- Rede e entrega
- Segurança e identidade
- Compute
- Banco de dados
- IA e machine learning
- Gestão e governança
Percorra os passos: o caminho de ida monta o contexto e o de volta empurra cada pedaço pela mesma conexão. É esse desenho que elimina o timeout da borda síncrona.
- Conectar. O navegador abre a conexão; a rota de conexão autentica e grava o identificador no DynamoDB, associado ao usuário e à sessão.
- Enviar. A mensagem chega pela rota padrão e dispara a Lambda de conversa levando o connectionId junto.
- Montar o contexto. Histórico em janela deslizante do DynamoDB e retrieval com filtro de permissão. O que a pessoa não pode ler não entra no contexto.
- Chamar em fluxo. ConverseStream devolve pedaços conforme o modelo gera, com o ponto de cache marcado no prefixo estável.
- Empurrar. A cada pedaço a Lambda publica na conexão. Se o usuário fechar a aba, interrompa o laço — senão você paga a resposta inteira para ninguém.
- Fechar o turno. Grava a resposta e o uso de tokens, emite métricas por app e libera. Na desconexão, remove o registro da conexão.
Combinações que se repetem
| Borda | Precisa de streaming? | Governança | |
|---|---|---|---|
| Chat no app, resposta longa | API Gateway WebSocket | Sim — é o requisito que define a escolha | Autorizador e quota por área, no próprio gateway |
| API para parceiro | API Gateway REST | Não — resposta curta e estruturada | Plano de uso e chave por consumidor |
| Voz por telefone | Amazon Connect + Lex | Sim, mas em áudio: a percepção é a soma das etapas | Métricas de atendimento já existentes no serviço |
| Documento por e-mail | SES, sem borda HTTP | Não — assíncrono libera batch e tier maior | Regra de processamento e antispam |
| Assistente no Slack | API Gateway HTTP + evento do Slack | Não — a plataforma atualiza a mensagem | Identidade corporativa no SSO, quota por área |
| Agent em container | Application Load Balancer | Depende do produto | Autenticação é sua: o balanceador não tem autorizador |
A coluna do meio é a que decide
Repare que a escolha da borda é quase inteiramente determinada pela segunda coluna. Responder "preciso de streaming?" antes de qualquer outra discussão elimina metade das opções e evita a conversa improdutiva sobre preferência de stack. E a resposta é sim sempre que houver humano esperando por texto longo.
Erros clássicos desta camada
- Escolher a borda sem responder "preciso de streaming?": é a decisão que define a camada, e trocar depois é refazê-la.
- Testar só com perguntas curtas: o timeout aparece exatamente nas perguntas difíceis, que são as que importam para o usuário.
- Não interromper a geração quando o cliente desconecta: você paga a resposta inteira para uma aba que já foi embora.
- Registro de conexão sem expiração automática: a tabela acumula conexões mortas e o custo de estado cresce sozinho.
- Ignorar reconexão no cliente: rede móvel derruba conexão persistente o tempo todo, e o usuário perde o turno.
- Mandar campo de formato conhecido para o modelo: número de pedido e CPF têm validação determinística, e errar a coleta contamina tudo depois.
- Começar pelo canal de voz: é o mais difícil, porque soma transcrição, latência e interrupção antes de você ter aprendido o domínio.
- Esperar que o CDN acelere a inferência: ele acelera tudo em volta, não o modelo.
- Escolher Function URL num ambiente que exige quota por área: você descobre a falta do autorizador quando o compliance pergunta.
O requisito é chat com streaming, autenticação pelo IdP corporativo e quota por área. Por que Function URL com resposta em fluxo não atende?
Num assistente por voz, qual é a consequência arquitetural de as etapas acontecerem em série?
Próximo passo
O pedido chegou. Agora: onde o código roda, quem coordena os passos quando são muitos, e onde mora o estado da conversa. O próximo módulo é sobre os dois limites que definem mais decisões que qualquer preferência de stack — o teto de execução da função e a entrega ao-menos-uma-vez.
Perguntas frequentes
❓ Como colocar IA no atendimento telefônico?
❓ Vale usar serviço de bot conversacional junto com modelo generativo?
❓ Como reduzir latência percebida em canal de voz?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…