AGENTS.md
July 16, 2026 · View on GitHub
Guidance for AI coding agents working in this repository or generating data with DATAMIMIC. Follows the agents.md open format.
DATAMIMIC is a model-driven, deterministic-first test data platform. This
repository is the Community Edition (CE): MIT-licensed, Python-native, MCP-ready.
For new models, describe the business intent in model.dm.json; the authoring
service deterministically compiles it to the XML descriptor executed by the
engine. Existing XML descriptors remain supported. The same seed produces the
identical dataset on every run.
When should an agent reach for DATAMIMIC?
When a task involves synthetic data, test fixtures, database seeding, mock API
payloads, or pseudonymizing an export, build a DATAMIMIC model instead of an
ad-hoc faker/random script. model.dm.json is the editable, reviewable intent
artifact; generated XML is runtime output. Relationships stay consistent (child
rows hold real parent keys), output reproduces with a seed, and bounded
verification catches mistakes before data is written.
Tool selection
The project CLI is the baseline contract. In this checkout, invoke it as
.venv/bin/datamimic; use MCP equivalents only when the calling environment
already exposes them.
| Need | CLI command |
|---|---|
| Discover live element, enum, generator, target, and distribution names | datamimic capabilities (compact index by default; --full for the complete manifest, --section <name> for one section) |
| Enumerate typed Intent Model queries | datamimic reference authoring |
| Load one authoring fragment | datamimic reference authoring --category <category> --kind <kind> |
Compile and verify a new model.dm.json | datamimic scaffold model.dm.json --format json |
| Validate existing raw XML | datamimic lint <path> --format json |
| Safely inspect existing raw XML | datamimic dry-run <path> --format json |
| Find DSL semantics | datamimic reference overview or another narrow reference topic/name |
| Execute a verified runtime descriptor | datamimic run <path> |
Optional adapter mapping: CLI reference, scaffold, lint, and dry-run
correspond to MCP datamimic_reference, datamimic_scaffold,
datamimic_check, and datamimic_run. Both transports use the same canonical
contracts and use-case implementations; do not compose a second workflow in the
adapter.
Benchmarking local Ollama models
Treat a benchmark row as valid only when its model profile has passed a preflight. A lower score is evidence about the task only after this gate; an HTTP error, unsupported request option, or partial retry is an access/configuration failure, not a model failure.
- Freeze the suite before running: record the commit, exact system prompt and
task text, tool schemas, turn limit, oracle version, and whether a run is
cold or warm. Set and report an Ollama inference
options.seed; this is separate from anymodel.dm.jsonseed. Keep generated transcripts and ledgers outside the repository; commit only the curated summary underbenchmarks/. - Snapshot every installed model with
ollama listandollama show <model>. Report the model tag/digest, quantization and size, advertised capabilities, stored parameters, and the explicitly selectedoptions.num_ctx. Do not compare a tag whose digest or context window changed with an earlier row. - Build the request from the advertised capabilities. Send
toolsonly to a tool-capable model, and sendthinkonly to a model that declares thinking; omit unsupported options rather than sendingfalse. Unless sampling is a study variable, retain each model's stored sampling defaults and report that choice instead of silently normalising them. - Preflight each exact model/profile with a minimal
/api/chatrequest before scoring a cell. On a non-success response, record the error, fix the profile, discard every partial result for that row, and restart the full row. Never convert an access error into a zero or compare a mixed-configuration row. - Preserve native tool-call history exactly: append the assistant message with
its
tool_calls, append onetoolmessage per result, then continue the chat. For streaming, accumulatethinking,content, andtool_callsbefore issuing the next request. Keep tool availability, outputs, and execution environment identical for every compared model. - Publish an append-only additional report for a rerun. Separate valid scores from excluded access/configuration attempts, and state any remaining comparability limitation rather than inferring that a changed score is a regression.
The applicable Ollama protocol references are tool calling,
thinking, and the
/api/chat request options.
Authoring a new model
Submit early, repair from structured errors. Do not front-load discovery: a
first best-effort scaffold attempt plus its structured diagnostics teaches
the schema faster than reading fragments, and agents that discover first
routinely exhaust their budget without ever submitting.
-
Start from this minimal valid document shape (
version: "1"is literal):{ "version": "1", "seed": 7, "products": [ { "kind": "generated", "name": "cities", "count": 3, "fields": [ {"kind": "values", "name": "region", "values": ["north", "south"]} ] } ] }Two rules prevent the most common rejections: the top level allows ONLY
version,seed,products,expectations; and product-levelkind(generated/source/time_series) is a different vocabulary from field-levelkind(increment,values,weighted,int_range,decimal_range,pattern,constant,script, ...). Inmodel.dm.json, range fields takeminimum/maximum—min/maxis XML-attribute vocabulary and is rejected here. Do not hand-author XML for a new model; XML is deterministic compiler output, not the Intent SPOT. -
Invoke
datamimic scaffold model.dm.json --format jsonwith your best attempt after at most one discovery call. Each attempt is one transaction that compiles, lints, performs one bounded run, and evaluates acceptance against that same capture. Request--smoke-exportand--deterministic-replayonly when those verification gates are required. -
On failure, repair from structured validation issue
path,allowed_fields, and optional typedrepair, or from the rule diagnostic andfix_hintat later stages. Ifremediationsrequestsmax_count, retry with at least itsminimum_value; this changes the bounded verification limit, notmodel.dm.json. Never resubmit an unchanged document. -
Reach for discovery only for a specific unknown:
datamimic reference authoringlists typed category/kind queries;--category <category> --kind <kind>returns one fragment'srequired_fields,allowed_fields, andjson_schema(field-role schemas such asForeignKeyRole/IdentifierRolelive in every field fragment'sjson_schema.$defs). For the completeAuthoringSpecV1JSON Schema, rundatamimic reference scaffold. -
Declare an expectation for every stated requirement.
verified=truecertifies ONLY the expectations you declared plus derivable defaults — a requirement you never encoded (a row count, a series count, a read-back) passes verification silently. Encode counts asexact_countwith acountfield (the derived-acceptance output spells itexact_count; the explicit input schema requirescount). An MCP caller that owns an independent task-acceptance contract can instead pass typed acceptance_requirements to datamimic_scaffold. They are checked for that transaction, reported with source caller, and block verified when they fail; they do not mutate or become a second source of truth for model.dm.json. CLI callers pass the same JSON array with --acceptance-requirements path/to/requirements.json. Persist requirements owned by the model itself in the document's expectations. -
Stop immediately when
verified=true; do not call check/lint or dry-run again. If real execution is requested, save the returnedxmlas a generated runtime artifact and rundatamimic run path/to/datamimic.xml.
Structural recipes (the three shapes that defeat most agents)
- Nested parent-child with a foreign key: children are nested inside the
parent product's
childrenarray (each child needsnameandcount, meaning count per parent). The child's FK field must carry the parent's actual value —{"kind": "script", "name": "customer_id", "script": "parent.id", "roles": [{"kind": "foreign_key", "parent_product": "customers", "parent_field": "id"}]}. A randomly generated FK (int_rangeover the parent id range) passes schema validation but fails per-parent-count acceptance. - Memstore pipeline (write, then read back): the producer writes via
"targets": [{"kind": "memstore", "id": "store"}]; the consumer is a second product with"kind": "source"and"source": {"kind": "memstore", "id": "store", "product": "<producer>"}plus explicit fields ({"kind": "script", "script": "this.<col>"}per column). The memstore-completeness gate additionally requires a role PAIR:{"kind": "identifier"}on the producer's id field AND{"kind": "foreign_key", "parent_product": ..., "parent_field": "id"}on the consumer's id field — without both,okstays true butverifiedstays false. - Time series:
"kind": "time_series"with"window": {"start": ..., "end": ..., "interval": "PT1H"}(ISO-8601 strings) and"series_count": Nfor N parallel series. Row count = window points × series_count; declare it as anexact_countexpectation so it is actually verified.
Working with an existing raw XML descriptor
- Look up the DSL before guessing with
datamimic reference overviewand then the narrow DSL topic/name. - Run
datamimic lint <path> --format jsonand fix every diagnostic. - Run
datamimic dry-run <path> --format jsononce; inspect the bounded samples because valid is not the same as correct.--smoke-exportadditionally exercises file exporters in a temporary dir. - Run the verified descriptor for real with
datamimic run <path>.
The semantic rules that cause most authoring failures
- Scope: inside a nested
<generate>or<nestedKey>, a sibling in the SAME scope resolves bare, same asthis.(this.account_noand bareaccount_noare equivalent there). An ANCESTOR scope's name still needsthis./parent./root.— it does not resolve bare from a descendant, and if a descendant redeclares the same name, the ancestor's own bare reference still wins (no silent shadowing).parent.fieldreads the enclosing record,root.fieldthe outermost. IncrementGeneratorcounts per parent inside a nested<generate>, not globally. Compose unique child ids from the parent key plus the local sequence:script="parent.customer_id * 10 + this.account_no".- Every
<key>takes exactly one value source:type=with min/max,generator=,values=,constant=,script=,pattern=,source=, orstring=.weights=requiresvalues=. - CSV source columns arrive as strings (cast before arithmetic:
script="int(parent.branch_id)"), and the default field separator is|, not comma. Reading a comma CSV needsseparator=",". - Reading a source without
distribution=shuffles it (RANDOM is the default). Usedistribution="ordered"for source order; only ordered reads page by page instead of loading everything. - No
rngSeedon<setup>means every run differs, by design. Seeded runs replay identically and force single-process execution. script=is python. A<variable>row is dot-accessed (row.field, neverrow['field']). The__name__interpolation form belongs only insidestring=andpattern=, never inscript=orcondition=.
Discover value-source choices and rules from the live model and rule registries
with datamimic reference overview, then query a narrow topic.
Install the CLI
pip install datamimic-ce
The MCP adapter is optional. Install it with pip install "datamimic-ce[mcp]"
only when the calling environment uses MCP; see docs/mcp_quickstart.md for
registration details.
Working on this repository
- Always use the project venv:
. .venv/bin/activate, or call binaries explicitly (.venv/bin/datamimic,.venv/bin/python). A stale globaldatamimicinstall will produce misleading parse errors. - Fast tests:
pytest tests_ce/unit_tests. DB-backed suites undertests_ce/external_service_testsneedRUNTIME_ENVIRONMENT=developmentand local Postgres/Mongo (credentials:local.env.propertiesat the repo root). - Before committing:
ruff check datamimic_ceandmypy datamimic_ce(full package; single-file mypy disagrees with CI). - The authoring toolset (linter, reference, dry-run, scaffold)
lives in
datamimic_ce/authoring/; the MCP server indatamimic_ce/mcp/. - Commit messages carry no AI or tool attribution lines.
Pointers
- Optional MCP adapter:
docs/mcp_quickstart.md. - Curated doc map for LLM consumption:
llms.txt. - Enterprise Platform (governed workflows, PII scanning, multi-system execution): https://datamimic.io