modeio-middleware is a local AI gateway for policy, plugins, and live observability.
Put it between agent clients and their current upstream provider route to inspect traffic, enforce local policy, run external plugins, and open a built-in monitoring dashboard without replacing the clients your team already uses.
Built-in monitor with live traces, filters, before/after payload inspection, hook activity, and operator-friendly detail views.
Middleware is a protection layer for an already-working harness, not a replacement harness.
- The harness stays the owner of login, auth material, provider choice, model choice, and end-user UX.
- Middleware attaches in front of the harness's current route and adds two policy passes around model traffic: one before the upstream call and one after the upstream response.
- Plugins operate on a normalized semantic payload instead of raw provider JSON.
- If a plugin rewrites that semantic payload, middleware denormalizes the change back into the provider-native or harness-native shape before forwarding it.
- Today, supported harnesses still require explicit
middleware enable <harness>setup and controller coverage is not universal yet. The direction is to make middleware adopt the already-working harness state with less operator friction, without taking ownership of the user's auth/provider/model choices.
user prompt -> harness payload -> middleware normalize -> plugins -> denormalize -> provider
provider response -> middleware normalize -> plugins -> denormalize -> harness
For Claude Code, the same pattern applies, except the final step maps back to Claude's hook output contract instead of provider HTTP JSON.
- Add a local control layer around model traffic without replacing the harness
- Keep provider-compatible routes for chat, responses, and Anthropic messages
- See what the middleware actually did through a built-in browser dashboard
- Support Claude Code with a native hook connector
- Extend behavior with external
stdio-jsonrpcplugins instead of patching core code - Run locally for demos, operator workflows, safety experiments, and team rollouts
Provider-preserving gateway: route supported clients through chat, responses, and Anthropic message surfaces while preserving harness-owned provider selectionBuilt-in observability: inspect live traces, before/after payloads, block events, errors, and hook activity in the browserPlugin platform: author, validate, and conformance-test external plugins against a normalized semantic payload contractLocal-first operations: keep policy logic and monitoring close to where the agents run
Middleware expects an already-working harness and reuses that harness's current auth and provider route when possible. It does not log you in, choose a different provider for you, choose a different model for you, or fall back to a different auth path if your current harness state is unsupported.
This branch establishes the support boundary for the new middleware controller command.
| Harness | middleware inspect |
middleware enable / disable |
Works today when... | Not yet |
|---|---|---|---|---|
Codex CLI |
✅ Yes | ❌ No | Runtime support exists outside the new controller lifecycle | Controller-managed Codex attach/detach |
Claude Code |
✅ Yes | ✅ Yes | Claude is already logged in and working normally | None in the current controller scope |
OpenCode |
✅ Yes | The current selected provider is a normal API-key or proxy-style provider that can be rerouted, such as the built-in opencode provider with API-key auth |
Built-in openai with ChatGPT OAuth, built-in anthropic with subscription OAuth, Anthropic-style provider paths |
|
OpenClaw |
✅ Yes | The current selected provider is a normal OpenAI-compatible or Anthropic-compatible provider | OpenClaw's built-in Codex or ChatGPT-style provider path |
Compatibility expansion is intentionally paused at this matrix for now.
| Client | Status |
|---|---|
Codex CLI |
|
Claude Code |
✅ Supported |
OpenCode |
|
OpenClaw |
More detail:
Codex CLI: runtime support exists, but the newmiddlewarecontroller does not manage Codex yet.Claude Code: works with Claude's normal native auth.OpenCode: works today for normal API-key or proxy-style providers that use a standard provider API endpoint.OpenCode: does not work yet for built-inopenaiwith ChatGPT OAuth.OpenCode: does not work yet for built-inanthropicwith subscription OAuth.OpenClaw: works today for normal OpenAI-compatible and Anthropic-compatible providers.OpenClaw: does not work yet for OpenClaw's built-in Codex or ChatGPT-style provider path.
Deferred compatibility:
- Compatibility work is intentionally paused at the matrix above for now.
- The next planned OpenCode items are built-in
openaiwith ChatGPT OAuth, built-inanthropicwith subscription OAuth, and Anthropic-compatible provider paths such aszenmux. - The next planned OpenClaw item is the built-in Codex or ChatGPT-style provider path.
Traffic routes:
POST /v1/chat/completionsPOST /v1/responsesPOST /v1/messagesPOST /connectors/claude/hooks
Monitoring and ops routes:
GET /healthzGET /modeio/dashboardGET /modeio/api/v1/eventsGET /modeio/api/v1/events/{request_id}GET /modeio/api/v1/statsGET /modeio/api/v1/events/live
Admin routes:
GET /modeio/admin/v1/pluginsPUT /modeio/admin/v1/profiles/{profile}/plugins
From GitHub:
python -m pip install git+https://github.com/mode-io/mode-io-middlewareFrom a local checkout:
python -m pip install .- Inspect the harnesses you want to use:
middleware inspect opencode --json
middleware inspect openclaw --json
middleware inspect claude --json- Enable supported harnesses. Today this attach step is explicit: middleware inspects the exact current harness-selected state first, and it fails clearly if that state is unsupported:
middleware enable opencode
middleware enable openclaw
middleware enable claude- Check status and open the dashboard:
middleware status --json
curl -s http://127.0.0.1:8787/healthz
open http://127.0.0.1:8787/modeio/dashboard- Disable one harness or all harnesses when you are done:
middleware disable openclaw
middleware disable --allSource-checkout maintainers should prefer the repo-local wrapper instead of the installed entrypoint:
python scripts/middleware.py inspect opencode --json
python scripts/middleware.py enable opencodeThat flow keeps the controller and runtime state under the configured ModeIO runtime home instead of asking users to compose legacy setup and gateway commands manually.
- Send one request through the middleware:
curl -i http://127.0.0.1:8787/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "hello"}
],
"modeio": {
"profile": "dev"
}
}'The dashboard will update as traces arrive. If there is no live traffic yet, it shows example traces so the UI is still explorable during onboarding and verification.
The dashboard is served directly by the gateway at http://127.0.0.1:8787/modeio/dashboard.
It is designed for day-to-day operators and troubleshooting workflows. Out of the box you can:
- watch the live request stream in a browser
- inspect request and response bodies before and after middleware processing
- see block, error, and latency stats at a glance
- review hook and plugin activity per request
- filter traces by status, source, and endpoint
- switch between English and Chinese, plus day and night themes
If you want raw data or to wire your own tooling around it, use the versioned monitoring APIs under /modeio/api/v1/*.
Plugin inventory and mutation live under /modeio/admin/v1/*. The gateway keeps admin routes on loopback by default; binding a non-loopback host now requires --allow-remote-admin.
For frontend editing, npm run dev inside dashboard/ serves the Vite app on http://127.0.0.1:4173/modeio/dashboard/ and proxies /modeio/api/v1/*, /modeio/admin/v1/*, /v1, /connectors/*, and /healthz to 127.0.0.1:8787 by default. That means the canonical gateway still owns the live middleware state while the dev server handles hot-reload UI work.
Scaffold, validate, and conformance-check a public external plugin:
modeio-middleware-new-plugin my-policy
modeio-middleware-validate-plugin ./plugins_external/my_policy/manifest.json
modeio-middleware-plugin-conformance \
./plugins_external/my_policy/manifest.json \
python3 ./plugins_external/my_policy/plugin.py- Operator guide:
QUICKSTART.md - Architecture:
ARCHITECTURE.md - External plugin protocol:
MODEIO_PLUGIN_PROTOCOL.md - Contributor workflow:
CONTRIBUTING.md
Full repo validation:
python -m unittest discover tests -p 'test_*.py'
./scripts/release_check.shLive operator smoke is owned by the external middleware-api-smoke skill in the local workflow repo, not this repo.
Use middleware inspect <harness> --json locally when you only need machine-readable readiness for a specific harness:
middleware inspect opencode --json
middleware inspect openclaw --json
middleware inspect claude --json