The Problem
Building agentic applications quickly reveals a “hidden middleware” problem: routing logic, guardrails, observability, and model‑provider quirks are scattered across frameworks and application code, forcing every team to reinvent the same plumbing before reaching production.
What This Does
Plano is a collection of five semi‑independent projects (crates, apps, demos, cli, packages) that move core delivery concerns into an out‑of‑process data plane.
- Crates (
crates/brightstaff) – Rust‑based core: agent selection, function calling, LLM handling, and signal pipeline processing. Files such ascrates/brightstaff/src/handlers/agent_selector.rs,crates/brightstaff/src/handlers/function_calling.rs, andcrates/brightstaff/src/signals/analyzer.rsare oversized (≈1 650 loc) and have deep nesting (max indent 8), making control flow hard to follow. - Apps (
apps/www,apps/katanemo-www) – Next.js front‑ends that consume the data plane; they contain duplicated next‑config and layout boilerplate (1292 repeated 6‑line blocks across 98 files). - Demos (
demos/) – Small proof‑of‑concepts (e.g.,demos/filter_chains/http_filter/src/rag_agent/api) that showcase filter chains, MCP integration, and rag‑agent APIs. - CLI (
cli/planoai) – Python entry point (cli/planoai/main.py) that exposes commands for tracing and model interaction. - Packages (
packages/) – Shared UI and utility code (packages/ui/src/lib/utils,packages/ui/src/components/Navbar).
Recurring techniques across the portfolio include filter chains for guardrails, model‑agile routing (by name, alias, or preference), and zero‑code agentic signal capture via OTEL.
How It Is Wired
The internal call graph contains 125 modules and 42 import edges with no circular dependencies (analyzed 253 of 253 code files).
- Entry points that start a run:
cli/planoai/main.py– CLI dispatcher, parses commands and delegates to the data plane.crates/brightstaff/src/main.rs– Rust runtime that boots the proxy/agent orchestrator.apps/www/src/components/research/index.tsandapps/www/schemaTypes/index.ts– Front‑end types and UI that talk to the proxy over HTTP.
- Control flow: CLI → Python wrapper → Rust crate (
brightstaff) → internal handlers (agent_selector,function_calling,pipeline_processor). The handlers import frompackages/uifor UI helpers and from each other via a small set of edges (e.g.,agent_selectorimportsfunction_calling). The widest blast radius is incrates/brightstaff/src/handlers/pipeline_processor.rs(1 659 loc), where a change ripples through agent routing and signal aggregation.
- Out‑of‑process data plane: The Rust crate listens on a Unix socket/HTTP port; front‑ends and demos communicate via REST/GRPC‑like calls, keeping agent logic isolated from framework specifics.
How To Use It
Setup
# Clone the repo (verbatim URL)
git clone https://github.com/moses-y/plano
# Install Node deps for the web app
cd apps/www && npm install
# Install Python deps for the CLI
cd cli && pip install -r pyproject.toml # or `uv pip install -r pyproject.toml`
# Build the Rust data plane
cd crates/brightstaff && cargo build --release
Configuration
- Environment variables are read from
.envfiles referenced incli/planoai/trace_cmd.pyandapps/www/.env.example(not committed). Key vars:PLANO_BACKEND_URL,OPENAI_API_KEY,ANTHROPIC_API_KEY. - Docker base images are defined in
Dockerfile(rust:1.93.0,python:3.14-slim,docker.io/envoyproxy/envoy:v1.37.0).
Running it
# Start the Rust data plane (background)
cd crates/brightstaff && ./target/release/brightstaff &
# Start the Next.js UI
cd apps/www && npm run dev # http://localhost:3000
# CLI example – trace a request
cd cli && python planoai/main.py trace --url http://localhost:8080 --model gpt-4o
Real‑World Use
A travel‑agent demo (demos/filter_chains/mcp_filter/src/rag_agent/api) registers three agents (flight, hotel, car). Incoming user requests are routed by Plano’s model‑router (alias “budget‑travel”) through the filter chain that injects moderation policies and logs OTEL traces. The UI (apps/www/src/components/research/index.ts) displays the agent decisions and signal metrics, while the Rust core handles routing without any framework‑specific code.
Code Health & Issues
- HIGH – Pin third‑party GitHub Actions to commit SHAs:
.github/workflowsuses@v3.0.1,@v3,@v6,@masterforpre-commit/action,docker/setup-buildx-action,docker/build-push-action,aquasecurity/trivy-action. Mutable tags can introduce supply‑chain risk. - MEDIUM – Enable Dependabot/Renovate: 24 manifests, no update bot configured.
- MEDIUM – Pin container base images by digest:
Dockerfileusesrust:1.93.0,docker.io/envoyproxy/envoy:v1.37.0,python:3.14-slimwithout digests. - MEDIUM – Move large binaries out of repo:
docs/source/_static/img/tracing.pngis 8.6 MB; other blobs >5 MB exist. - MEDIUM – Add non‑root USER to Docker images: no
USERdirective present. - LOW – Set
timeout-minuteson CI jobs: 4 workflows have no job timeout, risking overlap on a two‑hourly schedule.
The Bottom Line
Plano delivers a pragmatic data‑plane for agentic apps: orchestration, model‑agile routing, and observability are provided as reusable Rust services, while the five project buckets let teams pick the pieces they need. The code base is functional but suffers from oversized Rust files, duplicated Next.js config, and SDLC hygiene gaps (mutable Action pins, missing Dependabot, untagged Docker images). It is well‑suited for teams that want to offload routing, guardrails, and tracing without embedding those concerns in their application framework, provided they address the pinning and image‑security findings.