Metis is an open-source, Ossie-first, engine-neutral semantic layer runtime engine. It sits between AI agents or applications and analytical databases, turning structured requests for metrics and dimensions into deterministic SQL and, when execution is configured, analytical results.
Agents reason. Metis resolves semantics. Engines execute.
For example, an agent asks for total revenue by region. Metis resolves the metric definition and compatible dimension from an Ossie model, plans the required joins and aggregations, and generates SQL for the selected database. The same semantic definitions serve the CLI, MCP, REST, and embedded Go APIs.
- Ossie-first: Apache Ossie models define metrics, dimensions, relationships, and ontology concepts that Metis discovers, validates, and resolves.
- Engine-neutral: semantic resolution and planning are shared across database targets. Renderers generate dialect-specific SQL; execution backends manage database access. Built-in targets are Doris, ClickHouse, and DuckDB.
- Deterministic: structured semantic requests go through validation, resolution, planning, and compilation. Metric definitions and relationship rules come from the model.
- Ready for analytical workflows: discover semantic assets, compile SQL, query metrics, compare periods, and analyze metric-change attribution.
Agent or application
|
| metrics, dimensions, filters, time ranges
v
Metis <----- Apache Ossie models
|
+--- discover / validate / resolve / plan
|
+--- compile SQL ---> database client of your choice
|
+--- execute through a configured backend ---> analytical results
Compilation works without a database connection. Execution adds connection management, cancellation, timeouts, and output limits. MCP and REST expose the same runtime services that Go applications can embed directly.
| Tool or interface | Use it to |
|---|---|
metis |
Validate and compile semantic models offline, manage local projects, or run the standalone semantic runtime. |
| MCP | Give an agent tools for semantic discovery, SQL compilation, and bounded analytics over stdio or HTTP. |
| REST | Integrate semantic discovery, compilation, explanation, and analytics into applications. |
s2sbench |
Run repeatable agent analytics experiments and inspect correctness, readiness, and execution evidence. |
| Go packages | Compose a runtime with your own configuration, policies, and database integrations. |
Requires Go 1.25 or later. The default binary does not require CGO.
git clone https://github.com/meaningforge/metis.git
cd metis
go build -o bin/metis ./cmd/metis
bin/metis validate --project demo examples/demo/models/sales.ossie.yamlThe example runtime configuration is examples/demo/metis.yaml. It registers a local project manifest that points to Ossie model files. Update those files and your DataSource configuration locally, then restart the runtime to apply changes.
A local MCP client can launch Metis as a stdio subprocess. Replace the absolute paths below with the location of your checkout:
{
"mcpServers": {
"metis": {
"command": "/absolute/path/to/metis/bin/metis",
"args": ["mcp", "--config", "/absolute/path/to/metis/examples/demo/metis.yaml"]
}
}
}Start with a request such as: “In the demo project, compile total revenue by
region.” The agent can discover the model, select total_revenue and region,
and call compile_sql.
| MCP tools | Purpose |
|---|---|
list_projects, list_models, get_model |
Find and inspect available projects and models. |
list_metrics, get_metric |
Discover metrics and inspect their definitions. |
get_dimensions, get_dimension, get_relationships |
Find compatible dimensions, time grains, and relationships. |
search_ontology_concepts, resolve_ontology_concept |
Map business concepts to semantic assets. |
compile_sql |
Validate a semantic request and return SQL with an output schema. |
query_metrics, get_dimension_values |
Retrieve bounded metric results and live dimension values. |
compare_metrics |
Compare metrics across two periods, including values and changes. |
attribute_metric |
Decompose metric changes using supported additive or ratio metrics. |
Tools that retrieve data require a configured execution backend. Metric-change attribution provides a numerical decomposition; interpreting its business causes remains the caller's task.
Configure a shared bearer token and start the server:
export METIS_API_KEY='replace-with-your-own-secret'
bin/metis serve --config examples/demo/metis.yaml --addr 127.0.0.1:8080Connect to http://127.0.0.1:8080/mcp with
Authorization: Bearer <your-token>. The REST endpoints under /v1/** use the
same authentication and semantic services. /healthz and /readyz are public
health endpoints. Local stdio runs under the subprocess owner's permissions.
For example, compile total revenue grouped by region:
curl -fsS http://127.0.0.1:8080/v1/compile-sql \
-H "Authorization: Bearer $METIS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"dialect": "DUCKDB",
"query": {
"project": "demo",
"model": "sales",
"metrics": [{"name": "total_revenue"}],
"dimensions": [{"name": "region"}]
}
}'The response includes sql_render_result and output_schema. This endpoint
compiles the query without executing it. /v1/explain accepts the same request
shape and returns SQLExplainResult: semantic planning evidence, the same
sql_render_result and output_schema as Compile, and any compilation warnings.
Explain generates SQL without executing it.
The metis model, metis project, and metis query commands work offline. Use
them to validate and inspect models, compare projects, or generate SQL without
starting a server, connecting to a database, or resolving secrets.
go build -o bin/metis ./cmd/metis
bin/metis query compile \
--model examples/demo/models/sales.ossie.yaml \
--dialect DUCKDB --metric total_revenue --dimension regionUse --dialect DORIS, CLICKHOUSE, or DUCKDB to select a target. Add repeatable
--metric, --dimension, and --filter flags, or pass a structured request with
--request-json.
metis query compile outputs JSON containing dialect, sql, and optional parameters.
SQL retains its placeholders; pass parameter values in order to your database
driver. Values are never interpolated into SQL text.
| Command | Purpose |
|---|---|
metis query compile |
Compile a semantic request into SQL and parameters as JSON. |
metis model validate, metis model inspect |
Validate an Ossie document or inspect its metadata. |
metis project validate, metis project inspect |
Load and check a complete semantic project. |
metis project diff |
Compare two local semantic project inputs. |
metis project test --mode compile |
Check project-owned compile expectations in CI without connecting to a database. |
metis project test --mode runtime |
Assert metric results against an externally prepared database fixture; emit JSON and optional JUnit. |
metis model format |
Format a model file. |
bin/metis project validate --project demo --config examples/demo/project.yaml
bin/metis model inspect --model examples/demo/models/sales.ossie.yamlRun the demo compile suite against a complete project. The command writes a private JSON report and exits nonzero on a failed or incomplete case:
bin/metis project test --mode compile --project demo \
--config examples/demo/project.yaml --suite examples/demo/checks/compile.yaml \
--dialect DORIS --output ./compile-report.jsonSee the regression-suite contract
for assertion syntax, limits, and exit codes, and the
runtime fixture example for Doris/ClickHouse setup.
Both modes support --junit-output; runtime currently supports query_metrics.
These commands test your project's business definitions, not Metis engine conformance or custom authorization. Fixture setup and CI orchestration stay external; the CLI is not a general-purpose testing framework.
To enable execution, reference a named DataSource from your project registration and define it in a local DataSource registry. The DataSource type selects the database backend and SQL renderer.
The default build includes Doris and ClickHouse execution backends. To enable
DuckDB execution, build with CGO and the duckdb tag:
CGO_ENABLED=1 go build -tags duckdb -o bin/metis ./cmd/metisDuckDB SQL compilation works with the default build. Compile-only deployments require no database credentials. The execution runtime manages connections, secrets, cancellation, timeouts, and output limits.
S2SBench evaluates how an agent completes analytical tasks through semantic interfaces. It runs frozen scenario suites, records attempts and query evidence, and produces machine-readable reports. Use it to investigate whether a change to Metis helps agents discover the right data and produce correct analytical results.
A run selects one interface: metis-mcp for Metis tools, or okf for
catalog-derived semantic files. Running the same suite with the same agent and
model through each interface enables a paired comparison.
Build with embedded DuckDB support and inspect the available commands:
make s2sbench-build
bin/s2sbench --help
bin/s2sbench run --helpAgent runs require an installed, authenticated agent CLI and model access. The
runner supports Codex, Claude Code, Pi, and a generic driver. The DuckDB build
also requires CGO and a C toolchain. Start with the smoke suite and set the
model identifiers to those used by your agent:
bin/s2sbench run \
--suite smoke \
--arm metis-mcp \
--agent codex \
--model '<model-id>' \
--provider '<provider>' \
--model-version '<model-version>' \
--output ./s2sbench-results/smoke-metisCompleted runs contain manifest.json, collection.json, attempts.jsonl, and
report.json. Repeat an interrupted command with --resume to keep completed
work. Use --detach for a background run and s2sbench stop <output-directory>
to stop it.
For a paired experiment, repeat the run with --arm okf and a separate output
directory, then compare both collections:
bin/s2sbench analyze \
--input ./s2sbench-results/smoke-okf \
--input ./s2sbench-results/smoke-metis \
--output ./s2sbench-results/comparison.jsonAdditional commands cover workload generation (gen), catalog-derived file
creation (okfgen), reports (report), and attribution and comparison
experiments. Use bin/s2sbench <command> --help for their inputs and options.
Agent benchmark runs are separate from the standard correctness tests.
- Copy examples/demo into your project directory.
- Add your Ossie model files under
models/. - Update
project.yamlto select those files and register your project inmetis.yaml. - Validate the project with
metis project validate, then startmetis serveormetis mcpwith your runtime configuration.
Model paths are resolved relative to the project manifest. A runtime can register multiple projects; see examples/multi-project/metis.yaml.
Import packages from github.com/meaningforge/metis and pin a version or
commit in your application's go.mod.
| Task | Entry point |
|---|---|
| Load a runtime from local configuration | bootstrap.LoadRuntime |
| Build a runtime from configuration and model bytes | bootstrap.NewRuntime, RuntimeInput, ProjectInput |
| Serve REST and MCP with an identity verifier | hosting.NewHTTPHandler |
| Configure project access and data constraints | bootstrap.WithProjectAuthorizer, WithAssetVisibilityPolicy, WithDataAccessPolicy |
| Supply database backends and secret resolution | bootstrap.WithBackendRegistry, WithSecretResolver |
| Load model documents from memory | source.LoadProjectDocuments |
| Replace an active semantic snapshot | runtime.Manager.Replace |
| Close database pools | bootstrap.Runtime.Close |
Runtime integration packages live under app/bootstrap, app/hosting,
app/auth, and app/service. Database extension interfaces live under
renderer and execution. Integrations use ordinary Go interfaces and
compile-time composition. Passing an explicit nil asset visibility policy
rejects runtime initialization. A request pinned again by the same runtime
keeps its snapshot; pinning it through another runtime creates a new scope
for that runtime.
The embedding example constructs a runtime from memory, applies access policies, and replaces a semantic snapshot. Before v1, pin exact versions and run compatibility tests when upgrading.
The documentation and license checks require Python 3 in addition to Go.
go mod tidy
make check
make test-e2e
make test-duckdb-backendmake check runs documentation and source contract checks, go vet, unit tests,
sample models, semantic conformance tests, and the quickstart verification.
The Apache Ossie fixture check downloads a pinned upstream commit. For an offline
run, set OSSIE_GIT_DIR to a local Apache Ossie Git object directory containing
that commit. Database integration tests require explicitly configured services
and run separately.
Apache License 2.0. Third-party attribution and license texts are
available in NOTICE, THIRD_PARTY_NOTICES, and
licenses/. Run make licenses after updating dependencies;
make licenses-check verifies the bundle included in release archives and images.
See the documentation guide for architecture, public contracts, model authoring, execution, and S2SBench. Core RFCs record proposals and design rationale, with explicit lifecycle status.