switchboard
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Fail
- Hardcoded secret — Potential hardcoded credential in config/personal.example.yaml
- Hardcoded secret — Potential hardcoded credential in config/personal.yaml
- process.env — Environment variable access in integrations/openclaw/dist/index.js
- Hardcoded secret — Potential hardcoded credential in integrations/openclaw/dist/lib.js
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Privacy-aware, local-first router for your CLI coding agents (Codex, Claude Code) and local LLMs (Ollama) — keeps sensitive prompts on-device and cuts premium-model usage.
Switchboard
A privacy-aware, local-first router across your CLI coding agents and local LLMs.
Install · How it works · Proof · Privacy · Context · Paper · Docs
One workstation, several ways to run a model: subscription CLI agents (Claude
Code, Codex) and whatever Ollama serves locally. Every prompt is a small
decision — does this need a premium model, is it safe to send off-box, and will
the next backend know what the last one did?
Switchboard makes that decision explicit. It routes each prompt across your
agents and local models — deterministic rules first — keeps sensitive work
local even on fallback, and carries session context and memory across backend
switches. It's built for the setting where the scarce resources aren't
dollars-per-token but subscription quota, privacy, and a pile of
heterogeneous agent interfaces.
Status: v0.1.1, early, single-maintainer. Deliberately a
single-workstation tool — not a hosted service, not an API proxy. The privacy
invariant is the part that won't move (CONTRIBUTING.md).
What it does
- Routes across local Ollama models, the Codex CLI, and Claude Code — deterministic rules first, with optional tiny learned classifiers for recall.
- Private mode — a deterministic keyword/PII/secret-format floor blocks sensitive prompts from ever reaching a subscription backend, even on fallback.
- Grounds answers with deterministic tools (time/date, safe calculator, unit conversion, keyless live stock & news) instead of letting a model guess.
- Carries context across backend switches: recent user, assistant, and tool turns are assembled into one redacted session prompt.
- Compresses long context with a Headroom-inspired layer; the model-boundary pass only summarizes recent conversation, while trusted facts, retrieved memory, and the current request survive intact.
- Remembers across backends via local embedding-based semantic memory, with SQLite search available for direct memory lookup.
- Explains every decision and records metadata-only telemetry (no prompt/response bodies).
- Ships its own evaluation — a 100-case quality benchmark and a local
LLM-as-judge; the multi-run statistical harness travels with the
paper's reproduction bundle.
How it works
UI / CLI ──► Session manager (shared history across all backends)
│
▼
Capability detector (regex) ◄──► deterministic tools
│ (learned tool dispatcher recovers misses; tool verifies)
▼
Privacy floor (keywords + PII + secret formats — a match is FINAL)
│ (learned sensitivity escalator may only ADD protection)
▼
Deterministic policy ← always wins; unknown ⇒ local
│ (learned router supplies recall: tool / local / coding / reasoning)
▼
Context builder + redaction ◄── semantic memory
│
▼
Compression (metadata + history-only context pass)
│
▼
Ollama (default) │ Codex (coding) │ Claude Code (reasoning)
│
▼
Response sanitizer ─► metadata-only telemetry
The organizing invariant: deterministic policy always precedes and overrides
the learned components.
Design decisions
- Learned components add recall, never authority. The classifiers can
escalate protection or recover a missed tool call; they cannot relax a
privacy verdict or override the deterministic policy. - Fail closed, stay up. If the local model runtime is down, every learned
component is down with it — and privacy, tool grounding, forced selection,
and fallback keep working on the deterministic path alone. - One source of truth for secrets. Secret-format detection shares its
patterns with context redaction, so the routing boundary and the redactor
cannot drift apart. - Local-first on uncertainty. A prompt the policy can't classify routes to
the local model, not to a subscription backend. - Metadata-only telemetry. Every routing decision is explained and
recorded; prompt and response bodies are not stored by default.
Get started
Install from source (Switchboard is not published to PyPI):
pip install "git+https://github.com/aivinay/switchboard"
Or work from a clone:
git clone https://github.com/aivinay/switchboard
cd switchboard
make install # .venv + editable install with dev extras
Then:
# point it at a local model runtime (install Ollama, then pull a small model)
ollama pull llama3.2:3b
# sanity-check your setup
switchboard doctor
# ask — Switchboard routes it, grounds it, and tells you why
switchboard ask "summarize this error log and suggest a fix"
# see the routing decision without running anything
switchboard route "refactor the auth module and add tests"
# prefer your browser? launch the local web UI, then open http://127.0.0.1:8080/ui
switchboard ui
Requires Python 3.11+. Codex / Claude Code backends are optional — without
them, everything routes locally. See docs/usage.md.
Proof
A 100-case benchmark across five task categories (coding, reasoning,
summarization, private, grounding), run on real backends, judged by a local
model, and repeated over independent runs. Means shown; per-condition numbers,
confidence intervals, and significance tests are in the paper.
Read the table as the shape of the quality/privacy/quota tradeoff, not as
leaderboard scores. Zero privacy leaks were measured in any condition, in
any run.
| Policy | Quality (1–5) | Premium usage | Privacy leaks | Answered |
|---|---|---|---|---|
| always-local | 3.4 | 0% | 0 | 100% |
| rules | 3.8 | 27% | 0 | 100% |
| hybrid | 3.9 | 28% | 0 | 100% |
| learned | 4.1 | 38% | 0 | 100% |
| always-premium | 4.6 | 100% | 0 | 61%¹ |
¹ The "just use the premium agent for everything" baseline must block every
sensitive prompt to stay leak-free, so 39% of cases go unanswered. The routed
policies answer those prompts locally instead.
Verify it yourself (no install required)
- CI logs are public — every run
shows what was checked and when;make checkruns ruff, mypy, and
the test suite locally. - The tests are in the open — browse
tests/before you clone anything. - The benchmark's raw material is archived — the reproduction bundle on Zenodo
carries the manuscript, the experiment harness, the run records, and the
aggregated results behind the table above. - Releases are tagged — v0.1.1
with a CHANGELOG that says what changed. - The docs exist — usage, privacy,
overrides, context, memory & compression.
Privacy
Switchboard is local-first and privacy-aware by construction:
- The deterministic privacy floor runs before any non-local routing; a positive verdict is final and cannot be overridden by a learned component or by prompt wording.
- Secret-format detection (cloud keys, JWTs, PEM blocks, env credentials) shares its patterns with context redaction, so the routing boundary and the redactor can't drift apart.
- Metadata-only telemetry — prompt and response bodies are not stored by default.
- Semantic-memory embeddings and the eval judge run locally.
Switchboard deliberately does not resell API access, scrape web UIs, or
bypass provider limits — subscription CLIs are invoked exactly as the
authenticated user could invoke them, in read-only sandbox modes. See
SECURITY.md and docs/privacy.md.
- Deterministic router — keyword rules; unknown prompts default local-first.
- Learned router / tool dispatcher / sensitivity escalator — tiny softmax classifiers over a locally-computed embedding (~50 ms, pure-Python inference), each retrainable in seconds from your own thumbs-down corrections behind golden-accuracy gates. They fail closed to the deterministic path.
- Tools — time/date with timezones, safe abstract-syntax-tree calculator, unit conversion, keyless live stock quotes & news.
- Compression — structure-aware, deterministic, dependency-free; preserves task header, code blocks, tracebacks, and grounded facts.
- Semantic memory —
nomic-embed-textembeddings, cosine retrieval, local memory commands, and SQLite text-search fallback for direct search. - Evaluation — mock evals (CI), real-backend smoke suite, 100-case quality benchmark, adversarial tester/developer dogfooding loop.
Context, memory, and tokens
Switchboard has two user-facing CLI surfaces:
switchboard route ...and bareswitchboard ask ...use the personal local-first route/call workflow.- The web UI and
switchboard ask --backend auto ...use the stateful core workflow: shared sessions, model switching, semantic-memory retrieval, context-boundary compression, and backend telemetry all run on the same path.
Example stateful CLI session:
switchboard ask --backend auto --new-session "Remember: prefer local models for private notes."
switchboard ask --backend auto --session <session_id> --memory "What should you remember?"
Long prompts and long sessions record token estimates and savings metadata. The request-level pass can shorten an oversized raw prompt; the context-boundary pass then compresses only <recent_conversation>. The <trusted_facts>, <long_term_memory>, and <current_user_request> blocks are protected from that second pass so grounding and intent are not traded away for token budget.
Memory is local. switchboard memory add stores the item in SQLite and, when semantic_memory_enabled is on and Ollama can serve nomic-embed-text, indexes an embedding for cross-backend retrieval. switchboard memory search works as local text search even when embeddings are unavailable.
Details: docs/context-memory-compression.md.
Configuration
Settings live in config/personal.yaml (ships with safe local-first defaults —
see config/personal.example.yaml). Highlights:
preferences:
router_mode: "learned" # rules | llm | hybrid | learned
private_mode: true # block sensitive prompts from non-local backends
allow_cloud: false
compression_enabled: true
compression_threshold_tokens: 1000
semantic_memory_enabled: true
semantic_memory_top_k: 3
finance_provider: "yahoo"
news_provider: "google_news_rss"
Provider API keys are referenced by environment-variable name (e.g.OPENAI_API_KEY), never inline. See docs/overrides.md.
The paper
Switchboard is described in a preprint — "Switchboard: Privacy-Aware Hybrid
Routing Across Heterogeneous AI Agents" (v2.0). The manuscript, the multi-run
benchmark harness, the statistical-aggregation and figure scripts, and the
per-case records are archived together as a reproduction bundle on Zenodo:
10.5281/zenodo.20836918.
This repository ships only the software. It deliberately does not carry the
paper's experiment-running or figure-generation tooling — that lives with the
archival record so the code stays focused on the router itself.
Development
git clone https://github.com/aivinay/switchboard && cd switchboard
make install # .venv + editable install with dev extras
make check # ruff + mypy + the full test suite
CI runs the mock evals alongside lint, types, and tests; the smoke suite and
the 100-case benchmark run against real backends. See
CONTRIBUTING.md. Issues and PRs welcome — please preserve
the privacy invariant described there.
Citing Switchboard
A preprint is available on Zenodo with a citable DOI —
10.5281/zenodo.20836918. See
CITATION.cff for machine-readable metadata.
V. Gupta, "Switchboard: Privacy-Aware Hybrid Routing Across Heterogeneous AI
Agents," Zenodo, 2026, doi:10.5281/zenodo.20836918.
Author
Switchboard and the paper are a
solo project by Vinay Gupta
(ORCID).
License
MIT © 2026 Vinay Gupta
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found