jev-agent-router
September 18, 2026 ยท View on GitHub
Picks the agent that fits the task, then explains, abstains, or falls back once.
Author: Pinuts. MIT license.
Part of JEV Labs.
Stack: Python 3.10+, HTTP, MCP stdio, Docker, HTML demo.
After jev-agent serve: demo
Local, no keys
git clone https://github.com/Pinutss/jev-agent-router
cd jev-agent-router
uv sync
uv run jev-agent demo
uv run jev-agent serve
No agent and no LLM are required. JEV_PROVIDER=auto (the default) stays on the local heuristic. If JEV and a gateway are configured, they are used as the judge. Docker:
docker compose up
What the prototype does
The router chooses an agent from a registry. It explains the choice, abstains if no candidate is safe, and allows only one fallback hop.
It does not run agents and does not ship them.
Permissions come only from the registry and the caller constraints. The task, a tool, or a model cannot add them.
Cursor and Hermes plugin
This repository is an Agent Plugin. Cursor and Hermes can install it directly.
Hermes
hermes plugins install Pinutss/jev-agent-router --enable
Cursor
Install from the JEV plugins marketplace, or copy this folder to ~/.cursor/plugins/local/jev-agent-router.
One tool: agent_route. Pass task + agents. Keys stay in the process environment, not in the call.
Requires uv. JEV_PROVIDER defaults to local.
Hermes and OpenClaw
Yes, locally. The MCP process does not need JEV or a gateway:
uv run jev-agent mcp
One tool: agent_route. Pass task + agents. Keys stay in the process environment, not in the call.
Hermes (~/.hermes/config.yaml):
mcp_servers:
jev-agent:
command: uv
args: ["run", "--directory", "/path/to/jev-agent-router", "jev-agent", "mcp"]
env:
JEV_PROVIDER: local
OpenClaw (~/.openclaw/openclaw.json, or Settings > MCP > Stdio):
{
"mcp": {
"servers": {
"jev-agent": {
"command": "uv",
"args": ["run", "--directory", "/path/to/jev-agent-router", "jev-agent", "mcp"],
"env": { "JEV_PROVIDER": "local" }
}
}
}
}
Python
from jev_agent_router import AgentRouter, DEFAULT_AGENTS
result = AgentRouter(provider="local").route(
task="Fix the CORS bug in the FastAPI API",
agents=DEFAULT_AGENTS,
required_permissions=["read_code"],
scope="demo",
)
print(result.decision, result.selected.id if result.selected else result.abstain_reason)
JEV + several LLMs (optional)
If you wire the cloud later: JEV_API_KEY / JEV_BASE_URL, plus an OpenAI-compatible gateway. Keys stay in the environment, never in the HTTP body or the MCP call.
One multi-model key (OpenRouter):
JEV_PROVIDER=jev
OPENROUTER_API_KEY=sk-or-...
JEV_LLM_DEFAULT=openrouter:anthropic/claude-sonnet-4
JEV_LLM_STRATEGY=named
Several providers:
OPENROUTER_API_KEY=sk-or-...
OPENAI_API_KEY=sk-...
GROQ_API_KEY=gsk_...
JEV_LLM_PROVIDERS=openrouter,openai,groq
JEV_LLM_STRATEGY=cheapest
Or a JSON catalog via JEV_MODELS_FILE. Classic GATEWAY_* still works.
cp .env.example .env
uv run jev-agent llms
GET /v1/llms lists the public catalog (has_key, api_key_env), never the raw key. To pick the judge from the call: gateway_provider, gateway_model, llm_prefer.
JEV_PROVIDER=jev will not start if JEV or no usable LLM is configured. With auto, missing keys just keep the local heuristic.
HTTP
uv run jev-agent serve
GET /healthz, POST /v1/route. Binds 127.0.0.1. The body must not contain keys.
Local validation
uv run jev-agent benchmark
Annotated set in benchmarks/annotated_tasks.json. This is a local baseline, not a live JEV trial.
Limits
Local ranking is lexical and deterministic. Scope isolates lists, it is not auth. One fallback hop. No agent runtime. No store, no PyPI yet.
docs/vision.md is a long-term target, not the current contract.