Skip to main content

SchemaRouter

Schema-aware planning and execution for LLM tool ecosystems.

English · 한국어 · Docs · Latest release

CI Docs PyPI MIT

SchemaRouter sits between an agent/RAG application and its data-capable tools. It parses registered OpenAPI, MCP, OPTIMADE, Python, or plugin capabilities into a typed catalog, retrieves the smallest declared executable data surface that can satisfy a request, and validates the resulting plan again at runtime before anything executes.

Query
  -> Tool
  -> Endpoint
  -> Parameters
  -> Response fields
  -> Policy / evidence
  -> Schema validation
  -> Execute

It is not another general agent framework. LangChain, LangGraph, LlamaIndex, or your own orchestrator can stay above it; OpenAPI, MCP, OPTIMADE, Python callables, and adapter plugins stay below it.

Mental model: RAG for executable capabilities

A conventional RAG stack parses documents into chunks + metadata, indexes them, and retrieves the smallest relevant context. SchemaRouter applies the same separation to APIs and tools:

documents -> parser -> chunks/metadata -> index -> retriever -> RAG
APIs/tools -> adapter -> endpoint/field contracts -> registry/index -> SchemaRouter -> RAG/agent

The retrieved unit is executable: endpoint operation, inputs, output fields, datatype/unit contracts, policy/evidence and availability. The registry is a logical capability graph; it does not require a graph database. Registered schema remains authority even when embeddings or optional decision backends help search it.

Capability catalog and RAG analogy

Field-first, route-second

SchemaRouter first asks which declared data fields are actually needed to answer the request, then chooses a provider/access path that can supply those fields. When an endpoint explicitly supports server-side projection, only the planned fields are requested upstream; after raw schema validation, final local projection keeps the downstream LLM context narrow even if a provider sends extra data.

Availability may change the route, but it does not broaden the data need. Precompiled read-only fallbacks can move from one access mode to another—and, when explicitly enabled, to another provider—without turning runtime into an autonomous agent loop.

Agent / graph / application orchestrator
                 |
           SchemaRouter
     typed planning + validation
                 |
        capability sources
 OpenAPI / MCP / OPTIMADE / Python

Optional decision backends (Laya / Ollama / Jev / System One-compatible providers) plug into
SchemaRouter's bounded selection step. Jev-compatible models can be swapped by configuration through
`SystemOneDecisionBackend`; other trusted bounded runtimes can enter through
`CallableDecisionBackend`. They do not become agents, do not run tool loops, and do not receive
execution authority.

Current stable release: 0.10.0 · pip install schemarouter · pre-1.0

Why SchemaRouter

Tool selection alone is not enough once an agent has many capabilities. SchemaRouter makes the execution boundary explicit:

  • choose a declared tool and endpoint;
  • accept only declared parameters and output fields;
  • validate inputs and raw outputs with JSON Schema;
  • reject stale schema fingerprints and stale invoker bindings;
  • keep mutation/destructive authority local and fail closed;
  • separate credentials from model-visible arguments;
  • bound retries, elapsed time, remote calls, and response size;
  • surface OpenAPI compatibility gaps instead of silently guessing.

Real-world scenario

SchemaRouter real-world scenario: field-first, route-second

A single request can require fields from different providers. For example, a materials question may need a numeric band_gap from Materials Project and a text abstract from arXiv.

SchemaRouter resolves the semantic field need first, then spends the bounded max_calls budget on complementary provider/access paths that can satisfy those fields. A route can change because of health, policy, or availability; the required data contract does not.

band_gap  -> Materials Project / OpenAPI
             ↳ OPTIMADE fallback
abstract  -> arXiv API

The final execution plan remains schema-validated, policy-bounded, and fail-closed. When one route already covers every matched field, SchemaRouter can stop before reaching the max_calls bound.

Quickstart

from pydantic import BaseModel
from schemarouter import PlanRequest, SchemaRouter, schema_tool


class Weather(BaseModel):
    city: str
    temperature: float


@schema_tool(read_only=True)
def current_weather(city: str) -> Weather:
    return Weather(city=city, temperature=20.5)


router = SchemaRouter()
router.add_callable(current_weather)

result = router.invoke(
    PlanRequest(query="city temperature", arguments={"city": "Seoul"})
)

print(result[0].data)

Connect capabilities

Source Use when Entry point
Python capability is local and typed router.add_callable(...)
OpenAPI HTTP API publishes a machine-readable contract SchemaRouter.from_url(..., kind="openapi")
MCP tools are exposed through MCP SchemaRouter.from_url(..., kind="mcp")
OPTIMADE materials data is exposed through OPTIMADE SchemaRouter.from_url(..., kind="optimade")
Human-readable docs no machine-readable schema exists inspect → proposal → explicit approval

Framework bridges are available for LangChain, LangGraph, and LlamaIndex. OpenTelemetry provides optional telemetry export. Jev / TypeSafe, System One-compatible providers, Laya, and Ollama are optional decision backends, not agent frameworks. Jev-wire-compatible models can reuse SystemOneDecisionBackend by changing provider/model configuration rather than adding a planner class. Existing GPT, Gemini, Claude, or other hosted/local decision clients can also be injected through the provider-neutral ModelQueryAnalyzer or CallableDecisionBackend contracts. None of these paths bypass SchemaRouter's policy, schema validation, or execution boundary.

Decision models are replaceable without moving execution authority into the model:

  • Jev/System-One-compatible servers use SystemOneDecisionBackend and can swap base_url/model/provider_name by configuration;
  • one-off local or hosted experiments can use CallableDecisionBackend;
  • reusable third-party runtimes can publish a schemarouter.decision_backends entry-point plugin.

SchemaRouter still validates the returned finite option ID locally. See the decision backend plugin guide and decision-model ecosystem intake.

What 0.6 adds

0.6 adds optional local/model-assisted decision backends, operational inspection/dashboard surfaces, and a broader fail-closed OpenAPI subset:

  • local Laya decisions with CPU/CUDA/MPS device controls and benchmark metadata;
  • provider-neutral reuse of existing GPT, Gemini, Claude, or other hosted clients;
  • live/persistent inspection plus a self-contained read-only HTML dashboard;
  • response oneOf/anyOf field discovery and static same-origin $id/$anchor resolution;
  • typed JSON root request bodies, OpenAPI 3.0 nullable normalization, and default parameter-style serialization.

See the 0.6.0 release notes for details.

What 0.7 adds

Version 0.7.0 strengthens the same narrow execution boundary rather than adding agent orchestration:

  • conservative schema-drift explanations while exact fingerprints still fail closed;
  • operation-scoped local allow/deny/approval policy rules;
  • structured, auditable plan explanations based on SchemaRouter-visible signals;
  • explicit flat parallel fan-out only when every planned call is currently trusted read-only;
  • provider/access identity, bounded read-only fallback, server-side field projection contracts, and recoverable access-path health state;
  • typed scientific result contracts with explicit JSON datatypes, optional unit metadata, canonical affine unit normalization, and exact measurement/material qualifiers such as temperature, phase, orientation, or method;
  • qualifier-aware routing that can distinguish otherwise equivalent scientific fields when the condition is explicitly present in the query, without unit conversion or scientific inference;
  • trusted parameter aliases so the same logical argument can bind safely to provider-specific local parameter names without model-authored remapping.

Workflow/DAG semantics, memory, prompt systems, and autonomous tool loops remain out of scope.

See the 0.7.0 release notes for details.

What 0.10 consolidates

Version 0.10.0 is a consolidation release rather than a claim that open-set routing is solved.

  • clarifies SchemaRouter as a typed capability retrieval/execution layer for agent and RAG systems;
  • keeps field-first, route-second planning as the stable product architecture;
  • treats JSON datatype/shape, semantic IDs, optional units, explicit unit normalization, and exact scientific qualifiers as part of the registered data contract;
  • keeps OpenAPI/MCP/OPTIMADE/Python registration provider-neutral rather than benchmark-specific;
  • keeps learned decision backends bounded and optional;
  • publishes the current routing benchmark outcome honestly: the strongest DEV candidate passed the standing target, but its frozen zero-overlap fresh confirmation failed, so no production-target candidate was promoted.

The successor registry-compiled capability verifier remains a research prototype and is not the 0.10.0 default.

0.10.0 release notes · Routing research status

What 0.9 adds

Version 0.9.0 adds a provider-neutral bounded pairwise scoring backend for applications that want cross-encoder or reranker-style decisions without moving execution authority into the model.

  • PairwiseDecisionBackend scores only the locally authorized (query, option) pairs;
  • opaque option IDs remain local and model/scorer output cannot invent a route;
  • malformed, non-finite, out-of-range, or wrong-length score batches fail closed;
  • sync and async scorers are supported without adding Torch, Transformers, or a specific model to SchemaRouter core;
  • benchmark metadata now records pairwise scoring configuration for reproducibility.

The frozen BGE pairwise candidate was evaluated exactly once on the fresh 600-case v11 holdout. It reached 51.667% overall accuracy, 25.781% supported-operation routed accuracy, 97.396% near-domain unsupported-operation rejection, and 100% ordinary OOD rejection. A post-consumption MiniLM 0.40 diagnostic on the same corpus reached 54.833% overall, 40.625% supported, and 77.604% near-domain rejection. BGE improved the equal-weight supported/rejection balanced score, but materially reduced supported recall and more than doubled CPU latency, so it is not the library default.

v11 is consumed evidence and is not eligible for further threshold/model selection.

See the 0.9.0 release notes and the decision routing benchmark guide.

Inspect what SchemaRouter built

Persisted registries and run traces can be inspected without executing tools:

schemarouter inspect registry --db ./registry.sqlite3
schemarouter inspect tool materials --db ./registry.sqlite3
schemarouter inspect diff materials \
  --old-db ./registry-before.sqlite3 \
  --new-db ./registry-current.sqlite3
schemarouter inspect traces --db ./traces.sqlite3
schemarouter inspect trace <RUN_ID> --db ./traces.sqlite3
schemarouter dashboard \
  --registry ./registry.sqlite3 \
  --traces ./traces.sqlite3 \
  --output ./artifacts/schemarouter-dashboard.html

Add --json to inspection commands for automation. The dashboard is a self-contained read-only HTML export built from the same inspection contracts. The registry view exposes tool/endpoint topology, method/path, mutation classification, parameter/output-field counts, and schema fingerprints; trace views expose persisted run/event history.

Operational inspection guide

Documentation

Start with the manual rather than this README:

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

ruff check .
pytest -q -m "not mcp_integration"

The protected CI surface also covers Python 3.10–3.14, Windows, minimum dependencies, package artifacts, Pyright, coverage, documentation, and optional integration suites.

Scope

SchemaRouter intentionally does not implement another chat abstraction, model-provider layer, memory system, checkpoint store, or graph runtime.

Natural-language request → typed tool execution plan → validated execution.

Research and license

SchemaRouter originated from SchemaRouter: Field-Aware Tool Routing for Efficient Heterogeneous Agentic RAG.

MIT © 2026 Yong-eun Cho

Metadata

Release files for schemarouter 0.10.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for schemarouter 0.10.0
File Size Uploaded
schemarouter-0.10.0.tar.gz 744.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for schemarouter 0.10.0
File Interpreter ABI Platform
schemarouter-0.10.0-py3-none-any.whl Python 3 none any Details

Total release size: 897.9 kB

Release files / schemarouter-0.10.0.tar.gz

Download URL schemarouter-0.10.0.tar.gz
Size 744.9 kB
Tags Source
SHA-256 checksum
How to use checksums
75db1843c3c9d7df6c4e8faf8d2ae763aa17a670a5be22311268056b1ceedefe
BLAKE2b-256 checksum
How to use checksums
c327bb3a47ab8774a4ca8f47812d4e48719a2717307f090b0e289cdc45ba163b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / schemarouter-0.10.0-py3-none-any.whl

Download URL schemarouter-0.10.0-py3-none-any.whl
Size 153.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ddeb521274e88bfef03a592006eefba2bf1528d81e68e40208e35db38055963c
BLAKE2b-256 checksum
How to use checksums
2f2cf2a29a2d411f940670b30b24cc454aa1960707d97c2a1c7d52613d57cef4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page