Skip to main content

SchemaRouter

SchemaRouter

Schema-aware planning and execution for LLM tool ecosystems.

English · 한국어

CI Docs License: MIT

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.0 is the current public non-prerelease release. Install it from PyPI with pip install schemarouter. SchemaRouter remains pre-1.0, so deliberate compatibility changes may still occur in later 0.x minor releases under the documented versioning policy.

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 "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 ToolRegistry protocol.
  • Pluggable source adapters — AdapterRegistry lets structured protocols compile into the same ToolSpec / EndpointSpec execution 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 "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 "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 "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:

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.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.3.0
File Size Uploaded
schemarouter-0.3.0.tar.gz 154.4 kB Details

Built distribution (wheel)

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

Total release size: 222.5 kB

Release files / schemarouter-0.3.0.tar.gz

Download URL schemarouter-0.3.0.tar.gz
Size 154.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ff09096f1c5493d235cb3fd87d85b6c9394ff22bd911af0a6b40b4e827585313
BLAKE2b-256 checksum
How to use checksums
a04cd43ab183234ca6dda3d76424c1f798be403ce4ea81df0163e42705243ff5
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

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

Download URL schemarouter-0.3.0-py3-none-any.whl
Size 68.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d3f79319b62af8320fb3c86781513a31e669cfc681b403b10348e8ab960b19b2
BLAKE2b-256 checksum
How to use checksums
21053f7e7f32deaff55a6ea40be559ecffb14f0ad963535fa28c2de96aeeb56a
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

Release history Release notifications | RSS feed

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

This release

0.3.0 This release

2 release files

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