This release is a pre-release and may not be stable for production use.
SchemaRouter
Schema-aware planning and execution for LLM tool ecosystems.
SchemaRouter compiles a natural-language request plus a registered capability catalog into a small, typed, auditable execution plan.
It goes beyond Query -> Tool routing:
Query
-> Tool
-> Endpoint
-> Parameters
-> Response fields
-> Evidence / policy
-> Schema validation
-> Execute
SchemaRouter is intentionally narrower than LangChain or LangGraph. It is designed to sit at the tool-schema boundary between an agent and structured capability sources such as OpenAPI, MCP, OPTIMADE, Python callables, and third-party adapter protocols.
Status: 0.3.0a1 alpha. Install the current prerelease from PyPI with
pip install --pre schemarouter. This release includes bounded decision backends, LangChain/LlamaIndex integrations, authenticated MCP transports, execution approval/budgets, OpenAPI compatibility reporting, OpenTelemetry export, and explicit third-party adapter plugins.
Why
As an agent gains more tools, choosing the tool is only one part of the problem. The runtime also needs to know:
- which operation inside that tool is relevant;
- which parameters are declared and valid;
- which response fields should be retained;
- whether the operation is read-only, mutating, destructive, or unclassified;
- whether the schema changed after planning;
- whether the raw tool result actually satisfies the declared contract.
SchemaRouter makes those decisions explicit.
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)
results = router.invoke(
PlanRequest(
query="city temperature",
arguments={"city": "Seoul"},
)
)
print(results[0].data)
The same execution vocabulary works across capability sources:
router.invoke(request)
await router.ainvoke(request)
router.batch(requests)
await router.abatch(requests)
router.stream(request)
router.astream(request)
router.astream_events(request)
Bring your schema
OpenAPI
router = await SchemaRouter.from_url(
"https://api.example.com/openapi.json",
kind="openapi",
)
OPTIMADE
router = await SchemaRouter.from_url(
"https://www.crystallography.net/cod/optimade",
kind="optimade",
)
OPTIMADE entry schemas are discovered from /info/<entry_type>. Planned fields are translated
into the protocol's response_fields query parameter before execution.
MCP
pip install --pre "schemarouter[mcp]"
router = await SchemaRouter.from_url(
"http://localhost:8000/mcp",
kind="mcp",
)
Python
router.add_callable(my_typed_function)
Human-readable API docs
proposal = await router.inspect_url(
"https://docs.example.com/api",
model=documentation_model,
)
router.approve_proposal(
proposal,
base_url="https://api.example.com",
)
Human-readable documentation never becomes executable automatically. It first becomes an evidence-grounded proposal and then requires explicit approval.
Core guarantees
- Schema-constrained planning — unknown tools, endpoints, parameters, and fields cannot become executable calls.
- Runtime JSON Schema validation — validate arguments before invocation and raw output before projection.
- Schema and binding drift detection — stale plans and stale transports fail closed.
- Local execution authority — remote metadata and model output cannot grant mutation or destructive permissions.
- Credential separation — schema-fetch credentials and runtime credentials stay in different channels; authenticated MCP keeps secrets in the trusted transport boundary.
- Read-only retries by default — contract violations are never retried.
- Per-call approval and execution budgets — trusted local callbacks and deterministic call, attempt, remote, time, quota, and cost-unit limits fail closed.
- OpenAPI compatibility reporting — partial/unsupported constructs are machine-readable instead of silently reinterpreted.
- Redacted runtime events by default — payload tracing is opt-in.
- Pluggable registry — custom registries can implement the public
ToolRegistryprotocol. - Pluggable source adapters —
AdapterRegistrylets structured protocols compile into the sameToolSpec/EndpointSpecexecution model; installed entry-point plugins require an explicit allowlist before import. - Optional OpenTelemetry export — redacted runtime events can become parented run/tool spans without exporting payload values.
With LangChain
pip install --pre "schemarouter[langchain]"
from schemarouter.integrations import to_langchain_tools
tools = to_langchain_tools(router)
Execution still flows through SchemaRouter's policy, fingerprint, input, and output validation.
With LlamaIndex
Install the packaged LlamaIndex bridge:
pip install --pre "schemarouter[llamaindex]"
from schemarouter.integrations import to_llamaindex_tools
tools = to_llamaindex_tools(router)
LlamaIndex remains the agent/workflow layer; SchemaRouter retains schema identity, validation, and endpoint execution.
Experimental bounded decisions
SchemaRouter includes an optional bounded DecisionBackend for tool/endpoint selection. It is
off by default and cannot invent executable schema members.
from schemarouter import DecisionPolicy, SchemaPlanner
from schemarouter.integrations import JevDecisionBackend
planner = SchemaPlanner(
registry,
decision_backend=JevDecisionBackend(min_confidence=0.65),
decision_policy=DecisionPolicy(
enabled=True,
endpoint_selection=True,
fallback="deterministic",
),
)
Jev / TypeSafe System One is optional:
pip install --pre "schemarouter[jev]"
export TYPESAFE_API_KEY="..."
The provider receives only bounded decision inputs. Unknown option IDs fail closed, low-confidence valid choices can abstain, and deterministic fallback remains available. Jev is never enabled just because the package or an API key exists.
Decision benchmark
Run the deterministic baseline:
python scripts/benchmark_decision_routing.py
Compare Jev when credentials are available:
TYPESAFE_API_KEY="..." python scripts/benchmark_decision_routing.py --jev
The harness includes a checked-in 144-case multilingual/adversarial corpus and reports routing
accuracy, invalid-plan rate, abstentions/fallbacks, category accuracy, p50/p95 latency, token usage,
errors, and optional cost estimates. A provider-neutral ModelQueryAnalyzer callable can also be
supplied with --model-callable module:function.
python scripts/benchmark_decision_routing.py \
--corpus benchmarks/decision-routing-v1.json \
--json-out artifacts/decision-benchmark.json \
--csv-out artifacts/decision-benchmark.csv
Documentation
Full documentation is organized as a framework manual rather than embedded in this README:
- Getting started
- Core concepts
- OpenAPI guide
- OpenAPI compatibility
- OPTIMADE guide
- MCP guide
- LangChain integration
- LlamaIndex integration
- Jev / TypeSafe integration
- OpenTelemetry integration
- Third-party adapter plugins
- Decision backends
- Decision benchmark
- API reference
- Architecture
- Security
- Brand assets
Build the docs locally with:
pip install -e ".[docs]"
mkdocs serve
Development
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
ruff check .
pytest -q -m "not mcp_integration"
python examples/quickstart.py
python scripts/benchmark_decision_routing.py
# Type-check the complete packaged surface, including optional integrations.
pip install -e ".[dev,mcp,langchain,llamaindex,jev,otel]"
pyright
pytest -q --cov=schemarouter --cov-branch --cov-report=term-missing
Optional integration suites are isolated from the core package:
pip install -e ".[dev,mcp]"
pytest -q tests/test_mcp_integration.py
pip install -e ".[dev,langchain]"
pytest -q tests/test_langchain_integration.py
pip install -e ".[dev,llamaindex]"
pytest -q tests/test_llamaindex_integration.py
pip install -e ".[dev,jev]"
pytest -q tests/test_jev_integration.py
pip install -e ".[dev,otel]"
pytest -q tests/test_opentelemetry_integration.py
Project scope
SchemaRouter does not implement another chat abstraction, graph runtime, model-provider layer, memory system, or checkpoint store. Those belong in surrounding agent frameworks.
Its scope is:
Natural-language request -> typed tool execution plan -> validated execution.
Research
SchemaRouter originated from SchemaRouter: Field-Aware Tool Routing for Efficient Heterogeneous Agentic RAG. The framework keeps the research idea while removing harness assumptions such as one endpoint per tool and fixture-only execution.
License
MIT © 2026 Yong-eun Cho
Release files for schemarouter 0.3.0a1
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.3.0a1.tar.gz | 152.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| schemarouter-0.3.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 220.3 kB
Release files / schemarouter-0.3.0a1.tar.gz
| Download URL | schemarouter-0.3.0a1.tar.gz |
|---|---|
| Size | 152.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c88554382da95f99a54b23a14dc8d12cf1ffb1b78f348a216eadd9e872ca8d49
|
|
BLAKE2b-256 checksum How to use checksums |
284144643c23c3e71455141882be50e7145c37efa5f9bf84fd0a34778f0299e5
|
| 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 22, 2026.
Transparency logRelease files / schemarouter-0.3.0a1-py3-none-any.whl
| Download URL | schemarouter-0.3.0a1-py3-none-any.whl |
|---|---|
| Size | 68.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
91a9939789b9b99b163ef0030af5aa6578ca8a25bd307783f1be4d81432508fe
|
|
BLAKE2b-256 checksum How to use checksums |
bfc39b40de052ae9fca7a71498e213f31ca6370282958b68176c2235a87454fc
|
| 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 22, 2026.
Transparency log