Agent Inventory
Agent Inventory is a workstation-reported inventory of slash-skills (/skill-name), workstation MCP configuration, and installed agent plugins. It discovers installed agent surfaces at session...
Agent Inventory is a workstation-reported inventory of slash-skills (/skill-name), workstation MCP configuration, and installed agent plugins. It discovers installed agent surfaces at session start, scores skills for risk, and lets you govern them, allow, warn, or block, from the dashboard without touching individual workstations.
This is distinct from MCP Activity, which covers observed mcp__server__tool calls from hook telemetry, and from MCP Gateway, which covers routed Gateway traffic, managed servers, and Gateway policy. Agent Inventory only shows surfaces reported by workstation scans.
Prerequisites
- Runtime Shield enabled: available on Free and paid plans
- AgentKeeper workstation hooks installed on each workstation. Claude Code slash-skill and plugin inventory currently comes from the Claude Code plugin, see Plugin Reference
The scanner activates automatically when the plugin is connected. If you installed AgentKeeper via the plugin, make sure ~/.agentkeeper-plugin/api_key exists, see Troubleshooting if inventory is not appearing.
How it works
1. Discovery, SessionStart scan
Every time a developer opens Claude Code, the SessionStart hook fires and runs the scanner. Two delivery paths ship the same inventory contract:
- Plugin install (default):
${CLAUDE_PLUGIN_ROOT}/scripts/session-start.sh, installed by the AgentKeeper Claude Code plugin. This is Inventory Lite: no MCP gateway binary required. - MDM install (Iru/Kandji, Jamf, Intune):
agentkeeper-mcp-gateway scan-inventoryruns as atype: "command"SessionStart hook. This path requires an AgentKeeper API key in the gateway config written by the fleet script (see Troubleshooting). - Native Linux RPM: the runtime invokes the checksum-pinned Gateway scanner as each explicit enrolled user and authenticates through the peer-verified machine broker. It uploads names, scopes, versions when available, hashes, and observation time, but removes skill previews, MCP commands, arguments, environment, headers, URLs, and raw paths.
Both emit POST /api/v1/claude-code/checkin with stable hostname and machine ID metadata. The scanner walks these skill sources:
| Location | Source label | When scanned |
|---|---|---|
~/.claude/skills/ | global | Always |
$cwd/.claude/skills/ | project | Current working directory and bounded project ancestors |
~/.claude/plugins/cache/**/skills/ | global | Enabled Claude Code plugins |
Two skill layouts are supported at the leaf:
skills/skill-name.md # flat file (older format)
skills/skill-name/SKILL.md # directory layout (current standard)
The scanner follows the plugin manifest/cache layout Claude Code writes for /plugin install, so plugin-provided skills are discovered alongside standalone skills.
For each skill found, the script collects:
- Name: derived from the filename or directory name
- Source:
globalorproject - Preview: first 500 bytes of the skill file (used for risk scoring)
- Hash: SHA-256 of the full file (for drift detection)
2. Checkin payload
The skill list is included in the POST /api/v1/claude-code/checkin payload that the SessionStart hook already sends:
{
"hostname": "dev-machine",
"session_id": "abc123...",
"cwd": "/Users/alice/project",
"installed_skills": [
{
"name": "react",
"source": "global",
"preview": "# React
...",
"hash": "a1b2c3..."
},
{
"name": "deploy",
"source": "project",
"preview": "# Deploy
...",
"hash": "d4e5f6..."
}
],
"installed_mcp_servers": [
{
"name": "github",
"type": "stdio",
"source": "project",
"platform": "claude_code"
}
],
"installed_plugins": [
{
"full_name": "notion@claude-plugins-official",
"version": "1.2.3",
"platform": "claude_code",
"source": "installed"
}
]
}
The endpoint upserts each skill into the host_skill_inventory table, keyed on (host_id, skill_name, skill_source). A skill seen on 5 workstations creates 5 rows, one per host, aggregated in the dashboard view.
3. Risk scoring
Risk is scored server-side against the 500-byte content preview. Seven pattern categories are checked:
| Flag | What it detects | Score |
|---|---|---|
credential_access | secret, token, password, api_key | +40 |
destructive_ops | rm -rf, delete all, format disk | +35 |
bash_commands | ```bash, Bash tool calls, shell_command | +30 |
code_execution | eval(), exec(), subprocess, os.system | +30 |
package_install | pip install, npm install, brew install | +25 |
network_access | curl, wget, WebFetch, https:// URLs | +20 |
file_write | Write tool calls, write file, create file | +20 |
Scores are additive, capped at 100:
| Level | Score range |
|---|---|
| Low | 0 – 25 |
| Medium | 26 – 50 |
| High | 51 – 75 |
| Critical | 76 – 100 |
Scoring runs on the preview only, the first 500 bytes. Skills with their risky instructions beyond that threshold score lower than they should. If you want accurate scoring for a long skill, ensure the relevant intent appears early in the file.
4. Dashboard view
The Agents page at /agents shows aggregated installed/configured inventory across all workstations in your organization.
Installed skills (slash-skills):
- Skill name: the slash-command name (e.g.,
/react) - Risk level: Low / Medium / High / Critical badge
- Risk flags: which pattern categories triggered (Shell Access, Credentials, etc.)
- Hosts: how many workstations have the skill installed
- Status: Active, Warn, or Blocked per your policy
- Policy controls: Allow / Warn / Block buttons per row
Click any row to open a detail panel showing the stored content preview, host list, and timestamps.
Workstation MCP configuration:
- Server name: the key from
mcpServersin Claude Code settings (e.g.,postgres,github) - Type: transport type:
stdio,HTTP, orSSE - Command: the binary that runs the server (basename only, no args or environment variables are captured)
- Source:
global(from~/.claude/settings.json) orproject(from.claude/settings.json/.mcp.json) - Hosts: how many workstations have the server configured
- First / Last seen: timestamps from the most recent workstation scans
This is proactive discovery. Servers appear the first time a workstation scan checks in, before any tool has been called. Gateway-managed servers do not appear here unless a workstation scan also reports them. For Gateway-managed servers, see MCP Gateway. For observed hook activity, see MCP Activity.
5. Governance, Block, Warn, Allow
Policy is stored in claude_code_policies and enforced on the UserPromptSubmit hook, the same hook that handles prompt injection detection.
When a developer types /skill-name at the start of a prompt, AgentKeeper:
- Detects the slash-skill invocation (regex match at prompt start)
- Checks
blocked_agent_skills, if matched, denies the invocation with:Blocked by AgentKeeper org policy: skill /name is not allowed - Checks
warn_only_agent_skills, if matched, allows the invocation but logs it as a shield event for review
Blocking happens before the skill content is loaded into Claude Code's context. The developer sees the deny message immediately.
To configure policy:
- Go to Team → Policies in the dashboard
- Use the Allow / Warn / Block controls on the Agent Inventory page, or edit the policy arrays directly
- Changes apply on the next supported runtime evaluation. Gateway-managed MCP policy can take up to 30 seconds to sync on the gateway heartbeat.
Supported skill layouts
The scanner handles both layout conventions used in the Claude Code ecosystem:
Flat file (older format):
~/.claude/skills/
my-skill.md
Directory layout (current standard, used by most published skill packages):
~/.claude/skills/
my-skill/
SKILL.md ← case-insensitive: SKILL.md or skill.md both work
handler.ts ← optional, not scanned
Symlinks at any level are followed (find -L). If you manage skills via a dotfiles manager that symlinks ~/.agents/skills/ into ~/.claude/skills/, they are discovered correctly.
FAQ
How often does the scan run? Once per Claude Code session start. Not on a schedule, not on file change. If a developer installs a new skill mid-session, it appears in the inventory on the next session start.
Does it scan project-level skills?
Yes. If the working directory at session start contains a .claude/skills/ folder and is not the home directory, those skills are scanned with source label project.
Does blocking prevent a skill from being installed?
No. Blocking prevents invocation (/skill-name at the start of a prompt). The skill files remain on the workstation. Installation happens outside Claude Code's control.
What content is sent to AgentKeeper?
The first 500 bytes of each skill file, plus a SHA-256 hash of the full file. The full skill content is never sent. The preview is stored in the dashboard for the content preview panel. Plugin-installed skills (from ~/.claude/plugins/) are included alongside standalone skills in ~/.claude/skills/.
Can I see which hosts have a specific skill? Yes. Click any skill row to open the detail panel. It shows the full hostname list, first/last seen timestamps, content preview, and SHA-256 hash. Full skill content is not uploaded.
Where do I see which MCP servers my team has installed? Use Workstation MCP configuration on Agent Inventory for servers found in workstation settings files. Use MCP Gateway for servers managed by the standalone gateway. Use MCP Activity for tool calls that were actually invoked.
Why is a skill showing a lower risk score than expected? Risk scoring runs only on the first 500 bytes of the SKILL.md. If the sensitive instructions appear later in the file, they are not scored. The SHA-256 hash is stored for drift detection, if the file changes between sessions, the hash changes, though no alert is fired automatically.
Does skill scanning affect session startup time?
Barely. The command SessionStart hook is fail-open, scans local config without network round trips per file, and posts one check-in payload. If AgentKeeper is unreachable, it returns allow and Claude Code continues.
The dashboard shows 0 skills but skills are installed on the workstation.
The most common cause is an HTTP-only SessionStart hook or a missing plugin API key at ~/.agentkeeper-plugin/api_key. HTTP SessionStart can register a workstation but cannot read local skills, MCP servers, or plugins. See Troubleshooting for a full checklist.
Troubleshooting
Skills not appearing in the dashboard
Work through these checks in order.
1. Confirm the plugin API key is present
The plugin session-start.sh script reads the API key from ~/.agentkeeper-plugin/api_key or CLAUDE_PLUGIN_DATA/api_key. If the file is missing, the script exits fail-open and no inventory is reported.
test -s ~/.agentkeeper-plugin/api_key && echo ok || echo missing
If it is missing, reconnect the plugin:
/agentkeeper:connect
Then restart Claude Code. This is the most common cause of 0 skills discovered.
2. Confirm there is inventory to scan
The scanner walks standalone skills, enabled Claude Code plugins, and MCP config files:
find -L ~/.claude/skills ~/.claude/plugins/cache -name "SKILL.md" 2>/dev/null | wc -l
python3 -m json.tool ~/.claude/settings.json >/dev/null
If this returns 0 and ~/.claude/settings.json has no mcpServers or enabledPlugins, there is no discoverable inventory on this workstation.
3. Check whether SessionStart is command-based
Runtime HTTP hooks are fine, but SessionStart should be a command hook for inventory. It should point at session-start.sh; an HTTP SessionStart hook can register a workstation but cannot read local config files.
python3 - <<'PY'
import json, os
p = os.path.expanduser("~/.claude/settings.json")
d = json.load(open(p))
for group in d.get("hooks", {}).get("SessionStart", []):
for hook in group.get("hooks", []):
print(hook.get("type"), hook.get("command") or hook.get("url"))
PY
4. Verify the scan ran
After restarting Claude Code, check whether the checkin reached the API. The workstation's Last seen timestamp on the Workstations page should update within a few seconds of session start. If it does not update, the hook is not firing or the API key is missing.
Related
- Plugin Reference, full hook configuration and install instructions
- Runtime Shield, the detection engine that enforces skill governance
- MCP Activity, monitoring for
mcp__server__toolcalls from hook telemetry - MCP Gateway, standalone routing, policy, and audit for Gateway-managed MCP traffic