Docs / Explanation / Agents
Explanation For everyone

Agents

Three agents run in the application, one per agent step of the workflow, each a stateless function from versioned artefacts to a proposal — never to the record.

Role Step In Out
requirements Draft the requirements the brief and the source profiles structured requirements with gradeable criteria
modelling Design the data model the scoped sources' profiles and the shared model a Data Vault design: the shared layer and the product on top
contract Data contract v0.1, and the data contract the requirements, the model, the glossary a v0.1 section per source system; then the draft contract

Two more role files exist and are not wired to a step yet: review (a failed validation run in, a proposed revision and blame out) and sql.

They live in dpf/roles/*.md with frontmatter and a playbook — the house rules, kept separate because that is the part a data team actually edits and its diff should be readable on its own. On startup, any file whose hash is not registered becomes a new agent_versions row; old versions are never touched.

On reproducibility. A model is not bit-reproducible and no amount of version control makes it one. It does not need to be, because of where the deterministic boundary sits: agents produce specifications, and specifications compile to code deterministically. So "run it back" means pinned agent version, pinned inputs, re-run, and diff the proposal against the one that shipped. The code was never the unreproducible part.

What reaches the model

Three agents send text to Anthropic. DPF_LLM_DATA decides what:

What is sent
full Profiles, six sample rows per scoped table, and each column's smallest and largest value. the default, and what a laptop demo wants
metadata Column names, types, null rates, distinct counts, candidate keys. No value from any row. what a deployment should set
off Nothing. The agents are unavailable and every document is written by hand.

metadata is not "send less" — it is a promise about a category, enforced in the one function that gathers grounding, and allow-listed rather than deny-listed so that a statistic the profiler starts reporting tomorrow is left out rather than shipped. It costs something real: without sample rows the agent is materially worse at noticing that a column holds two spellings of the same status. That is a trade the customer should make, which is why it is configuration.

The prompt, the response, the model and the token cost of every call are written to llm_calls before the result is returned, and the mode in force is stated on the Connections page.

Documentation for version 0.2.0 Reviewed 2026-10-19 Covers dpf/agents.py, dpf/llm.py, dpf/privacy.py, dpf/roles/*.md