# AGENTS.md — rules for anyone (human or AI) working in this repo

Read `docs/PROJECT_SPEC.md`, `docs/ARCHITECTURE.md`, and `docs/STAGES.md` before changing code.

## Code style

- Readable code first: clear names, docstrings on every public module, class, and function,
  short single-purpose functions, full type hints.
- Python 3.11+, formatted and linted with `ruff` (line length 100).
- No clever one-liners where a named helper would be clearer.

## Data contracts

- Every agent input and output is a pydantic v2 model. No raw dicts cross an agent boundary.
- Numbers come from SQL/Python (`analytics/`). The LLM only reasons and decides; it never
  computes a metric that code could compute.

## Boundaries (enforced by review and by tests where possible)

- Agents access CRM data **only** through `tools/`. No SQL, no `db/` imports inside `agents/`.
- Only `evaluation/` may read the `ground_truth` table. Tools must never expose it.
- Only `llm/client.py` imports `openai`.
- Only `execution/email.py` imports `resend`.
- Execution happens only after `approval/` policy allows it. Agents propose; they never execute.
- Secrets come from environment variables (`.env`, see `.env.example`). Never commit `.env`.

## Complexity ladder

Start simple and add complexity only when needed, and document why in `docs/STAGES.md`:

1. Augmented LLM (LLM + tools + structured output)
2. Fixed workflow (code decides the sequence)
3. Agent loop (LLM decides the next tool call), always with a step budget

## Process

- Per stage: Explore → Plan → wait for approval → Implement → Test → Commit (tag `stage-XX`).
- Every stage ships with tests. `uv run pytest` must pass before committing.
- Tests must not call the real LLM or send real email, except smoke tests that are skipped
  when credentials are missing.
- Never start the next stage without explicit approval.

## Commands

```bash
cd backend
uv sync                 # install
uv run pytest           # tests (smoke tests skip without AVALAI_API_KEY)
uv run ruff check .     # lint
```
