ariadne-data 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ariadne_data-0.2.0/PKG-INFO +363 -0
- ariadne_data-0.2.0/README.md +339 -0
- ariadne_data-0.2.0/pyproject.toml +87 -0
- ariadne_data-0.2.0/setup.cfg +4 -0
- ariadne_data-0.2.0/src/ariadne/__init__.py +1 -0
- ariadne_data-0.2.0/src/ariadne/admission.py +1148 -0
- ariadne_data-0.2.0/src/ariadne/answer_examples.py +492 -0
- ariadne_data-0.2.0/src/ariadne/author.py +839 -0
- ariadne_data-0.2.0/src/ariadne/authoring.py +3937 -0
- ariadne_data-0.2.0/src/ariadne/authoring_cli.py +743 -0
- ariadne_data-0.2.0/src/ariadne/authoring_context.py +106 -0
- ariadne_data-0.2.0/src/ariadne/authoring_inputs.py +515 -0
- ariadne_data-0.2.0/src/ariadne/authoring_semantic.py +75 -0
- ariadne_data-0.2.0/src/ariadne/authoring_sources.py +387 -0
- ariadne_data-0.2.0/src/ariadne/cli.py +433 -0
- ariadne_data-0.2.0/src/ariadne/context.py +3897 -0
- ariadne_data-0.2.0/src/ariadne/example_review.py +552 -0
- ariadne_data-0.2.0/src/ariadne/execution.py +294 -0
- ariadne_data-0.2.0/src/ariadne/grain.py +188 -0
- ariadne_data-0.2.0/src/ariadne/ingest.py +1121 -0
- ariadne_data-0.2.0/src/ariadne/init.py +369 -0
- ariadne_data-0.2.0/src/ariadne/migration.py +631 -0
- ariadne_data-0.2.0/src/ariadne/planner.py +2940 -0
- ariadne_data-0.2.0/src/ariadne/profiler.py +521 -0
- ariadne_data-0.2.0/src/ariadne/promote.py +584 -0
- ariadne_data-0.2.0/src/ariadne/proposals.py +1228 -0
- ariadne_data-0.2.0/src/ariadne/query.py +1616 -0
- ariadne_data-0.2.0/src/ariadne/query_results.py +558 -0
- ariadne_data-0.2.0/src/ariadne/render.py +435 -0
- ariadne_data-0.2.0/src/ariadne/runtime.py +21 -0
- ariadne_data-0.2.0/src/ariadne/semantic_graph.py +884 -0
- ariadne_data-0.2.0/src/ariadne/serve.py +1471 -0
- ariadne_data-0.2.0/src/ariadne/skill.py +147 -0
- ariadne_data-0.2.0/src/ariadne/skill_assets/SKILL.md +503 -0
- ariadne_data-0.2.0/src/ariadne/skill_assets/references/grain-rubric.md +69 -0
- ariadne_data-0.2.0/src/ariadne/sources.py +575 -0
- ariadne_data-0.2.0/src/ariadne/sql_authority.py +620 -0
- ariadne_data-0.2.0/src/ariadne/validate.py +986 -0
- ariadne_data-0.2.0/src/ariadne_data.egg-info/PKG-INFO +363 -0
- ariadne_data-0.2.0/src/ariadne_data.egg-info/SOURCES.txt +77 -0
- ariadne_data-0.2.0/src/ariadne_data.egg-info/dependency_links.txt +1 -0
- ariadne_data-0.2.0/src/ariadne_data.egg-info/entry_points.txt +15 -0
- ariadne_data-0.2.0/src/ariadne_data.egg-info/requires.txt +20 -0
- ariadne_data-0.2.0/src/ariadne_data.egg-info/top_level.txt +1 -0
- ariadne_data-0.2.0/tests/test_answer_examples.py +1066 -0
- ariadne_data-0.2.0/tests/test_author.py +1121 -0
- ariadne_data-0.2.0/tests/test_authoring.py +1959 -0
- ariadne_data-0.2.0/tests/test_authoring_mcp.py +971 -0
- ariadne_data-0.2.0/tests/test_business_answers.py +563 -0
- ariadne_data-0.2.0/tests/test_cli.py +641 -0
- ariadne_data-0.2.0/tests/test_context_admission.py +1268 -0
- ariadne_data-0.2.0/tests/test_context_browsing.py +142 -0
- ariadne_data-0.2.0/tests/test_context_schema.py +959 -0
- ariadne_data-0.2.0/tests/test_context_signals.py +369 -0
- ariadne_data-0.2.0/tests/test_data_signals.py +2131 -0
- ariadne_data-0.2.0/tests/test_docker_mcp.py +183 -0
- ariadne_data-0.2.0/tests/test_evals.py +563 -0
- ariadne_data-0.2.0/tests/test_git_admission.py +1444 -0
- ariadne_data-0.2.0/tests/test_git_authoring.py +1110 -0
- ariadne_data-0.2.0/tests/test_git_migration.py +1162 -0
- ariadne_data-0.2.0/tests/test_git_proposals.py +1117 -0
- ariadne_data-0.2.0/tests/test_git_source_access.py +515 -0
- ariadne_data-0.2.0/tests/test_ingest.py +1902 -0
- ariadne_data-0.2.0/tests/test_init.py +335 -0
- ariadne_data-0.2.0/tests/test_mapping_inspection.py +1568 -0
- ariadne_data-0.2.0/tests/test_mcp_toolsets.py +530 -0
- ariadne_data-0.2.0/tests/test_multifact.py +3329 -0
- ariadne_data-0.2.0/tests/test_profiler.py +421 -0
- ariadne_data-0.2.0/tests/test_promote.py +691 -0
- ariadne_data-0.2.0/tests/test_query_containment.py +317 -0
- ariadne_data-0.2.0/tests/test_query_records.py +1048 -0
- ariadne_data-0.2.0/tests/test_query_results.py +1003 -0
- ariadne_data-0.2.0/tests/test_render.py +248 -0
- ariadne_data-0.2.0/tests/test_seed.py +220 -0
- ariadne_data-0.2.0/tests/test_serve.py +1385 -0
- ariadne_data-0.2.0/tests/test_skill.py +350 -0
- ariadne_data-0.2.0/tests/test_sources.py +633 -0
- ariadne_data-0.2.0/tests/test_terms.py +931 -0
- ariadne_data-0.2.0/tests/test_validate.py +492 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ariadne-data
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Governed metrics for autonomous agents: OKF context layer + OSI semantic layer behind one MCP facade
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: duckdb>=1.0
|
|
8
|
+
Requires-Dist: sqlglot>=25.0
|
|
9
|
+
Requires-Dist: openai>=1.40
|
|
10
|
+
Requires-Dist: pyyaml>=6.0
|
|
11
|
+
Provides-Extra: mcp
|
|
12
|
+
Requires-Dist: mcp<2,>=1.2; extra == "mcp"
|
|
13
|
+
Provides-Extra: documents
|
|
14
|
+
Requires-Dist: liteparse>=2.4.0; extra == "documents"
|
|
15
|
+
Requires-Dist: markitdown[docx]>=0.1.6; extra == "documents"
|
|
16
|
+
Requires-Dist: firecrawl-anydoc==0.1.3; extra == "documents"
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
19
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
20
|
+
Requires-Dist: mcp<2,>=1.2; extra == "dev"
|
|
21
|
+
Requires-Dist: liteparse>=2.4.0; extra == "dev"
|
|
22
|
+
Requires-Dist: markitdown[docx]>=0.1.6; extra == "dev"
|
|
23
|
+
Requires-Dist: firecrawl-anydoc==0.1.3; extra == "dev"
|
|
24
|
+
|
|
25
|
+
# Ariadne
|
|
26
|
+
|
|
27
|
+
**Governed metrics for AI agents.** Ariadne sits between your data and your AI agent
|
|
28
|
+
and makes sure the numbers coming back are the numbers your business agreed on.
|
|
29
|
+
|
|
30
|
+
When an agent writes SQL directly against a database (text-to-SQL), it guesses: which
|
|
31
|
+
table, which join, which filter, which definition of "revenue". Two runs of the same
|
|
32
|
+
question can return different answers, and nothing tells the agent that cancelled orders
|
|
33
|
+
must be excluded or that the currency changed in March. Ariadne replaces the guessing
|
|
34
|
+
with a governed catalog:
|
|
35
|
+
|
|
36
|
+
- A **semantic layer** holds the one canonical definition of each metric, written in
|
|
37
|
+
the open [OSI](https://ossie.apache.org/) YAML format. Ariadne compiles these to SQL
|
|
38
|
+
itself and executes them read-only — no agent ever hand-writes a query for a governed
|
|
39
|
+
number.
|
|
40
|
+
- A **context layer** holds the business knowledge around those metrics — policies,
|
|
41
|
+
table caveats, provenance — as plain version-controlled Markdown. Every governed
|
|
42
|
+
answer carries its caveats with it, so the agent reports "revenue was X *— excluding
|
|
43
|
+
cancelled orders, per policy*" instead of a bare number.
|
|
44
|
+
|
|
45
|
+
Agents query Ariadne through the local `ariadne` command line — no server to run,
|
|
46
|
+
no extra setup. Ariadne also speaks [MCP](https://modelcontextprotocol.io/), the
|
|
47
|
+
standard tool protocol, as an optional extra (`ariadne-data[mcp]`) for remote or
|
|
48
|
+
host-integrated tool registration.
|
|
49
|
+
|
|
50
|
+
## What you get
|
|
51
|
+
|
|
52
|
+
### For querying agents
|
|
53
|
+
|
|
54
|
+
- **Local commands** covering the full question lifecycle (see below) — governed answers
|
|
55
|
+
first, with a safe path for anything not yet modeled, plus saved answer examples as
|
|
56
|
+
labeled method references. No server required.
|
|
57
|
+
- **Caveats attached to every number.** Governed answers include the full text of every
|
|
58
|
+
business policy the metric cites. Ungoverned answers are clearly labeled
|
|
59
|
+
`governed: false`.
|
|
60
|
+
- **Fan-out protection.** Ad-hoc queries are checked for grain-preserving joins *before*
|
|
61
|
+
execution, so one-to-many joins can't silently inflate totals — a classic way
|
|
62
|
+
text-to-SQL agents produce wrong-but-confident numbers.
|
|
63
|
+
|
|
64
|
+
### For data owners
|
|
65
|
+
|
|
66
|
+
- **AI-assisted authoring, human gate.** One command profiles your databases and drafts
|
|
67
|
+
the entire metric catalog and context pages into a `staging/` area. Nothing is ever
|
|
68
|
+
served until a human reviews and promotes it.
|
|
69
|
+
- **Bring your own agent.** In harness-led authoring, your agent's *own* model drafts
|
|
70
|
+
the catalog from measured profiles and converted documents (`ariadne-authoring`) —
|
|
71
|
+
no server-side LLM. Source access, admission and Promotion stay human decisions.
|
|
72
|
+
- **Everything is files.** Metrics are YAML, business knowledge is Markdown. Review in
|
|
73
|
+
pull requests, diff definitions, roll back with git. No server database to migrate.
|
|
74
|
+
- **Self-improving catalog.** When an agent answers an unmodeled question, its working
|
|
75
|
+
definition is automatically staged as a proposal — good ad-hoc answers become
|
|
76
|
+
governed metrics through the same human review.
|
|
77
|
+
- **Document ingestion.** Feed existing data dictionaries, PDFs, or Office documents in;
|
|
78
|
+
get typed, provenance-cited proposals out, staged for review.
|
|
79
|
+
|
|
80
|
+
### For everyone
|
|
81
|
+
|
|
82
|
+
- **Lightweight.** A Python package plus embedded DuckDB. No API gateway, cache cluster,
|
|
83
|
+
or refresh workers to operate.
|
|
84
|
+
- **Permissive runtime.** Only MIT/Apache-licensed dependencies — no AGPL, no proprietary
|
|
85
|
+
engine.
|
|
86
|
+
|
|
87
|
+
## How it works
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
your data ──▶ profile ──▶ author (AI) ──▶ staging/ ──▶ human review ──▶ served catalog
|
|
91
|
+
(many sources) drafts everything nothing serves metrics + policies
|
|
92
|
+
from here │
|
|
93
|
+
▼
|
|
94
|
+
AI agent runs `ariadne` (local) or connects over MCP:
|
|
95
|
+
Ariadne compiles the metric
|
|
96
|
+
to SQL, checks it, runs it read-only,
|
|
97
|
+
returns the number + its business caveats
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
1. **Register your sources** in one `ariadne.yaml` file.
|
|
101
|
+
2. **Profile & author**: `ariadne-author` inspects the actual data and combines it with
|
|
102
|
+
your seed notes (the rules statistics can't see) to draft the catalog into `staging/`.
|
|
103
|
+
Or let your own agent's model draft through `ariadne-authoring` Git proposals (see
|
|
104
|
+
"Harness-led authoring" below) — either way, a human reviews, and only a human
|
|
105
|
+
promotes or admits.
|
|
106
|
+
3. **Review & promote (legacy staged project)**: a human reads the staging area, then
|
|
107
|
+
`ariadne-promote` merges approved artifacts into the served catalog and marks them
|
|
108
|
+
verified. **Git-managed project**: a human admits the exact reviewed, validated
|
|
109
|
+
candidate revision with `ariadne-admit --confirm` (see
|
|
110
|
+
[docs/how-to/git-authoring.md](docs/how-to/git-authoring.md)).
|
|
111
|
+
4. **Query**: your agent runs `ariadne` locally against the promoted catalog (`--served`)
|
|
112
|
+
or the pinned admitted snapshot (`--project DIR`) — or connects over MCP with the
|
|
113
|
+
optional extra.
|
|
114
|
+
|
|
115
|
+
## Quickstart
|
|
116
|
+
|
|
117
|
+
Requires Python ≥ 3.12 and [uv](https://docs.astral.sh/uv/). Authoring uses an LLM —
|
|
118
|
+
set `OPENAI_API_KEY` (plus `OPENAI_BASE_URL` / `OPENAI_MODEL` if not using OpenAI
|
|
119
|
+
directly) in a `.env` file.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
uv venv --python 3.12 .venv
|
|
123
|
+
uv pip install --python .venv/bin/python -e .
|
|
124
|
+
source .venv/bin/activate
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**See it end-to-end** on a bundled example (seeds a demo shop, authors a catalog with a
|
|
128
|
+
live LLM, pauses for your review, then queries a governed metric locally):
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
examples/retail-demo/demo.sh
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Point it at your own data:**
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
ariadne-init my-project && cd my-project # scaffold registry, seed notes (local-first)
|
|
138
|
+
# edit ariadne.yaml (your sources) and data/seed_notes.md (your business rules)
|
|
139
|
+
ariadne-author --sources ariadne.yaml --notes data/seed_notes.md
|
|
140
|
+
# review staging/, then:
|
|
141
|
+
ariadne-promote
|
|
142
|
+
ariadne list-metrics --sources ariadne.yaml # query locally — no server needed
|
|
143
|
+
ariadne get-metric gross_margin --sources ariadne.yaml
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Or run the same project Git-managed — isolated revision-checked proposals, exact-
|
|
147
|
+
revision human admission, pinned snapshots (the full legacy → new mapping lives in
|
|
148
|
+
[docs/how-to/git-authoring.md](docs/how-to/git-authoring.md)):
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
ariadne-init --git my-project && cd my-project && git init
|
|
152
|
+
# declare sources, then (agent or you):
|
|
153
|
+
ariadne-authoring start --project .
|
|
154
|
+
ariadne-authoring propose-sources --proposal ID --expected-revision REV --file sources.yaml
|
|
155
|
+
# HUMAN: ariadne-authoring approve-sources --project . --proposal ID \
|
|
156
|
+
# --revision REV --source-digest DIGEST
|
|
157
|
+
ariadne-authoring edit --proposal ID --expected-revision REV --file edit.json
|
|
158
|
+
ariadne-authoring validate --proposal ID --expected-revision REV
|
|
159
|
+
ariadne-authoring review --proposal ID
|
|
160
|
+
# HUMAN: ariadne-admit --project . --proposal ID --revision REV \
|
|
161
|
+
# --reviewed-digest DIGEST --confirm
|
|
162
|
+
ariadne list-metrics --project . # queries the pinned admitted snapshot
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Already have a legacy staged project? The human import moves its served artifacts
|
|
166
|
+
into an unadmitted Git proposal without touching pending staging work — never
|
|
167
|
+
admission:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
ariadne-init --git . && git init
|
|
171
|
+
ariadne-authoring import-legacy --project . --from-root . # HUMAN
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Imported legacy table pages bind to their approved catalog assets with the
|
|
175
|
+
human `ariadne-authoring enrich-legacy` (ambiguous same-named tables refuse
|
|
176
|
+
rather than guess), and the explicit `refresh-schema` generates their physical
|
|
177
|
+
schema facts. Context knowledge — physical schemas, shared terminology,
|
|
178
|
+
identifier mappings and bounded mapping evidence with automatic hypothesis
|
|
179
|
+
capture — has its own guide:
|
|
180
|
+
[docs/how-to/context-knowledge.md](docs/how-to/context-knowledge.md).
|
|
181
|
+
Aliases, observations and measurements never authorize joins or replace the
|
|
182
|
+
compile gate and live audits.
|
|
183
|
+
|
|
184
|
+
Installing the packaged skill (`ariadne-skill install --scope user`) teaches your agent
|
|
185
|
+
the whole workflow — query governed metrics first, respect the staging boundary, report
|
|
186
|
+
caveats with every number.
|
|
187
|
+
|
|
188
|
+
### Harness-led authoring — bring your own agent
|
|
189
|
+
|
|
190
|
+
`ariadne-author` above drafts using an LLM configured on the host (`.env`). If your
|
|
191
|
+
agent harness has its own model, it authors instead through the local
|
|
192
|
+
`ariadne-authoring` commands — base install only, no OpenAI-compatible endpoint, no
|
|
193
|
+
extra credential. In a Git-managed project (scaffolded with `ariadne-init --git`, the
|
|
194
|
+
flow above) the agent drafts through isolated proposals; `ariadne-author --git` runs
|
|
195
|
+
the same drafting loop straight into an unadmitted proposal. The legacy staged route
|
|
196
|
+
below keeps working for non-Git projects:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
ariadne-init my-project && cd my-project
|
|
200
|
+
# 1. agent: propose source registry entries (inert data — nothing is opened yet)
|
|
201
|
+
ariadne-authoring propose-sources --file sources-proposal.yaml
|
|
202
|
+
# 2. HUMAN operator (never the agent): review the digest, install into ariadne.yaml
|
|
203
|
+
# ariadne-authoring approve-sources --digest <digest>
|
|
204
|
+
# 3. agent: read the measured profile (null until step 2) and converted documents
|
|
205
|
+
# from data/docs/ (allowed roots live in ariadne.yaml's documents: section)
|
|
206
|
+
ariadne-authoring inputs --document policy-notes.md
|
|
207
|
+
# 4. agent's own model drafts Seed Notes + OSI + OKF, submits, repairs on errors
|
|
208
|
+
# (3 rounds max; each repair needs the current digest as --base-digest)
|
|
209
|
+
ariadne-authoring submit --file submission.json # cites its document references
|
|
210
|
+
# 5. agent inspects and reports the exact digest, then STOPS
|
|
211
|
+
ariadne-authoring review
|
|
212
|
+
# 6. HUMAN (never the agent): ariadne-promote on the reviewed digest
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Documents are pre-staged by the operator in `data/docs/` (or another configured
|
|
216
|
+
root); PDF/Office/HTML conversion uses the optional `.[documents]` extra, and
|
|
217
|
+
inputs are bounded (converted text arrives in parts). Metrics without an
|
|
218
|
+
independent expected-value oracle are staged with `attestation: pending` —
|
|
219
|
+
`governed: true` means Promoted, not independently value-attested.
|
|
220
|
+
|
|
221
|
+
**Optional: stdio MCP toolsets.** With the `mcp` extra installed (see below),
|
|
222
|
+
the same local stdio server exposes the role toolsets over one core — pick the
|
|
223
|
+
registration at launch: `python -m ariadne.serve --project DIR` (combined,
|
|
224
|
+
the default), `--toolset analyst` (the query tools `list_metrics`,
|
|
225
|
+
`search_context`, `get_metric`, `list_datasets`, `define_metric`,
|
|
226
|
+
`query_metrics`, `query_detail`, `query_records`, `resolve_term`,
|
|
227
|
+
`save_example`, `search_examples`), or `--toolset authoring` (the Git proposal contract:
|
|
228
|
+
`authoring_start_proposal`, `authoring_read_artifact`,
|
|
229
|
+
`authoring_edit_proposal`, `authoring_propose_sources`, `authoring_inputs`,
|
|
230
|
+
`authoring_upload_document` for bounded ≤5 MiB uploads,
|
|
231
|
+
`authoring_refresh_schema`, `authoring_validate_proposal`,
|
|
232
|
+
`authoring_inspect_mapping`, `authoring_resolve_term`,
|
|
233
|
+
`authoring_review_proposal`) with identical
|
|
234
|
+
contracts to the `ariadne-authoring` commands. Stdio is local and needs no
|
|
235
|
+
token; the server runs for one project root. Source approval, admission,
|
|
236
|
+
reconciliation, the legacy import/enrichment and Promotion are never exposed
|
|
237
|
+
as tools.
|
|
238
|
+
|
|
239
|
+
**Opt-in HTTP (issue #18).** `ariadne-serve --project DIR --http` serves the
|
|
240
|
+
same toolsets at `/mcp`, on loopback (`127.0.0.1`) by default. Every request,
|
|
241
|
+
including health/readiness checks, requires `Authorization: Bearer <token>`
|
|
242
|
+
from the server environment `ARIADNE_HTTP_TOKEN`. Missing/wrong tokens fail
|
|
243
|
+
before dispatch; the token never belongs in `ariadne.yaml`, responses or logs.
|
|
244
|
+
Stdio remains token-free and opens no HTTP listener.
|
|
245
|
+
|
|
246
|
+
**Compose/container binding (owner-approved 2026-10-10).** Add
|
|
247
|
+
`--http-container --http-host 0.0.0.0` to allow other containers to connect.
|
|
248
|
+
The default Compose service publishes no ports; put the MCP client or HTTPS
|
|
249
|
+
proxy on the same network. The separate loopback-only override is for a
|
|
250
|
+
host-side private HTTPS proxy such as Tailscale Serve. External clients still
|
|
251
|
+
require private HTTPS. This option is not deployment/exposure approval.
|
|
252
|
+
|
|
253
|
+
The SDK's DNS-rebinding protection stays enabled. Explicitly add the service
|
|
254
|
+
and proxy Host values using repeatable `--http-allowed-host` flags. For
|
|
255
|
+
clients sending an Origin header, add its exact origin with
|
|
256
|
+
`--http-allowed-origin`; requests without Origin need no origin entry.
|
|
257
|
+
Do not use blanket wildcards. The repository includes a non-root
|
|
258
|
+
[Dockerfile](Dockerfile), [Compose template](compose.yaml) and
|
|
259
|
+
[loopback override](compose.loopback.yaml). See
|
|
260
|
+
[Docker MCP with an external data project](docs/how-to/docker-mcp.md) for
|
|
261
|
+
owner permissions, stable Git/source paths, networking and the smoke check.
|
|
262
|
+
The project stays external and is mounted at the same absolute host/container
|
|
263
|
+
path; the image does not contain project data or credentials. A network client
|
|
264
|
+
uses `http://ariadne:8000/mcp` with the bearer token. A private HTTPS proxy
|
|
265
|
+
must preserve Authorization/MCP headers and streaming; configure it separately.
|
|
266
|
+
|
|
267
|
+
- `GET /healthz`: `200 {"status":"ok"}` when the HTTP process responds.
|
|
268
|
+
- `GET /readyz`: `200 {"status":"ready"}` for Authoring without requiring a
|
|
269
|
+
catalog; Analyst/Combined require a usable metric catalog through the shared
|
|
270
|
+
runtime's discovery/admission checks. Failures return only
|
|
271
|
+
`503 {"status":"not_ready"}`, never exception details or project paths.
|
|
272
|
+
- Both accept HEAD and require the same bearer token. Readiness does not
|
|
273
|
+
calculate metrics or test every source/graph operation. A lazy runtime may
|
|
274
|
+
perform its existing bounded source initialization on the first ready check.
|
|
275
|
+
|
|
276
|
+
**Optional: MCP.** The base package is local-first and needs no server; MCP registers the
|
|
277
|
+
same operations as tools when you want them. Install the extra into the same Python
|
|
278
|
+
environment as `ariadne`, from the Ariadne package checkout (the directory containing
|
|
279
|
+
`pyproject.toml`):
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
uv pip install --python .venv/bin/python -e '.[mcp]'
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Then, from the initialized project root, opt in to its registry-aware `.mcp.json` (an
|
|
286
|
+
existing file is never overwritten) and start the server:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
ariadne-init --with-mcp .
|
|
290
|
+
ariadne-serve --sources ariadne.yaml
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The scaffolded `.mcp.json` wires your agent to `ariadne-serve`; restart the agent after
|
|
294
|
+
config changes.
|
|
295
|
+
|
|
296
|
+
## Querying: the local commands
|
|
297
|
+
|
|
298
|
+
All commands print one JSON value; the common options (`--sources`/`--db`, `--served`) follow
|
|
299
|
+
the subcommand. The CLI finds promoted artifacts in the working directory or `./served`.
|
|
300
|
+
MCP registers the same operations as tools when the `mcp` extra is installed.
|
|
301
|
+
|
|
302
|
+
| Command | What the agent uses it for |
|
|
303
|
+
| --- | --- |
|
|
304
|
+
| `ariadne list-metrics` | Browse the governed catalog: metrics, descriptions, available dimensions |
|
|
305
|
+
| `ariadne get-metric NAME` | Get a governed number — compiled SQL, executed read-only, caveats included |
|
|
306
|
+
| `ariadne search-context QUERY` | Look up business rules, policies, and table caveats before answering |
|
|
307
|
+
| `ariadne resolve-term TERM` | Resolve shared business terms and identifier knowledge (representations, exact field bindings, scope, ambiguity, claim/confirmation status) against the admitted context — read-only guidance, never join authority |
|
|
308
|
+
| `ariadne list-datasets` | See every table across all registered sources |
|
|
309
|
+
| `ariadne query-records` | Bounded record selection from one known table — the latest N rows, no aggregation: explicit filters/order/timestamp contract, `governed: false`, never staged, truthful requested-top-N completeness, and all-or-nothing overflow refusals with narrowing guidance |
|
|
310
|
+
| `ariadne define-metric` | Answer an unmodeled question: draft a metric (JSON via `--file` or stdin), pass the safety checks (ad-hoc SQL may read only registered catalog relations — file, network and table-function reads are refused before execution), run it read-only, label it `governed: false`, and auto-stage it as a proposal |
|
|
311
|
+
| `ariadne search-examples QUERY` | Find explicitly saved answer examples — labeled references (draft/stable, staleness, provenance) for checking a method, never cached answers; never executes a query |
|
|
312
|
+
| `ariadne save-example` | Save one answer example after the user explicitly confirms the bounded record (question, interpretation, method, result excerpt, self-declared attestation); stages a draft under `staging/answer_examples/` for operator review |
|
|
313
|
+
|
|
314
|
+
Saved examples are references, not caches: a similar question still compares dates, filters,
|
|
315
|
+
grain and cited policies, and the answer is always produced fresh by the runtime. Reviewing
|
|
316
|
+
submissions is an operator command (`ariadne-example-review`), never an agent action.
|
|
317
|
+
|
|
318
|
+
## Data sources
|
|
319
|
+
|
|
320
|
+
One read-only connection unifies every source; the agent addresses them as
|
|
321
|
+
`<source>.<table>`:
|
|
322
|
+
|
|
323
|
+
```yaml
|
|
324
|
+
sources:
|
|
325
|
+
- name: shop
|
|
326
|
+
type: sqlite
|
|
327
|
+
path: data/shop.db
|
|
328
|
+
- name: events
|
|
329
|
+
type: parquet
|
|
330
|
+
path: data/events/*.parquet # globs become one table
|
|
331
|
+
table: events
|
|
332
|
+
- name: warehouse
|
|
333
|
+
type: postgres
|
|
334
|
+
connection_env: ARIADNE_PG_DSN # credentials are env-var names, never inline
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Supported: **SQLite, CSV, JSON, Parquet, Delta Lake, Iceberg, DuckLake, PostgreSQL** —
|
|
338
|
+
local files, `https://`, or `s3://`. Document ingestion (optional extra
|
|
339
|
+
`.[documents]`) covers Markdown, text, PDF, Word, PowerPoint, Excel, and HTML.
|
|
340
|
+
|
|
341
|
+
## How Ariadne compares
|
|
342
|
+
|
|
343
|
+
| Approach | What it is | Where Ariadne differs |
|
|
344
|
+
| --- | --- | --- |
|
|
345
|
+
| **Raw text-to-SQL agents** | The agent writes SQL directly against your database | No canonical definitions, no business rules, joins can silently inflate numbers. Ariadne compiles every governed metric itself and attaches the rules to the answer. |
|
|
346
|
+
| **Cube** | Mature headless-BI semantic layer you operate as a service | Cube is infrastructure: API gateway, caching, refresh workers, vendor-specific model format. Ariadne is a Python package with embedded DuckDB — no serving infrastructure — using open file formats (OSI YAML, Markdown). |
|
|
347
|
+
| **dbt MetricFlow** | Semantic layer inside the dbt ecosystem | Strong choice if you already run dbt; adopting it otherwise means adopting the whole dbt workflow. Ariadne stands alone and adds the agent-facing context layer and review gate. |
|
|
348
|
+
| **Wren MDL** | AI-oriented semantic modeling spec | Similar niche, but a vendor-specific spec with a weaker governance and join-safety story; Ariadne builds on the vendor-neutral OSI standard. |
|
|
349
|
+
| **Malloy** | Semantic modeling *language* from ex-Looker engineers | A language and toolchain, not a governed metric registry with business context; Ariadne's artifacts are plain YAML/Markdown with a human promotion gate. |
|
|
350
|
+
|
|
351
|
+
Ariadne is a good fit when AI agents need trustworthy, repeatable numbers from
|
|
352
|
+
heterogeneous data — and a human must stay in the loop on definitions. It is **not** a
|
|
353
|
+
BI dashboard, a transformation pipeline, or a high-concurrency metrics API; if you need
|
|
354
|
+
those, pair it with (or choose) the tools above.
|
|
355
|
+
|
|
356
|
+
## Technical details
|
|
357
|
+
|
|
358
|
+
The design decisions, specification, and research behind Ariadne live in the repo:
|
|
359
|
+
|
|
360
|
+
- Behavior spec: [project/specs/mvp-vertical-slice.md](project/specs/mvp-vertical-slice.md)
|
|
361
|
+
- Architecture decisions: [project/adr/](project/adr/)
|
|
362
|
+
- Domain vocabulary: [CONTEXT.md](CONTEXT.md) · Research: [project/research/](project/research/)
|
|
363
|
+
- Contributing: `python -m pytest` and `ruff check .` must stay green
|