agro-market-agent
README.md
# agro-market-agent
[](https://github.com/caioribeiro25/agro-market-agent/actions/workflows/ci.yml)
[](https://www.python.org/)
[](https://github.com/astral-sh/ruff)
[](https://mypy-lang.org/)
[](LICENSE)
Agente de IA multi-step que responde perguntas de inteligência de mercado
agropecuário — *"qual minha margem na soja hoje, com custo de R$95/saca?"* —
decidindo sozinho quais ferramentas chamar, em que ordem, e finalizando com um
relatório. As ferramentas são expostas por um **MCP server** próprio (Model
Context Protocol), reutilizável em qualquer cliente MCP.
Não é um wrapper de chatbot: é um agente instrumentado, testado e avaliado,
construído com as preocupações de um sistema de produção.
## O que este projeto demonstra
| Área | Como |
|------|------|
| **Agente sobre a API oficial** | Loop de tool-use com o SDK da Anthropic — sem framework de orquestração, para deixar explícito o mecanismo. |
| **MCP server próprio** | 5 tools tipadas (`src/agro_market/server.py`), reutilizáveis em qualquer cliente MCP (ex: Claude Desktop). |
| **Avaliação rigorosa** | `tests/eval.py`: precision/recall de seleção de tools + **LLM-as-judge** + **detecção de regressão** contra baseline. |
| **Observabilidade** | Tracing estruturado (spans JSON no stderr), contabilidade de tokens e **custo por execução**, `RunTrace` persistida em disco. |
| **Type safety** | Modelos Pydantic v2 em todas as fronteiras; **mypy strict** e **ruff** no CI. |
| **Robustez** | Guardrails de entrada, timeout global, limite de iterações; cliente HTTP com **retry exponencial + cache TTL**. |
| **Testes sem custo** | Anthropic e HTTP mockados (`respx`) — a suíte roda no CI **sem API key e sem rede**. |
| **Fonte de dados plugável** | Padrão adapter: `mock` (offline, default) ou `yahoo` (HTTP real), trocável por config. |
| **Engenharia de projeto** | `pyproject.toml`, layout `src/`, CI (GitHub Actions), pre-commit, Dockerfile, Makefile. |
## Arquitetura
```
Usuário
│ pergunta em linguagem natural
▼
Agente (Claude + tool runner) ── src/agro_market/agent.py
│ guardrails · tracing · timeout · limite de iterações
│ descobre e chama tools via MCP (stdio)
▼
MCP Server ── src/agro_market/server.py
├── list_commodities
├── get_commodity_price → data_sources.py (mock | yahoo, com retry+cache)
├── calculate_margin → calculations.py (lógica pura)
├── get_historical_trend → db.py (SQLite)
└── generate_report → markdown
```
## Estrutura
```
src/agro_market/
├── agent.py loop de orquestração (Claude + MCP)
├── server.py MCP server (5 tools)
├── data_sources.py adapter de preço: mock | Yahoo (httpx + tenacity + cache)
├── calculations.py lógica de negócio pura
├── db.py SQLite + histórico auto-semeado
├── domain.py modelos Pydantic (contratos entre camadas)
├── observability.py tracer, spans, custo, RunTrace
├── guardrails.py validação de entrada
└── config.py settings tipadas (pydantic-settings)
tests/
├── test_*.py unit + integração (mockados, rodam no CI)
└── eval.py avaliação end-to-end (LLM-as-judge, usa a API)
```
## Quickstart
```bash
python -m venv .venv
.venv\Scripts\activate # Windows (Linux/macOS: source .venv/bin/activate)
pip install -e ".[dev]"
copy .env.example .env # e preencha ANTHROPIC_API_KEY
```
Rodar o agente:
```bash
python -m agro_market.agent "Qual minha margem na soja com custo de R$95/saca em 1000 sacas? Gere um relatório."
```
O agente busca o preço → calcula a margem → consulta a tendência → gera o
relatório, e ao final reporta tools chamadas, tokens, custo e latência.
## Qualidade (o que roda no CI, sem API key)
```bash
make check # ruff + mypy strict + pytest (com cobertura)
# ou individualmente:
ruff check .
mypy
pytest # 20 testes, ~86% de cobertura, sem rede
```
## Avaliação (metodologia)
`tests/eval.py` roda cenários fixos e mede, por caso:
- **Seleção de tools** — precision/recall contra o conjunto esperado.
- **Qualidade da resposta** — LLM-as-judge dá nota 0..1 com justificativa
(via structured output).
- **Custo e latência** por execução.
Agrega as métricas e **compara com um baseline** (`eval_baseline.json`): se a
nota média cair além do limiar, sinaliza regressão e falha. É o que separa
"funcionou uma vez" de "não regrediu".
```bash
python tests/eval.py # exige ANTHROPIC_API_KEY
```
## Observabilidade
Cada execução emite spans estruturados (JSON no stderr, prontos para um
coletor de logs) e persiste uma `RunTrace` completa em `traces/` — pergunta,
spans com duração, tools chamadas, tokens e custo estimado. Debugar uma run
que deu errado é ler um JSON, não vasculhar prints.
## Fontes de dados
- `AGRO_PRICE_SOURCE=mock` (default) — determinística, offline.
- `AGRO_PRICE_SOURCE=yahoo` — futuros via Yahoo Finance, com timeout, retry
exponencial e cache TTL. Ponto de extensão para CEPEA/ESALQ isolado no adapter.
## Configuração
Todas via ambiente (prefixo `AGRO_`) — ver `.env.example`. Principais:
`AGRO_MODEL`, `AGRO_PRICE_SOURCE`, `AGRO_MAX_TOOL_ITERATIONS`, `AGRO_AGENT_TIMEOUT_S`.
## MCP server em outro cliente
```bash
python -m agro_market.server # processo stdio
```
Aponte a config MCP do cliente (ex: Claude Desktop) para esse comando.
## Roadmap
- [ ] Integração CEPEA/ESALQ real no adapter
- [ ] Export de traces em formato OpenTelemetry
- [ ] GIF de demonstração no README
## Stack
Python · Anthropic API (tool use) · Model Context Protocol · Pydantic v2 ·
httpx · tenacity · SQLite · pytest · ruff · mypy · GitHub Actions
TDQS
A4/5.0
Scored across 5 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: listing commodities, getting price, calculating margin, historical trend, and report generation. No overlap or ambiguity.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern in snake_case (e.g., list_commodities, get_commodity_price), making them predictable and easy to understand.
Tool Count5/5
With 5 tools, the server covers the entire agricultural market analysis workflow without being too sparse or overwhelming. Each tool earns its place.
Completeness5/5
The tool set provides a complete lifecycle: discovering commodities, fetching prices, calculating margins, viewing historical trends, and generating reports. No obvious gaps for the intended purpose.
Maintenance
ActivitySlowing
ResponsivenessNo issues