Open-source security for AI coding agents.
Agentmetry records tool events reported by supported agent hooks and wrapped stdio MCP servers. It flags risky sequences, can block calls at supported hooks when you enable blocking, and keeps a verifiable audit trail you can forward to your SIEM.
Quick start · Docs · Schema · Issues · Contributing
Ninety seconds, recorded from real agentmetry demo and agentmetry benchmark output on 0.9.4.
Watch it on agentmetry.ai.
Public alpha. Capture, sequence detection, and SIEM forwarding work. APIs and hook payloads can still change.
Security engineers and developers who want a record of what a coding agent did at the tool boundary: which agent, which session, which call, in what order.
It is a sensor. The open-source package is not a console. agentmetry dashboard reads the trail on this machine. Fleet questions are answered in the SIEM you forward to. A hosted fleet console is allowed for Agentmetry Enterprise. It exists as a prototype that runs on localhost and is not offered as a hosted service. The sensor never needs that service to record or to forward. See open-core split.
It does not see an unmanaged browser chat, an IDE with hooks off, or an MCP server reached over HTTP instead of the stdio proxy. That is CASB or gateway territory.
Python 3.11 or newer. No server and no config file.
pip install agentmetry && agentmetry demo
agentmetry doctor
agentmetry benchmarkTo see the demo without installing anything, uvx agentmetry demo (with
uv) or pipx run agentmetry demo runs it from a
throwaway environment.
agentmetry demo replays a session through the real ingest path into a temp directory it deletes: a private-key read, a cloud key that DLP matches without storing the value, then a URL fetch. The sequence fires one critical credential-exfil. It then edits that finding and shows verify fail, re-hashes the file the way someone with the whole machine could, and shows verify pass again with a different chain head. That last step is what agentmetry anchor is for. Nothing is kept and nothing leaves the machine.
agentmetry doctor checks the install and exits 0 when nothing is broken. Warnings are expected on a fresh install: no trail yet, the orchestrator is not running, autostart is not registered.
agentmetry benchmark replays the detection corpus through the real rule engine and exits non-zero on a miss or a false positive. The figures it prints are below.
To check what the agents on this machine are about to depend on, before anything runs:
agentmetry scan # MCP servers your agents launch, and AGENTS.md / CLAUDE.md files left in Downloads or on the Desktop
agentmetry scan ~/.claude/skills # skills, rules and CLAUDE.md files: text that instructs the model instead of describing a tool
agentmetry scan npm:NAME # one package name, before you install itIt reads files and nothing else: it never starts a server or fetches a package. It exits 1 on a finding, and "no findings" means these checks found nothing, never that something is safe. The checks and their limits are in docs/scanner.md.
agentmetry demo --scenario hf replays the HF July 2026 patterns (credential-read-then-cloud-api and remote-staging-then-execute). --scenario all runs both.
An installed package keeps its trail, indexes, and API token in the user data directory: %LOCALAPPDATA%\Agentmetry on Windows, ~/.local/share/agentmetry on Linux, ~/Library/Application Support/Agentmetry on macOS. A git checkout keeps apps/orchestrator/data. AGENTMETRY_DATA_DIR overrides both. doctor prints the directory in use.
To record a real agent, then look at it:
agentmetry hooks install
agentmetry start
agentmetry dashboardagentmetry dashboard opens a one-time sign-in link. The browser does not hold the API token.
| Surface | What is recorded | How you turn it on |
|---|---|---|
| Claude Code | Tool calls and inferred approvals via hooks. The record-only agentmetry otel path captures tool results and observed human approvals after the fact. Use one path to avoid duplicate tool events. |
agentmetry hooks install, or agentmetry otel |
| Cursor | Tool calls and inferred approvals | agentmetry hooks install |
| Codex | Same. Codex skips untrusted hooks until its /hooks prompt is approved. |
agentmetry hooks install |
| Qwen, Kimi, Qoder, CodeBuddy | Tool calls and inferred approvals | agentmetry hooks install |
| GitHub Copilot (CLI and VS Code agent mode) | Tool calls, with deny. Deny has been run live on the CLI; VS Code's agent host has not yet been (#316). One hooks file in ~/.copilot/hooks/ serves both. VS Code hooks are a preview feature an organisation can turn off. |
agentmetry hooks install, or --managed for the CLI's policy hooks |
| Antigravity | Tool calls and inferred approvals | scripts/install_antigravity_hooks.ps1 on Windows. hooks install and scripts/install.sh do not write these. |
| MCP servers | Every stdio tools/call, plus a tools/list fingerprint |
agentmetry mcp-proxy -- <server command> |
| CrewAI, OpenSRE | Framework adapters | adapters/crewai, adapters/opensre |
| Microsoft Agent Governance Toolkit files | Import after the file's own chain verifies | agentmetry import-agt |
Any agent that acts on your machine can be recorded through the ingest API, not only coding agents. Agent coverage says what is supported, what is possible and what is impossible, for local agents such as OpenClaw and Hermes, frameworks such as LangGraph, and hosted agents such as the Grok app. The detections are written for agents that act on an endpoint.
| OS | What is tested |
|---|---|
| Windows | CI on windows-latest, plus the hooks-windows job. PyPI classifier Operating System :: Microsoft :: Windows. |
| Linux | CI on ubuntu-latest, plus the install-linux job. PyPI classifier Operating System :: POSIX :: Linux. |
| macOS | The full test suite runs on macos-latest in CI since 2026-10-10, as a non-required check. That covers the per-user data directory, the launchd agent (agentmetry install) and the managed-hook paths. No hook has been exercised against a live agent on a Mac, and PyPI does not list a macOS classifier yet. |
CI is .github/workflows/ci.yml. The test matrix is ubuntu-latest, windows-latest and macos-latest. The macOS leg is not yet a required check.
- Sequence detections. Fourteen published rules, plus one experimental rule (
autonomous-unapproved-write) that stays registered and is not part of the published set: no IDE capture surface produces the signal it reads, and it is not exported to Sigma. Rules match ordered steps inside a session.credential-exfilis credential access, then network egress. Reversed, it does not fire. The list is docs/detection-rules.md. - A check before anything runs.
agentmetry scanreads the MCP configs, skills and rules files an agent will load and reports typosquatted package names and text that steers the model: overriding instructions, hiding things from the user, reaching for credential files, exfiltration, shadowing other tools. The MCP proxy runs the same text check on everytools/listit relays and records the counts per category on the trail, never the text. - MITRE ATT&CK tags on tool calls the mapper recognises (
agentmetry/core/audit/mitre.py). A call it does not recognise carries no tag. - MITRE ATLAS labels on the subset where ATLAS says something ATT&CK cannot (
agentmetry/core/audit/atlas.py, content release 2026.07). Five techniques are emitted: indirect prompt injection (AML.T0051.001), agent-tool credential harvesting (AML.T0098), exfiltration via tool invocation (AML.T0086), destruction via tool invocation (AML.T0101), and MCP supply-chain rug pull (AML.T0109).AML.T0050andAML.T0053are deliberately not emitted. - Canonical events, schema 1.2.0. SHA-256 argument hashes by default. The secret value is not stored. Schema: docs/agentmetry-event-schema.md.
- SIEM and webhook export. File (default, hash-chained JSONL), generic webhook, Elastic ECS, Splunk HEC, Google SecOps UDM, Microsoft Sentinel (not yet run against a live workspace), and CloudEvents v1.0 as a webhook format. Loki is Grafana Alloy tailing the local file, not a native sink. The same list is in the table below.
- Claude Code OpenTelemetry ingest.
agentmetry otelis a loopback OTLP/HTTP JSON receiver. It shipped in 0.9.0. It does not export Agentmetry's own events as OTLP. That direction is not built. - Evidence.
agentmetry verify --trailchecks the hash chain.agentmetry anchorrecords a checkpoint; it protects against a rewrite of the whole trail only once a copy lives somewhere this host cannot write, because the default anchor file is local (anchoring).agentmetry proveis an inclusion proof for one event.agentmetry export --evidencewrites an evidence pack.agentmetry export --compliance-digestis a period summary. - A removed hook is loud. While
agentmetry startruns, it sends a heartbeat every 300 seconds (AGENTMETRY_HEARTBEAT_SECONDS) whether or not anyone is coding, listing which agents on the machine are hooked (heartbeat.hooks). A SIEM can alert on two things: the heartbeat stops, which means the recorder was stopped or the machine is off, or it arrives withaction.outcome: degraded, which means the recorder is running but an agent on the machine is not being recorded, the state a deleted hooks file produces. Both are in the Sigma pack: recorder silent and recorder degraded. This makes bypass visible, not impossible: an agent run that skips hooks still configured on disk sends no event, and anyone who can stop the recorder can also forge a beat.
These are the numbers from commands, not from a slide.
cases 57 (26 attack, 31 benign)
rules covered 13
expected firings 26
detected 26
missed 0
false positives 0
That block is what agentmetry benchmark printed from the PyPI 0.9.4 package and from this tree. "Rules covered 13" counts rule ids named in corpus expectations. Twelve of those are published rules. The thirteenth is the experimental rule. Two published rules have no corpus case: host-subagent-swarm-burst and off-hours-activity. They are named in apps/orchestrator/tools/generate_sigma_pack.py so the Sigma pack still has them.
2157 tests collected (pytest --collect-only -q from apps/orchestrator). The
0.10.6 release PR's CI run
on Python 3.12 reported 2089 passed and 19 skipped on Linux and macOS,
2102 passed and 6 skipped on Windows, and 82.13% line coverage on Linux
(pytest -q --cov=agentmetry --cov-report=term). CI fails the coverage job under 78%.
The corpus and the expectations live in apps/orchestrator/agentmetry/core/audit/detection/corpus/.
Not a sandbox. The default is detect and record. DLP and tool policy can deny a call at the hook, before it runs, when set to block. That is off by default (log). An after-the-fact hook cannot deny a tool that already ran.
Not a CASB. Hooks are cooperative. No event is not evidence that nothing happened. A hook removed from an agent's config shows up in the heartbeat (above); an agent session that skips hooks still configured does not.
Not a console. There is no central enforcement and no central triage in this package. Policy is per machine. See fleet via your SIEM.
Approvals are mostly inferred. A tool that runs after a prompt is marked inferred:* and is not a record of a click. Claude Code's OTel stream is the exception: a person's yes is stored as an observed approval (otel_decision:*).
The chain is not attribution. Verification catches in-place edits, inserted or reordered lines, and forged appends. Anyone who can rewrite the file and the sidecar can produce a trail that verifies. A checkpoint from agentmetry anchor, kept somewhere that person cannot also rewrite, is the check for that. The chain also does not prove who wrote a line.
What a token holder can and cannot claim is narrower than it sounds. ExternalIngestBody in agentmetry/api/routes/audit.py has no host_id or fleet_id field, and agentmetry/core/audit/identity.py stamps each event with the receiving orchestrator's hostname and its configured fleet_id. A client cannot claim to be another machine. It can claim another user: the hook reports the account that ran the agent, and initiator.operator_source says whether that id came from the caller (hook_os, hook_configured, client) or from the orchestrator. Anyone holding the API token can inject events that arrive stamped as the machine that accepted them.
MITRE coverage is narrow on purpose. It is not an official mapping and has not been through a MITRE evaluation.
Microsoft Sentinel has a sink and KQL docs. It has not yet run against a live workspace.
The JSONL trail is the system of record. Network sinks tail it from a cursor and retry. The cursor moves only after a batch is accepted. GET /api/v1/audit/status reports each sink.
| Sink | Configuration |
|---|---|
| File (default) | AGENTMETRY_AUDIT_SINK=file |
| Webhook | AGENTMETRY_AUDIT_SINK=webhook and AGENTMETRY_AUDIT_WEBHOOK_URL |
| Enterprise batch webhook | webhook sink plus AGENTMETRY_AUDIT_WEBHOOK_FORMAT=batch ({"events": [...]}) |
| CloudEvents | webhook sink plus AGENTMETRY_AUDIT_WEBHOOK_FORMAT=cloudevents |
| Elastic ECS | AGENTMETRY_AUDIT_SINK=elastic |
| Splunk HEC | AGENTMETRY_AUDIT_SINK=splunk |
| Google SecOps | AGENTMETRY_AUDIT_SINK=chronicle |
| Microsoft Sentinel | AGENTMETRY_AUDIT_SINK=sentinel. Setup. Not yet run against a live workspace. |
| Loki | Not a sink mode. Grafana Alloy tails the JSONL. Homelab notes. |
| AiSOC | Not a sink mode. The webhook sink with the default canonical format, pointed at an AiSOC inbox URL minted with its Agentmetry template. Only canonical works: the template does not unwrap the batch or cloudevents envelopes. Built and maintained by AiSOC: connector docs. Run live end to end on 2026-11-02 (AiSOC v21, Agentmetry 0.10.4): detections arrived as critical alerts with their ATT&CK techniques, and tool calls raised none. |
| Tenzir | Not a sink mode. The agentmetry package in the Tenzir Library maps events to OCSF 1.9.0 from the trail file or from the webhook sink (accept_http). Built in tenzir/library#211, reviewed and merged by Tenzir. Its tests pass on recorded events; a live webhook into accept_http has not been run. |
Guides: docs/integrations/. Detections are also a Sigma pack (23 rules): 15 generated files for the 14 published sequence rules (encoded-command-download is two severities), plus 8 rules for recorder health and triage.
agentmetry otel receives Claude Code's stream. It does not replace hooks for policy. Mapped today: tool_result becomes tool_called or tool_failed (arguments only if OTEL_LOG_TOOL_DETAILS=1); a person's yes on tool_decision becomes an observed approval. Other documented types are counted, not dropped silently. Prompts are not forwarded. --print-env and --print-mapping print the rest.
Under a minute and a half: one detection, from the alert to the decision. Captured on a synthetic sample trail.
Watch it on agentmetry.ai.
agentmetry dashboard signs a browser in to the console for this machine. The Overview separates alerts (the week's detections, grouped by rule, with how many are undecided) from risks (configuration that lets an agent act unseen, such as a configured agent that has sent nothing). A detection opens as an investigation with five views: details, the session's activity as a table, a tree and a graph, and an events timeline, sharing one selection, with the calls the detection cites marked in each. This machine shows which agents are recorded.
From a clone, python scripts/demo_dashboard.py seeds a local dashboard. Build apps/dashboard first (npm install && npm run build). The script says so if the export is missing.
agentmetry from pip install agentmetry. In a clone, use the orchestrator venv.
| Command | What it does |
|---|---|
agentmetry demo |
Replay an attack session in-process, then tamper with the trail and show verify catch it. --scenario hf or --scenario all. Nothing is kept. |
agentmetry doctor |
Preflight. A trail over 32 MB has its newest 5,000 records checked; --full walks the whole chain. --fix creates a portable drivers.json in a checkout. |
agentmetry benchmark |
Replay the detection corpus and score the rules. |
agentmetry start / agentmetry stop / agentmetry status |
Run the orchestrator detached, stop it, or check health. |
agentmetry serve |
Foreground process that autostart registers. |
agentmetry install / agentmetry uninstall |
Start at logon and restart on failure. Task Scheduler on Windows, a systemd user unit on Linux, a launch agent on macOS. |
agentmetry hooks install |
Write hook configs for supported agents found on the machine. agentmetry hooks status exits 0, 1, or 2. |
agentmetry hook |
Forward one IDE hook event. Hook configs should call agentmetry-hook instead. |
agentmetry otel |
Receive Claude Code's OpenTelemetry stream. No hooks required. |
agentmetry mcp-proxy |
Wrap a stdio MCP server command. |
agentmetry mcp |
List MCP servers configured for agents on this machine. |
agentmetry scan |
Check what an agent is about to depend on, before it runs. With no argument, the MCP servers configured on this machine (typosquatted launch packages and unpinned fetch-and-run entries) and the instruction files an agent would load from Downloads, the Desktop or the home folder. Given a file or folder (skills, rules, a saved tools/list), text that instructs the model: overriding instructions, hiding things from the user, reaching for credential files, exfiltration, shadowing other tools. An AGENTS.md, CLAUDE.md or similar file is also checked for installing a named package, for naming the agent's own endpoint or config, and for sitting in Downloads or on the Desktop outside any repository. npm:NAME or pypi:NAME checks one package name. Exits 1 on a finding, 2 when nothing could be read; it never says "safe". The MCP proxy runs the same text check on every tools/list and records the counts on the trail. |
agentmetry posture |
Report agent settings that skip approval prompts or turn hooks off: Claude Code bypass mode, Codex with no approvals or sandbox, VS Code auto-approve. --strict exits 1 on a high finding. AGENTMETRY_POSTURE=1 also sends it to the SIEM. |
agentmetry dashboard |
Open the dashboard signed in. |
agentmetry cloud cursor / cloud claude |
Poll a vendor API once (Cursor Cloud Agents; Claude Compliance, which covers Claude Code CLI and desktop sessions and Cowork but not Claude Code on the web) and record what it exposes through the same ingest as the hooks. Claude tool calls are imported as requested calls, recorded as success whatever their result, and each poll reads one page. Keys from CURSOR_API_KEY / ANTHROPIC_COMPLIANCE_KEY. |
agentmetry logs |
Tail the orchestrator log. |
agentmetry cloud cursor-cache |
Record Cursor cloud-agent tool calls from the Cursor desktop app's local cache, read-only: commands, file reads and edits, MCP calls, hashed like a local hook event. Only agents the app has streamed; after the fact. --dry-run counts without posting. |
agentmetry stats |
Trail metrics. agentmetry stats --days 7. |
agentmetry detections |
List detections for one session, via the API. |
agentmetry disposition |
Set a detection's triage status. false_positive and risk_accepted require --note. |
agentmetry replay |
ASCII timeline of one session from the trail. |
agentmetry export |
--evidence or --compliance-digest. |
agentmetry verify |
Recompute an evidence-pack hash, or agentmetry verify --trail for the JSONL chain. |
agentmetry trail |
rotate or segments. See trail retention. |
agentmetry anchor |
Publish a checkpoint. See anchoring. |
agentmetry prove |
Inclusion proof for one record, or --check to verify one. |
agentmetry import-agt |
Ingest a Microsoft Agent Governance Toolkit audit file. |
agentmetry backup / agentmetry restore |
Zip the data stores, or restore one with the server stopped. |
agentmetry dogfood |
Score the beta gate, or --start its clock. |
Clone installers, not part of the wheel: scripts/install.ps1 (Windows) and scripts/install.sh (Linux and macOS). scripts/otel_receiver.py is a shim for agentmetry otel.
CONTRIBUTING.md. Issues: github.com/blitzcrieg1/agentmetry/issues. Roadmap: ROADMAP.md.
| Area | Start here |
|---|---|
| Hooks | docs/agentmetry-external-ingest.md |
| Schema | docs/agentmetry-event-schema.md |
| Detection rules | docs/detection-rules.md and the corpus under apps/orchestrator/agentmetry/core/audit/detection/corpus/ |
| DLP rules | apps/orchestrator/agentmetry/policies/dlp/manifest.yaml |
| Sigma | docs/integrations/sigma/README.md |
PRs need a signed CLA (v1.0).
The trail stays on the machine unless you set a sink. Tool arguments are SHA-256 by default. Set AGENTMETRY_HASH_KEY and the fingerprints are HMAC-SHA256. Every API route except health needs the per-install token or AGENTMETRY_API_KEY. AGENTMETRY_AUTH_DISABLED=1 is for development, and doctor flags it.
Report vulnerabilities via private vulnerability reporting. See SECURITY.md.
Apache-2.0, Copyright 2026 blitzcrieg1. See LICENSE and NOTICE.
Companies use CCLA.md. Trademark: TRADEMARK.md. Commercial intent, non-binding: COMMERCIAL.md.
Built and maintained by Ioannis L. LinkedIn.

