Safe execution lanes for AI agents.
Deterministic routing, guardrails and run receipts for coding agents that talk to more than one model provider.
A lane is this repository's central abstraction: the resolved path a piece of work takes — which executor runs it, at which effort, with which tools, under which approval scope. Choosing a lane, refusing an unsafe one, and recording what actually ran on it is the whole of what these modules do.
Every module here is a pure function over an explicit input. Nothing in this repository calls a model, writes a file, or opens a socket — except one provider adapter, which is included precisely because its network behaviour is the thing worth reading.
Name checked 2026-08-18: free on the npm registry; no GitHub repository of the same name above 9 stars; no company or product found under this name. No formal trademark search (INPI/EUIPO/USPTO) was performed.
An agent that can reach several providers, several efforts and several tools has to answer four questions before it does anything:
- Which lane should run this — local, or a model?
- Which tools may it touch, and which are merely detected rather than proven?
- Is this loop making progress, or repeating itself?
- What actually happened — which model answered, at which effort?
These modules answer those four questions, and they are deliberately separable from whatever agent is asking.
| Module | What it decides |
|---|---|
router/mission-classifier |
Execution lane and complexity, from the request text alone. Vendor-neutral by construction: it never names a model. Recognises English and French phrasing. |
router/model-registry |
Whether a lane is actually executable. DETECTED is not WORKING_END_TO_END. |
router/provider-effort-registry |
Maps a provider-neutral effort to the exact label a given provider surface accepts. |
router/executor-resolver |
Maps a requested operation to a bounded executor, its network requirement, its write requirement and its approval scope — or refuses it. |
router/tool-selector |
Narrows a tool catalogue to a short, explained list, and excludes unproven tools with a reason code. |
router/loop-guard |
One verdict per iteration — continue, compact, or stop — from identical-call tracking, ping-pong detection and a context threshold. |
router/model-policy |
The run-mode surface. |
core/phishing-guard |
Host + path allowlist per MCP connector. A connector URL that does not match its policy is refused before any request. |
core/mcp-registry |
Parses connector registry output into typed entries. |
core/model-run-receipt |
Records requested versus observed model and effort, separately, so a run proves what ran and not what was asked for. |
core/redaction |
Inline credential redaction. |
provider-glm/glm-provider |
A provider readiness probe pinned to a single HTTPS origin, rejecting embedded credentials, query strings and fragments in the base URL. |
Detection is not availability. ConnectionStatus separates DISCOVERED,
CONFIGURED, DETECTED and WORKING_END_TO_END. A lane is only usable once a
bounded real task has completed through it. Finding a binary on the machine
proves nothing.
Requested is not observed. ModelRunReceipt stores requestedModel and
observedModels in different fields, and identityMatched is nullable, because
"we never observed it" is a different state from "we observed a mismatch". Same
for effort. A receipt that cannot tell those apart is not evidence.
npm install
npm run validate # typecheck + tests65 tests, no runtime dependencies.
- Not an agent. There is no loop, no planner, no execution engine.
- Not a framework. These are functions; wire them yourself.
- Not benchmarked. Nothing here has been measured against an alternative.
- Not a security product.
phishing-guardis an allowlist andredactionis pattern matching. Neither is a classifier, and neither should be trusted as one. - Not complete. This is an extraction from a larger private workbench. Mission compilation, action execution and persistence were left behind on purpose, because they encode workspace-specific policy rather than reusable behaviour.
Two modules were written after reading prior art. Both were checked line by line against the upstream sources before this repository was prepared for publication.
router/loop-guard — prior art:
open-jarvis/OpenJarvis
src/openjarvis/agents/loop_guard.py (Apache-2.0).
The comparison found a real problem, which was fixed rather than described away.
An earlier revision of this module contained a cycle detector that was a direct
statement-for-statement translation of that project's _detect_ping_pong: the
same fixed (2, 3) period pair, the same tail[-period*2:] slice, the same
pattern[i % period] comparison. That is a derivative work, and shipping it
under MIT with only a source comment would not have satisfied Apache-2.0.
It was rewritten. shortestTrailingCycle scans every period that fits the
inspection window rather than a hard-coded pair, compares two adjacent slices
instead of indexing a pattern modulo its length, returns the cycle length rather
than a boolean, and excludes period 1 by design. Three tests cover behaviour the
original could not express, including four-step cycle detection.
No code in this repository is derived from an Apache-2.0 source, and no Apache-2.0 obligation attaches to it. The three-signal idea — identical calls, cyclical sequences, context pressure — is a common pattern, and OpenJarvis is credited in the module header as the published example that informed it.
router/tool-selector — prior art:
rezaulhreza/jarvis
jarvis/core/intent.py and jarvis/core/tools.py (MIT).
The comparison found nothing shared. Upstream maps an enum to a fixed list via an
INTENT_TOOLS dictionary. This module scores tools (category match, keyword
hits), gates them on proven availability, caps the result at four, and returns an
exclusion reason code for every tool it drops. No structure, code or data is
common to the two. The module header, written before this check, credits the
upstream more generously than the comparison warrants; it is left as written.
MIT. See LICENSE.