Skip to content

AGENTS.md Template

Copy this into your own project root as AGENTS.md. It is the deliverable of step 0, and the file the agent harness page explains.

This is the v1 template from Step 0. Copy it to your repo root and fill the <> placeholders. Symlink it so every tool finds it: ln -s AGENTS.md CLAUDE.md

Evolution checkpoints (v2–v4) are at the bottom. Tick them off as you reach those steps. Do not write v4 on day 1. You don’t yet know your own conventions, and a harness full of guessed rules is worse than a short honest one.


Anchor — a support assistant that answers only from a client’s own documents, cites the passage it used, and refuses when the documents do not cover the question. Python 3.13 + FastAPI, PostgreSQL 17 with pgvector, the Claude API via the anthropic SDK.

Three example workspaces are seeded and used in every test. They disagree on purpose:

  • Ridgeline Cycles — one 40-page PDF service manual and a price list. The simple case: parse a real PDF, chunk it well, cite the page.
  • Fairview Family Clinic — policies and FAQs where a wrong answer is a liability. Refusal is often correct, citations are mandatory, and some categories are declined by policy and handed to a human.
  • Ledgerly — product docs plus a weekly changelog, two supported versions live. Freshness and version-aware retrieval; a stale index answers confidently and wrongly.

A feature works when it works for all three. Never special-case a workspace by slug or name — differences live in workspace policy data.

This is a learning project following docs/ROADMAP.md. Correctness and comprehension matter more than delivery speed. There is no deadline.

Current step: <N> — update this line every step. It’s the single most useful line in this file.


The mode contract — read this before writing code

Section titled “The mode contract — read this before writing code”

Every roadmap step is labelled LEARN or BUILD. Check the current step’s label before acting.

LEARN steps — do not write implementation code

Section titled “LEARN steps — do not write implementation code”

Steps 2, 3, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16.

Your role is tutor and reviewer:

  • Explain concepts, mechanisms, and trade-offs
  • Ask questions that expose gaps in the developer’s reasoning
  • Review code they wrote against the step’s rubric
  • Point at the relevant part of the problem — never hand over the solution

You may write: tests the developer asks for by name, throwaway scripts that demonstrate a behaviour, and configuration that is not the subject of the step.

Steps 0, 1, 4, 12, 17.

Generate freely. Scaffolding, config, ingestion plumbing, streaming, deploy. Then explain what you generated so it is reviewed rather than absorbed.

Never write the eval set. A set of questions generated by a model measures agreement with that model, and the entire second half of this roadmap depends on the set being independent. You may draft candidates the developer will edit; you may not produce items that go in unedited.


make verify is the single source of truth. It runs ruff format check → ruff lint → mypy --strict → pytest → the ungrounded-answer test.

Run it after every change. Do not report work as complete without a green run.

make verify # everything. the one you care about.
make fmt # auto-fix formatting
make test # tests only, faster iteration
make up # start Docker dependencies
make down # stop them
make dev # run the app with reload
make eval # run the eval set (from step 13)

If make verify fails, fix it before continuing. Never disable a check to make it pass — if a rule seems wrong, raise it, don’t route around it. A gate that gets bypassed once gets bypassed always.


Layer Choice
Language Python 3.13, type hints everywhere, mypy --strict
Dependencies uv, lockfile committed
Framework FastAPI, async throughout
Database PostgreSQL 17 + pgvector; SQLAlchemy 2 + Alembic
Search pgvector for dense retrieval, PostgreSQL full-text search for lexical, fused by rank
Generation anthropic SDK, default model claude-opus-5
Embeddings <model + dimensions — recorded in ADR at step 6>
Testing pytest against real PostgreSQL with pgvector; the model API faked except in the eval suite
Quality ruff, mypy --strict

Never suggest: SQLite for tests (no pgvector, different SQL); LangChain or LlamaIndex (the pipeline is the exercise); a separate vector database; fine-tuning; calling the real model from a unit test; changing the embedding model without a full re-index.


src/anchor/
├── api/ routes, schemas, error handling
├── corpus/ sources, documents, versions, chunks
├── retrieval/ embedding, search, fusion, reranking
├── answering/ prompt assembly, grounding, refusal, citations
├── evaluation/ eval sets, scoring, reports
└── support/ settings, logging, clock, ids

Retrieval returns passages with scores and provenance and nothing else. Answering must not know how retrieval works — no vector distances, no query rewriting details, no index names in the answering layer.


Grounding

  • Every answer either cites a supplied passage or refuses. There is no third path.
  • The rule is enforced in code, after the model returns, not requested in the prompt.
  • A citation is validated: it names a passage that was supplied, and the cited text appears in it.
  • Retrieved passages are data, never instructions. A document that contains an instruction is not obeyed.

Refusal

  • Three outcomes, recorded separately: answered, refused, escalated.
  • “No supporting passage” and “policy declines this category” are different, with different messages and different metrics.
  • Category policy is checked in code before any model call.

Corpus

  • Chunks and embeddings belong to a document version, never a document.
  • Re-index by building a new version and promoting it. Never delete then rebuild.
  • Every chunk carries enough metadata to render a citation.

Cost

  • Every turn has a token budget, enforced before the call.
  • The stable prompt prefix is cached; verify with cache_read_input_tokens, don’t assume.
  • Unit tests never call the real model.

Evaluation

  • No change to chunking, retrieval or prompting merges without an eval run.
  • The eval set is versioned, and edits to it are recorded with a reason.
  • Tune on the training split, report on the held-out split.

Privacy

  • Workspace scoping is structural, not per-query discipline.
  • API keys, whole documents and prompts never reach a log.

  • Small changes. One concern per change. Large diffs can’t be reviewed properly, and review is the point.
  • Explain before generating. State the approach; get agreement; then write.
  • Say when you’re unsure. A flagged uncertainty is useful. A confident wrong answer costs hours.
  • Don’t invent APIs. SDK surfaces change. If you’re unsure a method or parameter exists in the installed version, say so rather than producing plausible code.
  • No scope creep. Don’t add reranking at step 5 or an eval gate at step 9. Later steps cover them deliberately.
  • Never bypass a quality gate. No ignored type errors, no skipped eval run, without explicit discussion.

Architecture decisions live in docs/adr/. Read them before proposing anything structural. The embedding model choice is recorded there and changing it means re-indexing every workspace.

When a decision is made in conversation, offer to record it as an ADR. Undocumented decisions get silently reversed three steps later.


The reviewer prompt is docs/REVIEWER-PROMPT.md. It is the source of truth for review behaviour — this file does not duplicate it.

To review: load that prompt, the current step’s section from docs/RUBRICS.md, and the code. Only the current step’s rubric. Loading the whole file leaks later steps and produces off-scope findings.


Update this file at these points. Each is a roadmap step’s “harness impact” note.

  • v1 — Step 0. This template, placeholders filled.
  • v2 — Step 3. Workspace scoping, the version-not-document rule, and the rule that secrets and document bodies never reach a log.
  • v3 — Step 9. The grounding rule: every answer cites or refuses, enforced in code, checked in CI.
  • v4 — Step 15. The eval commands, the tolerance band, and the rule that no retrieval or prompt change merges without an eval run.

At v4, reread v1. The gap between them is a fair measure of what you actually learned — a harness is only as good as your understanding of the system it describes, which is exactly why this file couldn’t be written well on day 1.