# bedrock-agent-starter

Template de agente Amazon Bedrock pronto para produção — ferramentas, IaC e evals em 30 minutos.

- URL: https://fernando.moretes.com/open-source/bedrock-agent-starter

- Markdown: https://fernando.moretes.com/open-source/bedrock-agent-starter/guide.md?lang=pt

- GitHub: https://github.com/fernandofatech/bedrock-agent-starter

- Homepage: https://bedrock-agent.moretes.com

- Language: Python

- Topics: ai, ai-agents, aws, bedrock, github-actions, lambda, moretes, portfolio, solution-architecture, terraform

- Stars: 0

- Forks: 0

- Updated: 2026-05-16T02:23:27Z

---

bedrock-agent-starter é um template bilíngue e opinativo que conecta as peças que o Bedrock deixa por sua conta — registro de ferramentas, memória multi-turno, observabilidade estruturada, IaC com Terraform e um harness de avaliação — para que você possa fazer um fork e entregar um agente funcional sem reconstruir o scaffolding do zero.

## Por que este projeto existe

O Amazon Bedrock torna simples chamar um modelo de fundação. Não torna simples entregar um agente real. No momento em que você vai além de um prompt de turno único, precisa decidir como registrar ferramentas, como devolver resultados de ferramentas à conversa, onde persistir o estado da sessão, como emitir métricas sem poluir a lógica de negócio com boilerplate do CloudWatch, e como saber se uma troca de modelo quebrou algo.

Todas as equipes que vi começando do zero passam as primeiras duas semanas resolvendo exatamente esses problemas de infraestrutura. Este starter os resolve uma vez, de forma que seja fácil substituir peça por peça. O loop do agente é construído sobre a [Bedrock Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html), estável entre Claude, Nova, Llama e Mistral — então trocar modelos é uma mudança de variável de ambiente, não uma refatoração.

O projeto também é um artefato de portfólio. É bilíngue (inglês e português), documentado com MkDocs Material no GitHub Pages e tem uma landing page estática no Vercel. Cada commit segue Conventional Commits, cada PR executa ruff, mypy e pytest. A intenção é demonstrar não apenas que consigo montar um agente Bedrock, mas que consigo fazê-lo de uma forma que uma equipe consegue manter.

## O que você recebe pronto para uso

- **Loop do agente** na Bedrock Converse API — agnóstico de modelo, com uso de ferramentas de primeira classe entre Claude, Nova, Llama e Mistral.
- **Registro de ferramentas** com três ferramentas funcionais (`calculator`, `get_time`, stub de `web_search`) e um padrão de decorator de quatro linhas para adicionar as suas; o Pydantic infere o JSON schema automaticamente.
- **Memória plugável** — em memória para desenvolvimento local, respaldada por DynamoDB em produção, trocada por variável de ambiente.
- **Observabilidade estruturada** — linhas de log JSON por turno e métricas CloudWatch EMF (`Turns`, `InputTokens`, `OutputTokens`, `Duration`, `ToolErrors`) no namespace `BedrockAgent`.
- **Esqueleto de IaC com Terraform** que provisiona Lambda, API Gateway HTTP API, tabela DynamoDB de sessões, roles IAM e um log group no CloudWatch.
- **Harness de avaliação** baseado em `pytest` e um arquivo JSONL golden — reproduz prompts, verifica substrings esperadas e chamadas de ferramentas, falha em regressões.

## Como o agente funciona — fluxo de requisição

Uma requisição entra pela CLI local ou pelo API Gateway, passa pelo loop do agente que pode invocar uma ou mais ferramentas Lambda, e emite logs estruturados e métricas EMF a cada turno.

### 💻 Local Dev

- agent chat CLI (user)

### ☁️ AWS Edge

- API Gateway HTTP API (edge)

### ⚙️ Compute

- Lambda Handler Python 3.12 (compute)
- Agent Loop Converse API (compute)
- Tool Registry calculator / get_time / … (compute)

### 🤖 AI

- Amazon Bedrock Converse API (ai)

### 🗄️ Storage

- DynamoDB Sessions Table (storage)

### 📊 Observability

- CloudWatch Logs + EMF Metrics (data)

### Fluxos

- cli -> agentloop: invocação direta
- apigw -> lambda: requisição HTTP
- lambda -> agentloop: delega para
- agentloop -> bedrock: chamada Converse API
- bedrock -> agentloop: tool_use / resposta texto
- agentloop -> toolregistry: despacha chamada de ferramenta
- toolregistry -> agentloop: resultado da ferramenta
- agentloop -> dynamo: lê/escreve sessão
- agentloop -> cw: log JSON + métricas EMF

## Instalar e executar localmente

1. **Clonar o repositório** — Faça fork ou clone diretamente. O branch `main` está sempre em estado funcional.

2. **Criar ambiente virtual e instalar dependências** — Python 3.11+ é necessário. O extra `[dev]` instala ruff, mypy, pytest e MkDocs.

3. **Configurar credenciais AWS e ID do modelo** — Defina `AWS_REGION` e `BEDROCK_MODEL_ID`. O modelo padrão é Claude 3.5 Sonnet v2. Sua identidade IAM precisa de `bedrock:InvokeModel` no ARN do modelo alvo.

4. **Iniciar uma sessão de chat local** — Execute `agent chat`. A CLI usa estado de sessão em memória por padrão — nenhum recurso de armazenamento AWS é necessário para iteração local.

5. **Executar a suíte de testes e avaliações** — `pytest` executa testes unitários; `pytest tests/evals/` reproduz o conjunto JSONL golden e falha em regressões. Execute isso antes de adicionar uma nova ferramenta ou trocar modelos.

6. **Implantar na AWS com Terraform** — No diretório `terraform/`, execute `terraform init` e depois `terraform apply -var="project=my-agent"`. Backend de estado, estratégia de tags e limites de permissão IAM são intencionalmente deixados para você definir conforme os padrões da sua organização.

_Quickstart completo — do clone à primeira resposta do agente_

```bash
git clone git@github.com:fernandofatech/bedrock-agent-starter.git
cd bedrock-agent-starter

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

export AWS_REGION=us-east-1
export BEDROCK_MODEL_ID=anthropic.claude-3-5-sonnet-20241022-v2:0

# Chat locally — no deployed infrastructure needed
agent chat

# > what time is it in Tokyo, and what is (123 * 456) - 789?
# [tool] get_time(tz="Asia/Tokyo") → "2026-05-15T22:41:09+09:00"
# [tool] calculator(expression="(123 * 456) - 789") → 55299
# It is 22:41 in Tokyo, and (123 × 456) − 789 = 55 299.

# Run unit tests + evals
pytest
pytest tests/evals/

# Deploy to AWS
cd terraform
terraform init
terraform apply -var="project=my-agent"
```

## Adicionando uma ferramenta — o padrão de quatro linhas

O registro de ferramentas é a parte deste starter sobre a qual sou mais criterioso. Um modo de falha comum em projetos de agentes é que as definições de ferramentas divergem das implementações — o schema diz uma coisa, a função faz outra, e o modelo alucina parâmetros que não existem.

Aqui, o schema é derivado da assinatura da função no momento da importação via Pydantic. Você escreve um decorator e uma função; o registro os detecta automaticamente na próxima invocação:

```python
from agent.tools import tool

@tool(description="Traduz texto entre idiomas usando uma tabela determinística.")
def translate(text: str, source_lang: str, target_lang: str) -> str:
    ...
    return translated
```

O Pydantic infere `text`, `source_lang` e `target_lang` como propriedades de string obrigatórias no JSON schema enviado ao Bedrock. Se você adicionar um parâmetro com valor padrão, ele se torna opcional no schema. Se anotar com `Literal["en", "pt", "es"]`, o schema ganha uma restrição `enum` — e o modelo a respeitará.

Essa abordagem mantém o schema e a implementação co-localizados e sincronizados. Também significa que você pode testar uma ferramenta em Python puro sem dependência do Bedrock, que é exatamente o que os testes unitários fazem. O guia completo está na [documentação](https://fernandofatech.github.io/bedrock-agent-starter/adding-a-tool/).

## Observabilidade e avaliações — saber quando algo quebra

Duas coisas que vejo sendo mais frequentemente ignoradas em projetos de agentes são observabilidade estruturada e testes de regressão. Ambas estão incluídas aqui e ambas são suficientemente leves para que não haja desculpa para removê-las.

**Observabilidade:** Cada turno emite uma linha de log JSON com `session_id`, `turn`, `model_id`, contagens de tokens, ferramentas chamadas e duração em tempo real. Esses logs vão para o CloudWatch Logs. Em paralelo, métricas CloudWatch EMF são publicadas no namespace `BedrockAgent` — `Turns`, `InputTokens`, `OutputTokens`, `Duration` e `ToolErrors`. EMF significa que você obtém métricas sem uma chamada separada a `put_metric_data`; elas são extraídas da linha de log pelo CloudWatch automaticamente. Isso é suficiente para construir um dashboard e configurar alarmes sobre gasto de tokens ou taxa de erros desde o primeiro dia.

**Avaliações:** O harness de avaliação em `tests/evals/` é intencionalmente simples. Um arquivo `golden.jsonl` contém pares de prompt/saída esperada. O runner pytest envia cada prompt pelo loop real do agente (ou um mock, dependendo da configuração do CI) e verifica se as substrings esperadas aparecem na resposta e se as ferramentas esperadas foram chamadas. Isso não substitui a avaliação humana, mas captura a classe de regressão onde um prompt que funcionava com Claude 3.5 Sonnet para de funcionar após trocar para Nova Pro ou alterar um prompt de sistema. Execute `pytest tests/evals/` antes de qualquer mudança de modelo ou prompt.

> **O que o esqueleto Terraform NÃO faz por você:** O diretório `terraform/` provisiona os recursos principais, mas intencionalmente deixa três coisas indefinidas: backend de estado remoto (S3 + lock DynamoDB), estratégia de tags de recursos e limites de permissão IAM. Essas são decisões específicas da organização. Se você aplicar o esqueleto como está em uma conta AWS compartilhada, o estado será local e as roles IAM não terão limites. Defina isso antes de promover para qualquer ambiente que não seja sandbox.

> **Trocar modelos é uma variável de ambiente:** Como o loop do agente usa a Bedrock Converse API, mudar de Claude 3.5 Sonnet para Amazon Nova Pro ou Mistral Large é `export BEDROCK_MODEL_ID=amazon.nova-pro-v1:0`. Execute `pytest tests/evals/` após a troca para capturar regressões de formato de prompt antes que cheguem à produção.

## Perguntas frequentes

### Preciso solicitar acesso a um modelo Bedrock antes de executar localmente?

Sim. O acesso a modelos Bedrock não está habilitado por padrão. Vá ao console do Bedrock → Acesso a modelos, solicite acesso ao modelo que pretende usar e aguarde a aprovação (geralmente instantânea para Claude e Nova em us-east-1). Sua identidade IAM também precisa de `bedrock:InvokeModel` no ARN do modelo.

### Posso usar isso com o Bedrock Agents (o serviço de orquestração gerenciado) em vez da Converse API?

Não — este starter implementa seu próprio loop de agente usando a Converse API diretamente. Ele não usa o serviço gerenciado Bedrock Agents (que tem seus próprios grupos de ação, bases de conhecimento e gerenciamento de sessão). A troca é mais controle e menor custo ao custo de gerenciar o loop você mesmo. Se você quiser o serviço gerenciado, este starter não é o ponto de partida correto.

### Como adiciono memória persistente em produção?

Defina a variável de ambiente `MEMORY_BACKEND=dynamodb` (ou a variável Terraform equivalente). O handler Lambda usará a tabela DynamoDB de sessões provisionada pelo Terraform. A chave da tabela é `session_id`; o TTL é configurável. O backend em memória permanece como padrão para desenvolvimento local.

### A ferramenta `web_search` é funcional?

É um stub. Demonstra o padrão de ferramenta, mas retorna uma resposta de placeholder. Conectá-la a uma API de busca real (Brave Search, Tavily, SerpAPI) é um exercício deliberado deixado para o implementador — o ponto de integração está claramente marcado no código-fonte.

## Para quem é e quando usar

Use este starter se você está construindo um agente personalizado no Amazon Bedrock e quer uma base sólida em vez de um arquivo em branco. É adequado para: arquitetos de soluções avaliando o Bedrock para um cliente, engenheiros que precisam de um agente funcional em um dia e planejam estendê-lo, e equipes que querem um exemplo de como estruturar observabilidade e avaliações em um projeto de agente desde o início.

Não use se você quer o serviço gerenciado Bedrock Agents (grupos de ação, bases de conhecimento, orquestração gerenciada) — este starter deliberadamente contorna isso em favor de um loop autogerenciado. Também não use se precisar de um framework de orquestração multi-agente como LangGraph ou AutoGen; o escopo aqui é um loop de agente único com ferramentas e memória.

O projeto é licenciado sob MIT, bilíngue e mantido ativamente como parte do meu portfólio público. O site de documentação em [bedrock-agent.moretes.com](https://bedrock-agent.moretes.com) e os docs do GitHub Pages são mantidos em sincronia com o branch main.

## Links e recursos

- [GitHub — fernandofatech/bedrock-agent-starter](https://github.com/fernandofatech/bedrock-agent-starter)
- [Live portfolio site — bedrock-agent.moretes.com](https://bedrock-agent.moretes.com)
- [Project documentation (GitHub Pages)](https://fernandofatech.github.io/bedrock-agent-starter/)
- [Amazon Bedrock Converse API — AWS Documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)
- [Amazon Bedrock — product page](https://aws.amazon.com/bedrock/)
- [CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html)
- [Terraform AWS Provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
- [MkDocs Material](https://squidfunk.github.io/mkdocs-material/)

## Links

- [GitHub repository](https://github.com/fernandofatech/bedrock-agent-starter)
- [Homepage](https://bedrock-agent.moretes.com)
