Web app
Agents
The register of every agent in the workspace, and one page per agent for deciding whether it is safe to leave running as it is.
In the web app Agents
When to use this
- To approve or reject agents a scan proposed.
- To find agents sending traffic that nobody registered, or that nobody owns.
- To stop an agent now, and to see what policy actually applies to it.
The agents list
/app/agents, built from GET /api/agents and GET /api/discovery/shadow. Top to bottom:
- A strip of counts: agents, registered, unregistered, without an owner, tools, lineage edges.
- Pending review: draft agents proposed by a repository or hosted-API scan, with Approve and Reject. A draft is inert: approving makes it active (
POST /api/agents/{id}/approve), rejecting discards it. Both are written to the audit chain. - Unregistered agents: slugs seen in traffic that were never registered, with environment, call count, models, framework and first seen. These are shadow agents; each also appears in the attention queue as high severity.
- All agents: name and slug, purpose, owner (or an unowned — assign link), environment, risk tier, framework, and last seen ("—" means no traffic yet, not a fault). Tags mark
unregistered,draftandsample data. - Agents whose slug looks like a test, spec, script, example, demo or fixture are folded into a collapsed "look like tests, scripts or examples" list, so a scan of a repository's test directory does not bury production agents.
- What an agent is allowed to do: a reminder that what an agent was seen calling and what it is permitted to call are separate. Capability grants are default deny and have no screen; make them with agentfox permit grant (the explainer in the app shows the older command name).
Registering an agent by hand
+ Register an agent manually is for an agent that does not live in a repository you can connect. Fields: Slug (unique, lowercase), Name, Purpose, Owner email, Risk tier (minimal, limited, high, prohibited; default limited). It posts to POST /api/agents and the agent is registered at once. An agent that calls the gateway before anyone registers it shows up as unregistered instead; registering the same slug claims it.
The CLI reads the same register:
agentfox agents listagent env risk registered owner framework
127-0-0-1 production limited SHADOW unowned hosted_api
hr-screening production limited yes unowned crewai
marketing-copy… production limited SHADOW unowned —
payments-ops production high yes marcus@examp… claude-agent-s…
research-bot production limited yes dana@example… —
support-triage production limited yes priya@exampl… langgraph
6 agents · 1 shadow · 3 unowned · 11 lineage edgesresearch-bot was registered from the web app a moment earlier. 127-0-0-1 is a draft from a hosted-API scan; the CLI and the attention queue both count a draft as unregistered until it is approved.
The agent page
In the web app Agents → an agent
/app/agents/<slug>. Above the tabs, always visible: the name, a sample data tag for seeded agents, a red banner if the agent is quarantined or killed (with who did it, when and why), and a strip of counts: traces, decisions, blocked, escalated, hand-offs and blast radius. Each count links to the filtered list behind it. The page is built from GET /api/agents/{slug}/posture, /lineage, /api/traces?agent=, /api/risk/classify/{slug}, /api/answerability/boundaries, /api/agent-controls and /api/policies/effective?agent=.
Activity tab
- Open findings for this agent: severity, type, title, each linking to the finding.
- Recent traces: the last 15, with verdict, model, intent and time. If there are none but the agent has hand-offs, it says so: hand-offs are logged apart from traced calls.
- Reliability objectives: any SLOs declared for this agent on Evaluation, with attainment and error budget.
What it may do tab
Effective policy is the policy actually in force for this agent, composed from every level that reaches it, with where each rule came from. The header line gives the mode, the default effect and the layers applied. Each row is a rule: what it checks, its effect, its source (for example org:*), and the layer's compose setting (in the column headed "mode": extend, restrict or override). A custom tag marks a rule from a narrower level than the org default, and loosened marks a rule a narrower level relaxed. Rules rejected during composition are listed underneath.
+ Customize for this agent opens a new policy called <slug>-overrides, pre-scoped to the agent level. See the policy editor.
agentfox policy effective --agent payments-opseffective policy in development — default allow
layers:
org:*(extend) baseline observe
org:*(extend) eu-ai-act-high-risk observe
org:*(extend) tool-containment enforce
rule effect mode from overrides
access.undeclared_table escalate enforce org:* —
access.unscoped_table block enforce org:* —
…Knowledge boundary
On the same tab. A knowledge boundary is what the agent may answer from; without one, nothing stops it inventing an answer to a question it has no data for. Fields:
- Systems of record it may answer from (comma-separated)
- Coverage (months of history) and Freshness (hours)
- Entity types it knows about (comma-separated)
- Topics it must refuse even if it has data (comma-separated)
- Question types it may answer: fact, aggregate, prediction, opinion, procedure
Declare boundary (or Update boundary) sends PUT /api/answerability/boundary. The form has no mode field: a boundary saved from the web app is in observe, so refusals are recorded, not applied. Enforce it from the CLI once the dry runs look right.
agentfox declare boundary research-bot --systems wiki,ticket-history --coverage-months 12 --answerable fact,procedure --out-of-scope "legal advice,medical diagnosis"
agentfox test boundary research-bot "Can you give me legal advice about this contract?"✓ boundary declared for research-bot
answerable: fact, procedure
coverage: last 12 months
observe mode — refusals are recorded, not applied. Re-run with --mode enforce when the dry runs
look right.
╭─ would abstain — out_of_domain ───────────────────────────────────────────────╮
│ That topic is outside what this agent is set up to cover (legal advice). │
╰───────────────────────────────────────────────────────────────────────────────╯
recorded only (observe mode)Registration tab
- Purpose, editable inline (tagged
not setwhen empty). Saves withPATCH /api/agents/{slug}. - Agent map: everything this agent reached in observed traffic within two hops, drawn as a circle, with the blast radius on it. An edge that was observed but never declared is drawn as such; that gap is registry drift.
- Registration: owner (with an email and optional team field and Assign owner / Update), team, environment, risk tier, framework, registered, declared models, declared tools, data classes, last seen.
- Observed lineage: the same edges as a table (from, relation, to, times seen), with each tool's impact tier (read, write, high_impact, irreversible) and, for MCP tools, the server's trust level. Declared models and tools are what someone typed in; observed lineage is what happened. A mismatch is worth reading.
- Proposed risk classification: an EU AI Act class proposed from the purpose text and observed behaviour, with the signals behind it (for example "can invoke high-impact or irreversible tools"). It is advisory and says it requires human confirmation. When it differs from the recorded tier, Accept — set risk tier to … writes it; leaving it is rejecting it. The formal record (class, residual risk, signer) is on Compliance → Risk register.
- Kill switch, below.
Kill switch, quarantine and resume
The current state is shown as a tag: active, quarantined or killed. Any state other than active refuses every governed call from the agent immediately, and each change goes to the audit chain.
- Quarantine (with an optional reason) is the reversible "stop while I investigate". Allowed for owner, admin, security and developer.
- Kill is the incident action, with no reason field in the web app. It needs owner, admin or security.
- Resume (optional reason) returns the agent to active. It needs the same roles as Kill: restarting something stopped for cause is not a lesser decision.
The form posts to the web app's /api/agents/<slug>/control, which calls POST /api/agents/{slug}/quarantine, /kill or /resume. The CLI does the same:
agentfox agents quarantine research-bot --reason "checking an odd tool call"
agentfox agents resume research-bot --reason "incident closed"research-bot killed → active incident closed(That resume followed a kill made in the web app.)
Owners and shadow agents
An agent with no owner shows unowned — assign on the list and an unowned tag on its Registration tab; assign one there. An unregistered agent is one the gateway saw in traffic under a slug nobody registered. It raises a high-severity attention item ("'slug' is running and was never registered") and a finding. Register it with the same slug, give it an owner, then resolve the finding.
Common tasks
| You want to | Run |
|---|---|
| List agents, owners and shadow agents | agentfox agents list |
| See what one agent reached | agentfox agents lineage payments-ops |
| Stop an agent while you investigate | agentfox agents quarantine research-bot --reason "…" |
| Stop an agent now | agentfox agents kill research-bot --reason "…" |
| Bring it back | agentfox agents resume research-bot --reason "…" |
| Show the policy in force for it | agentfox policy effective --agent payments-ops |
| Declare what it may answer, in enforce | agentfox declare boundary research-bot --systems wiki --mode enforce |
| Let it call a tool | agentfox permit grant research-bot web.fetch --yes |
What can go wrong
- Kill or Resume shows an error banner. Your role is developer; those need owner, admin or security. Quarantine is still available to you.
- "no draft agent with that id" on Approve or Reject. Someone already decided it; reload.
- Tools count is high but nothing is allowed. Tools are declared; grants are separate and default deny. See Contain tool calls.
- Blast radius reads 0. Lineage is built from observed traffic only; an agent with no traces has none.
Limits
- No screen for capability grants or tool declarations.
- Boundaries saved from the web app are always observe mode.
- The risk classification is a heuristic over purpose text and behaviour, not a legal determination.