Metadata-Version: 2.5
Name: opensmartroute
Version: 1.2.0
Summary: AI decision control plane: route each request to the best LLM, agent, skill, persona, tool or human under hard constraints, and learn from outcomes.
Project-URL: Homepage, https://opensmartroute.ai
Project-URL: Documentation, https://opensmartroute.ai/docs
Project-URL: Repository, https://dev.azure.com/bhogarinc/OpenSmartRoute/_git/OpenSmartRoute
Project-URL: Changelog, https://opensmartroute.ai/docs/changelog
Project-URL: Issues, https://dev.azure.com/bhogarinc/OpenSmartRoute/_workitems
Project-URL: Security, https://opensmartroute.ai/docs/security-policy
Author: OpenSmartRoute Contributors
License: Apache-2.0
License-File: LICENSE
Keywords: a2a,agent-routing,agents,ai-control-plane,ai-gateway,bradley-terry,cascade,conformal-prediction,contextual-bandits,cost-optimization,item-response-theory,llm,llm-router,mcp,mixture-of-models,model-routing,multi-agent,openai-compatible,persona,routerbench,skills,thompson-sampling,tool-selection
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Environment :: Web Environment
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Distributed Computing
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: all
Requires-Dist: bandit>=1.7; extra == 'all'
Requires-Dist: cryptography>=42.0; extra == 'all'
Requires-Dist: fastapi>=0.110; extra == 'all'
Requires-Dist: httpx>=0.27; extra == 'all'
Requires-Dist: jsonschema>=4.18; extra == 'all'
Requires-Dist: mcp<2,>=1.10; extra == 'all'
Requires-Dist: mypy>=1.10; extra == 'all'
Requires-Dist: numpy>=1.26; extra == 'all'
Requires-Dist: openai<3,>=1.50; extra == 'all'
Requires-Dist: opentelemetry-api>=1.25; extra == 'all'
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'all'
Requires-Dist: pydantic>=2.0; extra == 'all'
Requires-Dist: pytest-cov; extra == 'all'
Requires-Dist: pytest>=8.0; extra == 'all'
Requires-Dist: pyyaml>=6.0; extra == 'all'
Requires-Dist: ruff; extra == 'all'
Requires-Dist: sentence-transformers>=3.0; extra == 'all'
Requires-Dist: uvicorn>=0.29; extra == 'all'
Provides-Extra: crypto
Requires-Dist: cryptography>=42.0; extra == 'crypto'
Provides-Extra: dev
Requires-Dist: bandit>=1.7; extra == 'dev'
Requires-Dist: cryptography>=42.0; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: jsonschema>=4.18; extra == 'dev'
Requires-Dist: mcp<2,>=1.10; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: openai<3,>=1.50; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: pyyaml>=6.0; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: embeddings
Requires-Dist: sentence-transformers>=3.0; extra == 'embeddings'
Provides-Extra: fast
Requires-Dist: numpy>=1.26; extra == 'fast'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'otel'
Provides-Extra: server
Requires-Dist: fastapi>=0.110; extra == 'server'
Requires-Dist: pydantic>=2.0; extra == 'server'
Requires-Dist: uvicorn>=0.29; extra == 'server'
Provides-Extra: yaml
Requires-Dist: pyyaml>=6.0; extra == 'yaml'
Description-Content-Type: text/markdown

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://opensmartroute.ai/brand/logo-horizontal-reverse-1240.png">
    <img src="https://opensmartroute.ai/brand/logo-horizontal-1240.png" alt="OpenSmartRoute" width="620">
  </picture>
</p>

# OpenSmartRoute

> **An open, intelligent route to the right decision, solution, or destination.**

<p>
  <a href="https://dev.azure.com/bhogarinc/OpenSmartRoute/_build?definitionScope=%5CCI"><img alt="CI" src="https://dev.azure.com/bhogarinc/OpenSmartRoute/_apis/build/status%2FCI?branchName=main&label=CI"></a>
  <a href="https://dev.azure.com/bhogarinc/OpenSmartRoute/_build?definitionScope=%5CPlatform"><img alt="Platform" src="https://dev.azure.com/bhogarinc/OpenSmartRoute/_apis/build/status%2FPlatform?branchName=main&label=platform"></a>
  <a href="https://dev.azure.com/bhogarinc/OpenSmartRoute/_git/OpenSmartRoute/tags"><img alt="Release" src="https://img.shields.io/pypi/v/opensmartroute?logo=semanticrelease&logoColor=white&label=release"></a>
  <a href="https://pypi.org/project/opensmartroute/"><img alt="PyPI" src="https://img.shields.io/pypi/v/opensmartroute?logo=pypi&logoColor=white"></a>
  <a href="pyproject.toml"><img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-3776AB?logo=python&logoColor=white"></a>
  <a href="deploy/README.md"><img alt="Container image" src="https://img.shields.io/badge/acr-opensmartroute-2496ED?logo=docker&logoColor=white"></a>
  <a href="LICENSE"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/license-Apache--2.0-D22128?logo=apache&logoColor=white"></a>
  <a href="src/opensmartroute/py.typed"><img alt="Typed" src="https://img.shields.io/badge/typing-py.typed-informational?logo=python&logoColor=white"></a>
  <a href="pyproject.toml"><img alt="Zero runtime dependencies" src="https://img.shields.io/badge/runtime%20deps-0-brightgreen"></a>
  <a href="azure-pipelines/ci.yml"><img alt="Coverage >= 89%" src="https://img.shields.io/badge/coverage-91%25%20(floor%2089%25)-brightgreen?logo=pytest&logoColor=white"></a>
</p>

OpenSmartRoute is an open-source **AI decision control plane**. For each request it picks the best
**LLM, agent harness, skill, persona, tool, workflow or human**, honours hard constraints (privacy,
region, budget, latency), explains the choice, executes the resulting plan and **learns from every
outcome**. The core is pure Python with zero runtime dependencies.

```mermaid
flowchart LR
    R([request]) --> G["guard<br/>redact PII"]
    G --> S["signals<br/>&lt; 1 ms"]
    S --> P["policy<br/>hard constraints"]
    P --> ST["strategies + ensemble utility<br/>rules, capability, similarity, bandit, LLM judge"]
    ST --> D["decision<br/>trace + plan"]
    D --> X["execute<br/>compact prompt, persona -> skill -> model + tools / agent / tool / human"]
    X -. outcomes .-> ST
```

## Why

- **Everything is a route target.** One `RouteTarget` contract for models, agent harnesses, SKILL.md
  packages, personas, MCP tools, workflows and human queues; one policy layer; one learning loop.
- **Plans, not just picks.** `route(plan=True)` composes persona, skill, model and the tools the model may
  call; `run()` executes the plan - tool calls the model makes to offered tools included - and records an
  `Outcome` per participant. An instructions-only skill or persona runs on the plan's model with its body
  disclosed in the system prompt.
- **Fewer tokens before the call.** `estimate()` quotes tokens, cost, latency and quality per candidate
  (calibrated against billed tokens), and every model call is compacted first - whitespace, repeated log
  lines and stale history go, code and words stay - with the saving reported as `tokens_saved`.
- **Keeps itself current.** A running router follows the marketplace (new skills and tools land in the
  catalogue on a schedule), the self-improvement loop reads vendor blogs and release feeds for new models,
  and IDEs reach the marketplace through the local MCP server.
- **Constraints are never traded off.** PII, data boundary, region, tenant, cost and latency SLOs are
  filtered before any score is computed, with the rejection reason in the trace. Redacted PII is
  restored only for targets allowed to hold it; every other target, and every log, sees placeholders.
- **Learns in production.** Thompson bandits, Item Response Theory, Bradley-Terry preferences,
  LinUCB, Markov lookahead, task-level credit assignment, drift detection and forgetting.
- **Honest evaluation.** Baselines, oracle, label-noise floor, paraphrase robustness, calibration
  (ECE, Brier, conformal sets), off-policy estimators, public benchmark presets.
- **Secure by design.** Learned and heuristic guards against rerouting gadgets and prompt injection,
  PII redaction, resource limits, signed MCP manifests, encrypted state, hash-chained audit.
- **Enterprise-ready.** Builder, middleware, telemetry / state / audit ports, Redis and SQL stores,
  shadow and A/B routing with SPRT, tenant fair share, async facade, container image and Helm chart.

## Install

The `osr` command line and the Python package ship together. On Linux and macOS:

```bash
curl -LsSf https://opensmartroute.ai/install.sh | sh
```

On Windows (PowerShell):

```powershell
powershell -ExecutionPolicy ByPass -c "irm https://opensmartroute.ai/install.ps1 | iex"
```

The installer puts `osr` in an isolated environment (uv, pipx or a private venv - whichever is
available, never the system Python) and adds it to your PATH. `OSR_VERSION=1.2.0` pins a release,
`OSR_EXTRAS=all` installs every optional dependency, `OSR_INSTALLER=uv|pipx|venv` forces a backend and
`OSR_NO_MODIFY_PATH=1` leaves your shell configuration alone. The scripts are
[install.sh](install.sh) and [install.ps1](install.ps1) in this repository and in the `dist` artifact of every
release pipeline run.

If you already manage Python tools yourself:

```bash
uv tool install 'opensmartroute[yaml,server]'   # or: pipx install 'opensmartroute[yaml,server]'
pip install opensmartroute                       # library only, zero runtime dependencies
pip install 'opensmartroute[yaml]'               # + YAML catalogues and rules
pip install 'opensmartroute[server]'             # + FastAPI server and OpenAI-compatible proxy
pip install 'opensmartroute[embeddings]'         # + sentence-transformers similarity
pip install 'opensmartroute[otel]'               # + OpenTelemetry telemetry
pip install 'opensmartroute[crypto]'             # + AES-GCM encrypted state
```

Container image: `crosrua2c6onyidguw.azurecr.io/opensmartroute:<version>` ([deploy/README.md](deploy/README.md)).
From a checkout: `pip install -e '.[dev]'`.

Then sign in. The hosted platform (community or enterprise edition) uses a browser hand-shake; a
self-hosted `osr serve` accepts a token you generate yourself:

```bash
osr login                                              # opens https://opensmartroute.ai/cli/authorize
osr login --url https://osr.example.com                # your own platform deployment
osr login --url http://router:8000 --token osr_local_...   # self-hosted server (see `osr serve --generate-token`)
osr whoami                                             # workspace, plan, edition, key
```

Credentials live in `~/.config/opensmartroute/credentials.json` (`%APPDATA%\opensmartroute` on
Windows), one profile per `--profile`; `OSR_API_URL` / `OSR_API_KEY` override them in CI.

## Quick start

```python
from opensmartroute import Router, TargetRegistry, RouteTarget, TargetKind, Capabilities, Outcome

registry = TargetRegistry([
    RouteTarget("llm-small", TargetKind.LLM,
                capabilities=Capabilities(max_complexity=0.45),
                cost={"usd_per_1k_tokens": 0.0002}, latency_ms=300, quality_prior=0.55,
                examples=["Hi, how are you?", "What is the capital of France?"]),
    RouteTarget("llm-frontier", TargetKind.LLM,
                capabilities=Capabilities(min_complexity=0.5, domains=["math", "coding"]),
                cost={"usd_per_1k_tokens": 0.015}, latency_ms=2500, quality_prior=0.93,
                examples=["Prove the theorem step by step."]),
    RouteTarget("human", TargetKind.HUMAN,
                capabilities=Capabilities(actions=["escalate"], tags=["safety"]),
                cost={"usd_per_1k_tokens": 0.5}, latency_ms=300_000),
])

router = Router(registry)
d = router.route("Prove that sqrt(2) is irrational, step by step.")
print(d.target.id, f"{d.confidence:.2f}")     # llm-frontier 0.97
print(d.trace.explain())                       # per-strategy scores and rationales

router.learn(Outcome(request_id=d.request_id, target_id=d.target.id, success=True,
                     quality=0.9, cost_usd=0.002, latency_ms=1800, domains=d.trace.signals.domains))
```

Hard constraints and a per-request objective:

```python
from opensmartroute import RouteRequest, RequestConstraints, Objective

req = RouteRequest("Summarize this patient intake note.",
                   constraints=RequestConstraints(region="eu", data_boundary="private", max_cost_per_1k=0.005),
                   objective=Objective(quality=1.0, cost=0.5, latency=0.1, quality_floor=0.6))
d = router.route(req)
print(d.trace.policy_rejections)   # {'llm-frontier': 'cost 0.015 > budget 0.005', ...}
```

Catalogue and rules from YAML, evaluated and served from the command line:

```bash
osr -t examples/targets.yaml -r examples/rules.yaml route "I want a refund for order #123" --plan
osr -t examples/targets.yaml -r examples/rules.yaml eval examples/eval_dataset.jsonl --frontier
osr -t examples/targets.yaml -r examples/rules.yaml serve        # http://127.0.0.1:8000/docs
```

Wiring real providers, executing plans with `router.run()`, agent harnesses, SKILL.md and MCP
catalogues, the decorator SDK and the enterprise builder are covered step by step in
[docs/GUIDE.md](docs/GUIDE.md).

## What it routes

| Kind | Examples | Executed by |
|---|---|---|
| `llm` | model endpoints, per reasoning effort or token budget | OpenAI-compatible client or any callable |
| `agent` | coding, research and support harnesses with tools and memory | callable, HTTP or subprocess harness |
| `skill` | deterministic capabilities, SKILL.md packages | your function; instructions disclosed to the model |
| `persona` | system-prompt layers composed on top of the primary target | `run()` prompt composition |
| `tool` | MCP or function tools, with schema-aware matching | tool call - as the routed target, or offered to the plan's model as a function it may call |
| `workflow` | fixed multi-step pipelines | workflow engine |
| `human` | queues and experts with Erlang-C capacity maths | ticketing or hand-off; also the abstention target |

Catalogues load from YAML or JSON, MCP `tools/list` payloads, A2A agent cards, SKILL.md and persona
directories and vLLM semantic-router configurations; the router plugs into LangGraph and Agent
Framework graphs as a node and into any chat loop as an OpenAI tool.

## How it decides

1. **Signals** (under 1 ms): task type, domains, complexity, reasoning need, PII, language, modality,
   history; optional verbalised difficulty, cheap-draft features and hidden-state probes.
2. **Policy**: hard constraints filter targets before any scoring.
3. **Strategies**: rules, capability fit, example similarity, task table, Thompson and LinUCB bandits,
   IRT, Bradley-Terry, Markov lookahead, multi-turn history embeddings, learning-to-defer, edge/cloud
   tiers, token budgets, auctions, user adaptation and an LLM judge consulted only below a confidence
   threshold; optionally a routing SLM (`RouterSLM`) distilled from the whole ensemble that keeps
   improving on its own from outcomes, public routing datasets, a live model catalogue and the article
   feeds you point it at
   ([guide](docs/GUIDE.md#the-routing-slm-and-the-self-improvement-loop)).
4. **Utility**: confidence-weighted ensemble, then
   `w_q * quality - w_c * norm(cost) - w_l * norm(latency)` with a hard quality floor; temperature
   scaling and conformal candidate sets calibrate the confidence; the router abstains when nothing is
   safe enough.
5. **After the answer**: cascades and self-escalation stop or reroute on response-side uncertainty
   (semantic entropy, P(True), streaming competence posterior); mixture-of-agents aggregation and
   permanent hand-off policies cover agentic trajectories.

Formulas and citations: [docs/MATH.md](docs/MATH.md), [docs/RESEARCH.md](docs/RESEARCH.md).

## Production

```python
from opensmartroute import RouteRequest, RequestConstraints
from opensmartroute.enterprise import RouterBuilder, MetricsTelemetry, FileAuditSink, TenantMiddleware
from opensmartroute.security import GuardMiddleware

app = (RouterBuilder(registry)
       .with_defaults().with_auto_learning(state_dir=".osr-state")
       .with_health(latency_slo_ms=3000)
       .with_middleware(GuardMiddleware(redact=True),
                        TenantMiddleware({"acme": {"deny_targets": ["llm-frontier"]},
                                          "globex": {"data_boundary": "on_prem"}}))
       .with_telemetry(MetricsTelemetry()).with_audit(FileAuditSink("audit.jsonl"))
       .build())

req = RouteRequest("Prove that sqrt(2) is irrational.", constraints=RequestConstraints(tenant="acme"))
d = app.route(req)                 # guard -> tenant -> policy -> strategies; audited and measured
result = app.run(req)              # ...then executes the plan once targets carry handlers, and learns
print(d.target.id, app.health_snapshot())
```

Routing overhead is 6 ms p50 with the default strategies and 9 ms with every learner enabled on a
16-target catalogue; retrieve-then-rank keeps it flat for thousands of tools
([measurements](docs/GUIDE.md#10-routing-latency)). `osr serve` (or `create_app(app)` with the
router above) exposes a FastAPI app and an OpenAI-compatible proxy (`/v1/chat/completions` with streaming
and tool calling, `/v1/embeddings`, `/v1/models`) plus an MCP endpoint (`/mcp`): point the official OpenAI
SDK at it with `model="osr/auto"` and keep the rest of the code; guard and tenant violations return 400, no
admissible target 422, an unreachable provider 503 and a failing target falls back to the next candidate.
Circuit breakers open on provider failures and recover on their own;
learner state survives restarts from `state_dir` or a Redis / SQL store. Deployment references:
[deploy/README.md](deploy/README.md), [docs/ENTERPRISE.md](docs/ENTERPRISE.md).

## Hosted platform

[platform/](platform/README.md) packages the router as a service in two containers: `osr-platform-api`
(FastAPI: self-serve signup with hashed API keys, plans and quotas, usage metering, the metered
`/api/v1/route` family with the full trace, per-tenant constraints and workspace policy, the audit
trail, per-request traces and a live event stream, and the OpenAI-compatible `/v1/chat/completions`
proxy) and `osr-platform-web` (Next.js: landing page, the rendered documentation, pricing, a live
playground and the account dashboard with activity, events, governance and health pages; it proxies
`/api` and `/v1` so the browser only talks to one origin). `OSR_PLATFORM_EDITION=community` runs the core
`Router`; `enterprise` runs the builder above with auto-learning, health, guard, metrics, a
hash-chained audit log and per-tenant constraints. `azd up` deploys both to Azure Container Apps with
Azure OpenAI from [infra/](infra/main.bicep); the reference deployment is
https://opensmartroute.ai. The end-user guide is
[docs/PLATFORM.md](docs/PLATFORM.md); the REST API reference is generated from
[platform/api/openapi.json](platform/api/openapi.json).

```bash
curl -s -XPOST $OSR/api/v1/signup -H 'content-type: application/json' -d '{"email":"you@example.com"}'
curl -s $OSR/api/v1/route -H "authorization: Bearer $KEY" -H 'content-type: application/json' \
     -d '{"text":"Prove that sqrt(2) is irrational."}'
```

## Security

Routing is a control plane; its integrity is a security property. `InputGuard` combines a heuristic
and a learned detector for confounder gadgets that reroute queries, an injection-risk scorer, PII
redaction and prompt sanitisation for the LLM judge. Per-task resource limits, an origin policy for
sensitive tool parameters, signed MCP manifests, AES-GCM state, content-free logs and hash-chained
audit complete the model. CI runs `ruff -S`, `mypy`, `bandit`, CodeQL and the `osr safety` red-team
suite. Threat model: [docs/SECURITY.md](docs/SECURITY.md). Reporting: [SECURITY.md](SECURITY.md).

## Documentation

The user documentation is a searchable, versioned site at
https://opensmartroute.ai/docs (built from these files
at release time, with a REST API reference generated from the platform's OpenAPI document). It covers
the hosted platform, the Python SDK and the pip package; the internal planning, go-to-market, brand
and sales documents below stay in the repository only.

| Document | Contents |
|---|---|
| [docs/QUICKSTART_PLATFORM.md](docs/QUICKSTART_PLATFORM.md) | Platform quickstart: workspace and key, first `/api/v1/route` call, the OpenAI-compatible endpoint, feedback |
| [docs/QUICKSTART_SDK.md](docs/QUICKSTART_SDK.md) | Python SDK quickstart: install, describe targets, route, constraints and objectives, learning, the CLI |
| [docs/GUIDE.md](docs/GUIDE.md) | User guide: targets, routing, execution, providers, learning, SDK, enterprise builder, research-track modules, CLI, latency, layout |
| [docs/PLATFORM.md](docs/PLATFORM.md) | Platform guide: authentication, `/api/v1/route`, execution, the OpenAI-compatible endpoint, feedback, plans and quotas, organizations, tenants, governance, observability (traces, events, readiness), the MCP server, dashboard |
| [docs/MARKETPLACE.md](docs/MARKETPLACE.md) | Marketplace: find, install, buy and publish agents, skills, personas, prompts and stack templates; ratings, review lifecycle, `osr stack` |
| [docs/MCP.md](docs/MCP.md) | Cost estimates (`estimate`, `POST /api/v1/estimate`), recommended models per use case and the MCP server for VS Code, Cursor, Claude, Windsurf and agents |
| [docs/SDK.md](docs/SDK.md) | API reference for the decorator SDK, components and settings |
| [docs/REFERENCE.md](docs/REFERENCE.md) | Generated API reference: every module and exported name (`python scripts/api_reference.py`) |
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Request path, module boundaries, performance envelope |
| [docs/ENTERPRISE.md](docs/ENTERPRISE.md) | Ports, stores, middleware, shadow and A/B, multi-replica operation |
| [docs/OBSERVABILITY.md](docs/OBSERVABILITY.md) | Tracing and observability: spans and events for every stage, sinks (memory, metrics, log, file, OpenTelemetry), `/events`, `/trace`, `/metrics`, `OSR_OBSERVABILITY_*`; the platform's per-workspace `/api/v1/trace`, `/api/v1/events`, `/api/v1/status` and dashboard pages |
| [docs/MATH.md](docs/MATH.md) | Every formula the router uses, with derivations |
| [docs/RESEARCH.md](docs/RESEARCH.md) | Literature survey and the idea-to-module map |
| [docs/SECURITY.md](docs/SECURITY.md) | Threat model and hardening checklist |
| [docs/SECURITY_REVIEW.md](docs/SECURITY_REVIEW.md) | External security review pack: scope, trust boundaries, evidence, reviewer questions, review log |
| [docs/ROADMAP.md](docs/ROADMAP.md) | Per-version exit criteria and status |
| [docs/PLATFORM_PLAN.md](docs/PLATFORM_PLAN.md) | Platform strategy: agentic routing, Open Capability Manifest, marketplace, editions and pricing |
| [docs/GO_TO_MARKET.md](docs/GO_TO_MARKET.md) | Go-to-market plan; the sales enablement kit lives in [docs/sales/](docs/sales/README.md) |
| [spec/ocm/README.md](spec/ocm/README.md) | Open Capability Manifest specification and JSON Schema |
| [deploy/README.md](deploy/README.md) | Container image, Helm chart, reference deployments |
| [platform/README.md](platform/README.md) | Hosted platform: `api/` (FastAPI) and `web/` (Next.js), playground, API keys, plans, editions, `OSR_PLATFORM_*` settings, Azure deployment |
| [docs/BRAND.md](docs/BRAND.md) | Logo system and naming conventions |

[.claude/skills/](.claude/skills/) ships Agent-Skills packages that teach coding assistants how to use
and extend the project; they are also valid routing targets (`osr skills` validates them) and each one is
published on the documentation site under `/docs/skills/`. Coding agents working in this repository
start from [AGENTS.md](AGENTS.md).

## Roadmap

| Release | Theme | Status |
|---|---|---|
| 0.3 | Real integrations: OpenAI-compatible client, adapters, config loaders | Shipped |
| 0.4 | Learned signals and honest evaluation | Shipped |
| 0.5 | Target representations, effort and personalisation | Complete |
| 0.6 | Multi-step and agentic routing | Complete |
| 0.7 | Catalogue interop and discovery at scale | Complete |
| 0.8 | Operations, risk control and economics | Complete |
| 0.9 | Security hardening of the control plane | Complete |
| 1.0 | Stable API, reference deployments, security review pack | Complete |

Every item in the research track is implemented on `main` with tests; a version is **Complete** when
its measured exit criterion is published (`python scripts/exit_criteria.py`, 8/8 met) and **Shipped**
when it is in a tagged release. 1.0 means what the repository can prove: frozen public API with a
deprecation path, published performance envelope, reference deployments, security controls with a
red-team suite in CI and a published review pack ([docs/SECURITY_REVIEW.md](docs/SECURITY_REVIEW.md)),
the public leaderboard run ([examples/leaderboard/results](examples/leaderboard/results/README.md),
produced by the recipe in [examples/leaderboard](examples/leaderboard/README.md)) and two consecutive
releases without a breaking change. Adoption evidence - an independent security report, accepted
leaderboard listings, two production users ([ADOPTERS.md](ADOPTERS.md)) - is tracked, never claimed:
`python scripts/release.py readiness` prints the whole table computed from the repository, and the
release tooling refuses any `1.x` version while a release row is open.
Details in [docs/ROADMAP.md](docs/ROADMAP.md) and [CHANGELOG.md](CHANGELOG.md).

## Contributing

Issues and pull requests are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md). CI runs `ruff`, `mypy`,
`bandit` and `pytest` on CPython 3.10 to 3.13 (Linux and Windows), a routing-accuracy gate and the
safety suite on the example catalogue, builds the distribution and the container image, and scans with
CodeQL. The test suite has no mocks of the router itself: [tests/test_e2e_scenarios.py](tests/test_e2e_scenarios.py)
drives the shipped example catalogue through an in-process OpenAI-compatible provider fleet over
HTTP, a real MCP server subprocess over stdio, the CLI, the FastAPI service, provider outages with
breaker recovery, agentic multi-round loops and concurrent traffic. Releases are automated: a release
pull request bumps the version and rolls the changelog; merging it tags, publishes to PyPI with
attestations and pushes the image.

## License

Apache-2.0
