PlanWise Router — intelligent tool routing layer for large tool catalogs
Project description
PlanWise Router
An intelligent tool-routing layer for large tool catalogs (60+ tools). Instead of showing an AI agent every tool schema — which wastes tokens and causes wrong picks between look-alike tools — PlanWise reads the user's query, writes a step-by-step plan, and hands the agent only the 3–6 tools it actually needs, in the right order.
Built for the Crest Data AI Innovation Challenge (Problem 02).
How it works (short version)
- Offline: every tool passes quality gates, gets ~8 LLM-written example user questions, and is indexed (embeddings + keywords). Twin tools are grouped; version families (v1/v2) are linked.
- Runtime: one cheap LLM call breaks the query into abstract steps (it never sees tool names, so it can't invent one). Each step finds its best tool with a 4-signal score: meaning match + keyword match + input fit + output fit (what the tool returns vs what the step needs — this is how same-input twins get told apart).
- Hand-off: the agent gets the few chosen tool schemas plus a plan hint like
Suggested plan: 1) get_revenue_report 2) generate_chart 3) send_email.
Full design: docs/HLD.md · docs/LLD.md · docs/architecture-diagram.html
Quick start
pip install planwise # from PyPI
# or, from a checkout: pip install -e ".[dev]" (pip install -e . for minimal core)
# Route one query — uses the sample catalog bundled with the package
planwise route "Pull last quarter's revenue and email the chart to finance@corp.com"
# Point it at your own catalog ({"tools": [...]}) any time
planwise route "..." --catalog my_catalog.json
# Run the evaluation harness (with the naive baseline to beat)
planwise eval --baseline
A sample catalog ships inside the package, so planwise route "..." works with no repo checkout. --catalog (or the PLANWISE_CATALOG env var) overrides it with your own.
Works fully offline out of the box: with no gateway configured it uses a rule-based planner and lexical embeddings. For the real pipeline (LLM planner + semantic embeddings), point it at the Crest AWS Bedrock gateway (OpenAI-compatible):
pip install -e ".[llm,embeddings]"
export PLANWISE_LLM_API_KEY=sk-... # your gateway key
export PLANWISE_LLM_CERT=/path/to/apiproxy.cdsys.crt # internal-CA cert from IT
# must be on the Crest network / VPN
planwise eval --baseline
All LLM traffic goes through planwise/engine/llm.py (one place). The key and cert path come from the environment — never hardcoded or committed. Default models: Bedrock-ant-haiku-4-5-20251001-v1-0 for the planner/enrichment.
Layout
planwise/engine/— the routing engine (pure library: intake, index, planner, scorer, binder, assembler)planwise/middleware/— self-healing execution wrapper (Tier 2)planwise/server/— HTTP gateway (Tier 1),planwise/mcp_server.py— MCP surface (Tier 3)eval/— evaluation harness, stress suites, baselinesplanwise/data/catalog.json— sample catalog bundled with the package (the default when no--catalogis given)data/— ground-truth queries + eval catalogs (replaced by the organizers' files at hackathon start)
Tier 1 — HTTP gateway
A stateless FastAPI service over the engine, so any stack (Python, Java, Go, Node.js, .NET, …) can route without embedding the library. Horizontally scalable, containerized, with runtime catalog updates (no restart). Full docs + architecture diagrams + design rationale: docs/http-gateway.md.
Run locally
pip install -e ".[server,embeddings]"
# CLI (applies --proxy-headers, structured JSON logs; bundled catalog by default):
planwise serve --host 0.0.0.0 --port 8000
# …or serve your own catalog:
planwise serve --host 0.0.0.0 --port 8000 --catalog my_catalog.json
# or directly with uvicorn (ASGI target is planwise.server.app:app):
PLANWISE_CATALOG=my_catalog.json uvicorn planwise.server.app:app
Environment variables
| Var | Meaning |
|---|---|
PLANWISE_CATALOG |
Path to the boot catalog JSON ({"tools": [...]}) |
PLANWISE_LLM_API_KEY |
LLM gateway bearer key (enables the LLM planner; offline rules planner otherwise) |
PLANWISE_LLM_CERT |
Path to the internal-CA cert for the LLM gateway |
PLANWISE_LOG_JSON |
true for structured JSON logs (default in Docker) |
PLANWISE_LOG_LEVEL |
DEBUG / INFO / … |
.env is auto-loaded if python-dotenv is installed. Secrets come only from the environment — never hardcoded or logged.
Example curl
curl -s localhost:8000/healthz
# Route, asking for the OpenAI tool dialect back:
curl -s 'localhost:8000/route?format=openai' -H 'content-type: application/json' \
-d '{"query":"Pull last quarter revenue and email the chart to finance@corp.com"}'
# Replace the whole catalog at runtime (no restart):
curl -s localhost:8000/catalog -H 'content-type: application/json' -d @my_catalog.json
# Add / remove a single tool:
curl -s localhost:8000/catalog/tool -H 'content-type: application/json' -d '{"tool": {…}}'
curl -s -X DELETE localhost:8000/catalog/send_email
# Report an outcome (returns 202):
curl -s localhost:8000/feedback -H 'content-type: application/json' \
-d '{"query":"…","route_id":"…","called":["send_email"],"outcome":"success"}'
Interactive API docs at GET /docs (Swagger) and GET /openapi.json.
Run with Docker
docker build -t planwise .
docker run -p 8000:8000 \
-e PLANWISE_LLM_API_KEY=... \
-e PLANWISE_LLM_CERT=/app/apiproxy.cdsys.crt \
-e PLANWISE_CATALOG=/app/catalog.json \
-v ./catalog.json:/app/catalog.json \
-v ./apiproxy.cdsys.crt:/app/apiproxy.cdsys.crt \
planwise
Deployment
Sits behind Nginx / Traefik / K8s Ingress / AWS ALB / Cloudflare, which own TLS, auth and rate limiting. The service is stateless and proxy-friendly (honors X-Forwarded-*); scale by adding replicas. Probes: /healthz (liveness) and /readyz (readiness).
Tests
python -m pytest tests/
Tests run deterministic and offline (hashing embeddings, rules planner) — no downloads, no API keys.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file planwise-0.2.0.tar.gz.
File metadata
- Download URL: planwise-0.2.0.tar.gz
- Upload date:
- Size: 65.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a821d7e71df609ca39003b9701dfbfa8122ca1774c164032f8f10b77a4e23e4c
|
|
| MD5 |
924cb137ccd60a563c4a717106b15faa
|
|
| BLAKE2b-256 |
f60f601e6a083dbb333122085199ca2428fa7555fab1d6e6ca2cd5d2a37564a3
|
File details
Details for the file planwise-0.2.0-py3-none-any.whl.
File metadata
- Download URL: planwise-0.2.0-py3-none-any.whl
- Upload date:
- Size: 82.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f552504ea1d9a7694d54d2072ac7034d8af34650c541cc25349902c859165b5
|
|
| MD5 |
335f0b321e0909edf935dca5635af076
|
|
| BLAKE2b-256 |
c5d822df8701a2e8f5d4b18a251f1527bff4a34d1b7cffdbbe8462a70764754d
|