Skip to main content

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)

  1. 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.
  2. 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).
  3. 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, baselines
  • planwise/data/catalog.json — sample catalog bundled with the package (the default when no --catalog is 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

planwise-0.2.0.tar.gz (65.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

planwise-0.2.0-py3-none-any.whl (82.5 kB view details)

Uploaded Python 3

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

Hashes for planwise-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a821d7e71df609ca39003b9701dfbfa8122ca1774c164032f8f10b77a4e23e4c
MD5 924cb137ccd60a563c4a717106b15faa
BLAKE2b-256 f60f601e6a083dbb333122085199ca2428fa7555fab1d6e6ca2cd5d2a37564a3

See more details on using hashes here.

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

Hashes for planwise-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9f552504ea1d9a7694d54d2072ac7034d8af34650c541cc25349902c859165b5
MD5 335f0b321e0909edf935dca5635af076
BLAKE2b-256 c5d822df8701a2e8f5d4b18a251f1527bff4a34d1b7cffdbbe8462a70764754d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page