Schema-aware planning and execution for LLM tool ecosystems.
English · 한국어 · Docs · Latest release
SchemaRouter sits between an agent and its tools. It turns a natural-language request plus a registered capability catalog into a small, typed execution plan, then validates that 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.
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) plug into SchemaRouter's bounded selection step.
They do not become agents, do not run tool loops, and do not receive execution authority.
Current stable release: 0.7.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.
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, Laya, and Ollama are optional decision
backends, not agent frameworks. Existing GPT, Gemini, Claude, or other hosted model 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.
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/anyOffield discovery and static same-origin$id/$anchorresolution; - 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.
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.
Documentation
Start with the manual rather than this README:
- Install and quickstart
- Understand the execution model
- OpenAPI guide
- Runtime policy and retry
- Framework integrations
- API reference
- Architecture and maturity
- Security model
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
Release files for schemarouter 0.7.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 | |
|---|---|---|---|
| schemarouter-0.7.0.tar.gz | 362.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| schemarouter-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 498.1 kB
Release files / schemarouter-0.7.0.tar.gz
| Download URL | schemarouter-0.7.0.tar.gz |
|---|---|
| Size | 362.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f43f39ca22098a76006f68d4c0fdd3c376a055683f48350d990fb855c1ad34de
|
|
BLAKE2b-256 checksum How to use checksums |
8e0bc45ccf5a2420c2187fb9b638011a4b6fc88e3daadc151c6f710dcc0a6878
|
| 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 25, 2026.
Transparency logRelease files / schemarouter-0.7.0-py3-none-any.whl
| Download URL | schemarouter-0.7.0-py3-none-any.whl |
|---|---|
| Size | 135.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
379769605ff28454a2e118cdf605777d40fc0309380cf38c337d5c5b67f26e53
|
|
BLAKE2b-256 checksum How to use checksums |
f4c3fbb1efe4e57041e776099c67421046aee4144341ba978d4d15867eef36fc
|
| 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 25, 2026.
Transparency log