Metis
Metis (μῆτις) — distributed cognitive layer over any LLM
Part of the alexar76 AI agent economy
Grab the star · watch it pulse and think · chat with Metis — open the live demo →
Multi-agent reasoning orchestrator — Understanding Council, DGPD depth gating, layered MoA, verifier, memory, search, economy metering, distributed cluster, MCP tools, and OpenAI-compatible API.
Quick start
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,distributed]"
ollama pull qwen3:8b
metis "Explain multi-agent systems" --model qwen3:8b --url http://localhost:11434/v1
Install
PyPI package name is aimarket-metis (the PyPI name metis is a different project). Import path and CLI stay metis, metis-serve, etc.
# PyPI
pip install aimarket-metis
pip install "aimarket-metis[dev,distributed]"
# GitHub release tag
pip install "aimarket-metis[distributed] @ git+https://github.com/alexar76/metis.git@v0.2.0"
# Clone / monorepo (editable)
git clone https://github.com/alexar76/metis.git && cd metis
pip install -e ".[dev,distributed]"
# Docker
docker compose up -d
Documentation index
| Resource | Link |
|---|---|
| Architecture | EN · RU · ES |
| API reference | EN · RU · ES |
| Deployment | EN · RU · ES |
| Security | EN · RU · ES |
| User guide | EN · RU · ES |
| Distributed | EN · RU · ES |
| Ecosystem | EN · RU · ES |
| Research | EN · RU · ES |
| Wiki | Home · Quick Start · FAQ |
| Landing page | Live demo · docs/landing/index.html · deploy guide |
| Changelog | CHANGELOG.md · RELEASE.md |
Ecosystem map
| Project | Role |
|---|---|
| Metis | Cognitive orchestration layer (this repo) |
| cognitive-runtime | OpenAI API wrapper with DGPD |
| ARGUS-3 | Demand-side reference agent + WARDEN MCP firewall |
| AIMarket Hub | Federated capability catalog and invoke API |
| aimarket-oracle-gateway | Verifiable oracle MCP services |
| aimarket-mcp | Shared MCP gateway — web fetch/search + Metis verify (Glama) |
| Ecosystem landing | Full AICOM map — Metis, MCP servers, oracles, ARGUS |
| HELIOS | Broadcast pipeline for ecosystem content |
| AICOM | AI-Factory — autonomous product pipeline |
CLI commands
| Command | Purpose |
|---|---|
metis |
Run a query through the cognitive stack |
metis-serve |
OpenAI-compatible API (/v1/chat/completions) |
metis-node |
Start a distributed worker node |
metis-coordinator |
Start the cluster coordinator |
metis-cluster |
Check cluster node health |
Architecture
flowchart LR
Q["Query"] --> M["Metis"]
M --> R["Router"]
R --> C["Council/MoA/Agent"]
C --> P["LLM Providers"]
C --> T["Tools + MCP"]
M --> E["Economy Meter"]
Jury verification (/v1/verify)
By default a /v1/verify verdict is written by one model and audited by one model — the
base model on fast, the MoA aggregator on council. That is the verdict the AIMarket
hub's Pay-on-Verified escrow moves money on,
so a seller only has to fool one lineage. A jury makes it a vote across vendors:
jury_default_for_verify: true # every /v1/verify goes to the jury; off → only route: "jury"
jury_min_vendors: 3 # and every seat must be a different vendor
jury_models:
- {model: deepseek-v4-pro, base_url: https://api.deepseek.com/v1, api_key_env: DEEPSEEK_API_KEY}
- {model: minimax/minimax-m3, base_url: https://openrouter.ai/api/v1, api_key_env: OPENROUTER_API_KEY}
- {model: z-ai/glm-5.3, base_url: https://openrouter.ai/api/v1, api_key_env: OPENROUTER_API_KEY}
Ready rosters for both courts are in deploy/prod.jury.example.yaml.
What the jury does, and what it promises:
- The caller's prompt goes to every juror unchanged, in parallel, at
jury_temperature(0.1). A juror slower thanjury_timeout_secondsabstains; it does not hold the jury. - A juror's vote counts only if it states
{"fulfils": bool, "score": 0–1}consistently at the caller's bar and — when the request carriesaudit_id— echoes that id. A juror that parroted a verdict planted in the audited text has not voted. - A side wins with a strict majority of the whole roster; abstentions count against
agreement.
verify_score= agreement × median confidence of the winning side (confidence in "fulfils" = score, in "does not fulfil" = 1 − score), so a confident unanimous conviction is a trusted audit. answeris one winning juror's verdict object on its own, so a consumer's parser reads it unchanged. A split carries no verdict object (indeterminate); every seat failing isstatus: "error"(retry), never a verdict.- The envelope adds
jury([{model, vendor, fulfils, score, latency_ms, abstained?}]),jury_outcome(pass|fail|split|unavailable),jury_agreementandinput_flags.injection_suspected. The trace resolves at/v1/traces/{trace_id}. - Injection-looking text is flagged, not blocked on this path: the audited text is written by the parties with money on the verdict, and a hard block would hand either of them an indeterminate outcome on demand.
Know the arithmetic before sizing a roster: at the hub's 0.7 bar a 3-seat jury settles only when unanimous (2/3 × anything < 0.7); five seats tolerate one confident dissent; an even roster only adds splits. The jurors are independent labs, not independent infrastructure — seats behind one gateway share its outages and its account.
The same change stops the capability gate from seating one model as both the writer and
the auditor of a verdict: with judge_distinct_vendor: true (default) the judge avoids the
vendors of the base model and the MoA aggregator, an explicit modules.judge that clears
min_aggregator_capability is honoured instead of silently overridden, and
min_unique_council_vendors extends the diversity check from (model, endpoint) pairs to
vendors, for the MoA seats as well as the council. metis validate warns when the judge
still shares a vendor with a writer.
Running a second instance as the appeal court
The hub's appeal path (AIMARKET_APPEAL_WINDOW_S) re-judges a disputed verdict on a
second, independent Metis. Independence is operational, so it has to be set up that way:
- Another host. Not the first instance's machine (shared failure, shared operator access) and not a host holding a hot wallet. Same image, its own container.
- A disjoint jury. The
metis_2roster indeploy/prod.jury.example.yamlshares no vendor withmetis_1(a test enforces it). Use a second OpenRouter key with its own spend cap — vendor-disjoint seats behind one key still share that key's quota. - Its own identity. Its own
METIS_API_KEY(setting it makes/v1/verifyrequire the Bearer), handed to the hub asAIMARKET_APPEAL_METIS_KEY; its ownAIMARKET_APPEAL_METIS_URL; and a distinctAIMARKET_APPEAL_VERIFIER_ID(e.g.metis.appeal@v1) so every envelope and receipt names which court decided. - Nothing from the first instance. It gets the stored intent and delivery, a fresh audit id and the appellant's fenced statement — never the first verdict, its score, its reasons or its trace. Do not point it at the first instance's trace store or knowledge store.
docker run -d --name metis-appeal --restart unless-stopped -p 127.0.0.1:8081:8080 \
-e METIS_API_KEY=<appeal-court key> -e OPENROUTER_API_KEY=<second, capped key> \
-v /opt/metis-appeal/prod.yaml:/app/config/prod.yaml:ro -v /opt/metis-appeal/data:/app/data \
metis:latest metis-serve --host 0.0.0.0 --port 8080 --config /app/config/prod.yaml
Production
export METIS_API_KEY=sk-...
metis-serve --config config.production.yaml --production --port 8080
Legacy env vars SUPERBRAIN_* and COGNITIVE_* are still read for one release cycle.
Docker
cp config/docker.env.example .env
docker compose up -d --build
Tests
pytest --cov=metis --cov-report=term-missing -v
Research citations
Design decisions are grounded in published work — see docs/en/RESEARCH.md for Yang et al. 2026 (heterogeneous agents), Wang et al. ICLR 2025 (layered MoA), and related citations with honest caveats.
MIT License
Metadata
Release files for aimarket-metis 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aimarket_metis-0.2.1.tar.gz | 189.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aimarket_metis-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 356.0 kB
Release files / aimarket_metis-0.2.1.tar.gz
| Download URL | aimarket_metis-0.2.1.tar.gz |
|---|---|
| Size | 189.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1fe43bc029ef3fce5822c0ba4b8b44d7c1583b5a025d43b2c5556dd65d17e085
|
|
BLAKE2b-256 checksum How to use checksums |
277201c8623388366e717fc949a180e2db2a907e734794a6b5377189c2612f1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / aimarket_metis-0.2.1-py3-none-any.whl
| Download URL | aimarket_metis-0.2.1-py3-none-any.whl |
|---|---|
| Size | 166.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
851688bfd1e32d1a59fa5f3ecc9674e411733de019320f9f83a293219a0421b9
|
|
BLAKE2b-256 checksum How to use checksums |
3b8fa17f2f9543d9aa9621da156b63b6aba109d949ce0e7a5285ff45c87d5005
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|