Capability Routing

An agent that hits the edge of its sandbox shouldn't hand the job back to you. MUR derives a dispatch index — who can run what — from the permissions the kernel actually enforces, so a blocked command finds an agent that can run it.

mur agent who                     # every agent, and what it can do
mur agent who --can cargo         # who holds `cargo`, and where work can be delegated
mur agent who --skill rust        # who has a matching skill
mur agent who --can git --as pm   # evaluate dispatch permissions as another agent

Why the front-door agent holds no keys

Your concierge is the agent with the widest reach: unrestricted network, several writable repositories, always running — and it reads whatever you paste into it, including text from the web. That combination is exactly the one that shouldn't also be able to execute arbitrary code. cargo and npm run build scripts; a build script is arbitrary code.

So the concierge doesn't get those keys. A narrow specialist does — one repository, restricted egress, a short list of binaries. When the concierge needs a build, it delegates.

What the index is made of

Nothing here is declared in a separate list that someone has to maintain. A new agent appears the moment its profile exists, and it can never claim an ability the kernel would refuse.

LayerComes fromUsed to
Hardentitlements — the binaries, paths, and network the sandbox enforcesFilter. Not in the allowlist means it physically cannot run
Softrole, installed skills, modelRank and explain. A label can be stale; it never decides
Authorizationfleet_run in ~/.mur/config.yamlDecide what may be delegated to. Never inferred

The three stay separate on purpose. A description can be out of date; a kernel allowlist cannot.

Reading the output

$ mur agent who --can cargo
Agents that explicitly hold `cargo`:
  qa [running]
      exec   cargo, cargo-nextest, rustc, git
      writes /repos/app, /repos/tools
      net    Restricted
  rustsmith [running]
      role   Engineer
      exec   git, cargo, rustc
      writes /repos/app
      net    Restricted

Dispatch routes for 'mur' (fleet_run), best first:
  ready:
    builder              via rustsmith             budget $1.00
  blocked (capable, but not usable right now):
    develop-rust         via rustsmith, qa         — not authorized for this agent
      authorize: add "develop-rust" to fleet_run.fleets in ~/.mur/config.yaml

ready routes are ordered least-privileged first. Among the agents that can do the job, MUR prefers the one carrying the least unrelated power — otherwise every task drifts toward whichever agent can do everything, undoing the containment you set up elsewhere.

blocked routes are shown to you, not to the agent. A capable fleet you haven't authorized is a grant path when you read it and a target list when a compromised agent reads it. The agent only ever sees routes it may already use; the authorize line is for the human.

If an agent shows PROFILE EDITED SINCE START, its live permissions are not what its profile now says — restart it before relying on the row.

What an agent sees when it's blocked

The sandbox is compiled when an agent starts and enforced by the kernel, so there is no approval prompt for a denied binary — the exec simply fails. Instead of an opaque error, the agent gets the route:

[sandbox] `cargo` is not in agent 'mur''s spawn allowlist, so the kernel refused
to exec it. This is decided when the agent starts — there is no approval prompt
for it. DELEGATE it instead of asking the user: fleet_run(fleet="builder",
goal=<this exact command, with absolute paths>). Best first: "builder" (via
rustsmith).
To grant it here instead, the user runs: `mur agent perm allow-spawn mur cargo`
and restarts the agent.

The delegation then runs as a normal fleet job, so it inherits the guards that come with one: a budget ceiling, the mur fleet stop kill-switch, fail-closed approval, and a signed channel record of what ran.

Authorizing a route

Discovery is automatic; authorization is deliberate. A fleet becomes a valid delegation target only when you say so, in a file no agent can write:

# ~/.mur/config.yaml
fleet_run:
  agents: [mur]                 # who may delegate
  fleets: [builder, deep-research]   # where they may delegate to

A fleet also needs a positive loop.budget_usd — an agent-triggered run without a spending ceiling is refused. Both lists are empty by default: nothing is delegable until you choose it.

Granting a binary directly

Sometimes the right answer is to widen the agent rather than route around it:

mur agent perm allow-spawn <agent> <binary>
mur agent restart <agent>          # the sandbox is sealed at startup

Weigh it against what that agent already reaches. A binary that runs project-supplied code — cargo, npm, make — turns into arbitrary execution with that agent's full network and filesystem access.

See also

  • Agent CLI — chatting with an agent, and approving its tool calls
  • Capabilities — installing bundled MCP servers, skills, and program requirements