name: meridian-integration description: How to call Meridian (the governance router) correctly from a new, standalone client — auth, the onboarding sequence, and what's still house/console-only.
Integrating with Meridian
Meridian is a policy-governed inference router: you ask it "which model should
agent_name use right now", and it answers using project/agent policy
(quality, cost, risk, allowed/denied hubs, data classification) rather than
you hardcoding a model name. It knows nothing about MTA specifically — any
client that holds a valid key can use it standalone.
Full generated route-by-route reference: docs/api/api-reference.md in this
repo (regenerate with python3 scripts/gen_api_docs.py after any route
change — it reads the live FastAPI app, so it can't go stale the way a
hand-written doc can).
Install
pip install meridian-client # published — the normal path, or
pip install -e meridian-client/ # editable, from this repo (contributing to the SDK itself)
Prefer a terminal to Python? pip install meridian-governance-cli wraps
this same SDK as subcommands (meridian signup, meridian resolve my_agent, meridian keys list, ...) — installs as the meridian command;
see meridian-cli/README.md (not to be confused with the unrelated
meridian-cli package also on PyPI). No chat loop, no personas; it's a
management CLI over the API, not a clone of mta-cli's consumer-companion
command set.
Auth — read this before anything else
Meridian accepts a key two ways; it doesn't matter which:
Authorization: Bearer mdn_xxxxxxxx
x-api-key: mdn_xxxxxxxx
With no key at all: on-prem only, and only if that instance was started
without MERIDIAN_AUTH_REQUIRED=true. The request resolves to the instance's
single default org. Every cloud deployment (dev-meridian.mytrustworthy.ai
and any other MERIDIAN_DEPLOYMENT=cloud instance) requires a key — no key
gets a flat 401, not a default org.
Getting your first key
from meridian import Meridian
m = Meridian.signup("https://dev-meridian.mytrustworthy.ai",
org_name="my-project", email="me@example.com", password="...")
# m is now an authenticated client. m.org_id and m.signup_response are set.
One call: creates a new org (always free tier — self-serve can't grant
itself more than that), its first user, and its first key, and returns a
Meridian already authenticated with it. This is the only unauthenticated
write on the whole API — everywhere else, minting a key or registering a
user needs an org_id that a cold caller doesn't have yet, which is exactly
the chicken-and-egg problem this one call exists to break.
If you already have a key (an account team provisioned you directly, or you're adding a second client to an org that already signed up):
m = Meridian("https://dev-meridian.mytrustworthy.ai", api_key="mdn_...")
Three tiers, one engine
There's one governance engine underneath all of this — the tiers below are just how much of it you choose to use, not three different products:
- Individual / fast start: pin a model and go.
pinned_modelskips scoring entirely (resolver.py's "Step 3: Pinned model — skip scoring") — deterministic, zero policy to configure. - Business / small team: the quality/cost/risk sliders. Same
create_agentcall, just set overrides instead of (or in addition to) a pin; invite teammates into the same org viaPOST /api/v1/auth/registeronce you're authenticated. - Enterprise / custom governance: change-requests and approval
(
create_change_request→approve_change_request), hub allow/denylists, data classification enforcement (piihard-forces risk to 1, on-prem only). All already built; nothing here is Enterprise-only code, just the parts a fast-start integration doesn't need to touch.
The onboarding sequence
A tenant key can do all of this itself — no console needed past signup:
# 1. A project: your governance boundary. One org can have many.
project = m.create_project(
org_id=m.org_id,
name="my-standalone-agent",
quality=7, cost=5, risk=5, # 0-10 sliders, project-level defaults
classification="general", # "pii" forces risk=1 regardless of the slider
)
# 2. An agent inside it. This is the identity you resolve against — not a
# user, not an API key, an AGENT. One project can have many, each with its
# own overrides.
agent = m.create_agent(
project.id, "my_agent",
quality_override=9, # omit to inherit the project default
allowed_hubs=["anthropic-direct", "bedrock"], # omit for no hub restriction
)
# 3. Resolve. Call this every time you're about to make an inference call —
# it's cheap, and policy can change between calls.
decision = m.resolve("my_agent", project_id=project.id)
print(decision.model, decision.hub) # e.g. "claude-opus-5" "anthropic-direct"
# 4. After the real inference call, report usage so cost tracking means
# something.
m.audit(decision.routing_log_id, input_tokens=512, output_tokens=128,
latency_ms=840)
That's the whole golden path. m.explain(decision.routing_log_id) gets you
the full candidate breakdown (every model considered, why each one was
eliminated or scored where it scored) if you need to show your work.
Without the SDK (raw HTTP)
curl -X POST https://dev-meridian.mytrustworthy.ai/api/v1/resolve \
-H "Authorization: Bearer mdn_..." -H "Content-Type: application/json" \
-d '{"agent_name": "my_agent", "project_id": 123}'
Every route in docs/api/api-reference.md works the same way — method, path,
JSON body of the fields listed, same two auth headers.
What a tenant key cannot do (yet)
docs/api/api-reference.md marks every route tenant key: yes/no. The
"no" routes answer 403 "This route is not yet tenant-scoped; refused for tenant keys" regardless of whether your key is valid — it's a blanket
refusal by path, not a permission check. As of this writing that's mainly:
hub/model/deployment registration and edits, org creation and edits, and most
cost/governance console views. Those need a house key or the console. Project
and agent create/update/delete, resolve, audit, explain, simulate, and
change-requests are all tenant-reachable.
Gotchas
PUT /api/v1/projects/{id}/lifecycleis a stub. It validates the request and echoes the current row back — it does not change anything. Don't build on it (meridian#7's predecessor finding).- The SDK's response objects have an
.extradict. Every typed field the SDK knows about is a real attribute (agent.allowed_hubs); anything the server returns that this SDK version doesn't model yet lands inagent.extrainstead of silently vanishing. If a field you expect isNone, check.extrabefore assuming the server didn't send it. resolve_failoveronly writes an audit record if you passagent_name. Without it you get a plain hub-allowlist fallback with no governance and no audit trail — fine for "just get me anything that works", wrong for anything that needs to explain itself later.- Tool-access governance does not exist yet. Meridian governs which
model an agent may use. It does not yet govern which tools an agent may
call — there's no route for it, and the schema slots for it
(
agent.agent_tools,agent.skill_ids) are unpopulated. If your new agent needs Meridian to gate tool access rather than just model choice, that's a real gap, not a documentation gap — seeobsidian-vault-kb/relays/meridian/2026-10-12-should-meridian-govern-tools-and-what-that-costs-in-apis.mdfor the live design discussion. - Forgot a built-in-auth password?
POST /auth/forgot-password/POST /auth/reset-password(meridian#10), also reachable from the console's "Forgot password?" link. RequiresRESEND_API_KEYto actually be configured on the instance — without it the request fails loudly rather than handing the token back in the response. That's deliberate: an earlier version of this capability did exactly that and was removed on 2026-09-12 because it let anyone who knew an email address take over that account. There is no magic-link login — only password reset; you still need to know a password to sign in, the email only proves you own the inbox.
Metadata
Release files for meridian-client 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| meridian_client-0.1.0.tar.gz | 16.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| meridian_client-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.4 kB
Release files / meridian_client-0.1.0.tar.gz
| Download URL | meridian_client-0.1.0.tar.gz |
|---|---|
| Size | 16.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
be690a0bef4114233b9f578b21d3fa77814452f4caeb681c4b487f7de194273a
|
|
BLAKE2b-256 checksum How to use checksums |
2128860361191a0d50c4c0da3b4d16d488be74b2efa31d86dfeebc2d5d0063b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / meridian_client-0.1.0-py3-none-any.whl
| Download URL | meridian_client-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f44eaccf28ceee94b1dca48e20d275ad719cf092e52b71f1baf035e5a1d8a52b
|
|
BLAKE2b-256 checksum How to use checksums |
c016b267b716e068215eb99dac758fb468b3790a7d54f3d89e642d1a994c51f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for meridian-client 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.