{"slug": "agentmetry-catch-your-ai-coding-agent-reading-ssh-and-phoning-home", "title": "Agentmetry, catch your AI coding agent reading –/.ssh and phoning home", "summary": "Agentmetry, an open-source flight recorder for AI coding agents, captures and correlates every tool call with MITRE ATT&CK tags and SHA-256 hashing, enabling replay and SIEM forwarding. The tool detects behavioral sequences like credential exfiltration and blocks secrets via a local DLP engine, all while running fully locally without vendor cloud dependency.", "body_md": "The open-source flight recorder and security layer for AI agent tool-use.\n\nEvery tool call, every denial, every human approval — hashed, correlated, and stored in a JSONL trail you own.\n\nReplay on demand; forward to Loki, Elastic, or Splunk when you want a SIEM.\n\n[ Quickstart](#install--quick-start) ·\n\n[·](/blitzcrieg1/agentmetry/blob/master/docs/agentmetry-external-ingest.md)\n\n**Docs**[·](/blitzcrieg1/agentmetry/blob/master/docs/agentmetry-event-schema.md)\n\n**Schema**[·](/blitzcrieg1/agentmetry/blob/master/ROADMAP.md)\n\n**Roadmap**\n\n**Security**\n*Every AI-agent tool call, tagged with MITRE ATT&CK as it happens — and a\ncorrelated alert when a sequence of innocent-looking calls adds up to an attack.*\n\n🚧\n\nPublic Alpha: Core capture, replay, and SIEM forwarding are usable for early exploration. APIs and integration surfaces may evolve rapidly.\n\n[Why Agentmetry?](#why-agentmetry)[Install & Quick Start](#install--quick-start)[How Agentmetry Works](#how-agentmetry-works)[Coverage & Limitations](#coverage--limitations)[Capabilities & Integrations](#capabilities--integrations)[Behavioral Detection Engine](#behavioral-detection-engine)[Data Loss Prevention (DLP)](#data-loss-prevention-dlp)[Dashboard](#dashboard)[Forwarding to a SIEM](#forwarding-to-a-siem)[CLI Reference](#cli-reference)[Contributing](#contributing)[Security](#security)[License](#license)\n\nWhen an autonomous agent runs a tool, most stacks keep nothing you could hand to an incident responder. Logs show a process; they do not show **intent**, **session boundaries**, or **what the human approved**.\n\nAgentmetry is the open-source **endpoint flight recorder** for AI agents — built to run entirely on your machine, with optional forwarding to the SIEM you already operate.\n\nan immutable, operator-owned audit trail for governed AI agents — capturing tool execution at the IDE lifecycle boundary and the MCP wire, not in a vendor cloud\n\nWe do that by:\n\n**Intercepting** agent tool calls through IDE lifecycle hooks (Cursor, Claude Code, Codex, Antigravity) and an MCP stdio audit proxy**Normalizing** every event into a canonical schema v1.1.0 with MITRE ATT&CK enrichment and SHA-256 argument hashing**Detecting** correlated behavioral sequences a single event cannot reveal (credential exfil, guardrail bypass, recon-then-grab)**Blocking** secrets and PII at the hook boundary with a local regex DLP engine (`log`\n\nor`block`\n\nmode)**Forwarding** the same JSONL trail to Loki, Elastic ECS, Splunk HEC, or a generic webhook — without making the cloud the system of record\n\n**Agentmetry is not a CASB or shadow-AI spy.** It records the agents you wire in. If your problem is unmanaged ChatGPT in the browser, you need network/endpoint policy — not a flight recorder.\n\nAgentmetry runs fully locally. The audit trail never leaves your machine unless you explicitly forward it.\n\nNo server, no API key, no config. Clone and run:\n\n```\ngit clone https://github.com/blitzcrieg1/agentmetry.git && cd agentmetry\npip install -r apps/orchestrator/requirements.txt\npython scripts/demo.py\n```\n\nIt replays an agent session through the real ingest API: the agent reads an SSH\nprivate key, runs a command containing an AWS key, then fetches a URL. Agentmetry\ntags each call with MITRE ATT&CK, catches the AWS key with DLP (storing the rule,\nnever the value), and then — without being asked — **correlates the key read with\nthe network call and fires a CRITICAL credential-exfil detection.**\n\nNo single one of those events is an alert. The sequence is. That is the whole product in one screen.\n\n```\npython scripts/demo_dashboard.py      # seeds 5 sessions + 4 detections, serves http://127.0.0.1:8010/\n```\n\nOne command seeds a realistic demo trail and serves the dashboard locally — no API key, no cloud. Click a flagged session and the detection is right there, with the full event drilled open beneath it:\n\nSee the [dashboard tour](/blitzcrieg1/agentmetry/blob/master/docs/dashboard-tour.md) for what each view shows and how\nto read it.\n\n| Requirement | Version |\n|---|---|\n| Python | 3.10+ |\n| Node.js | 18+ |\n\n```\ngit clone https://github.com/blitzcrieg1/agentmetry.git\ncd agentmetry\n\n# Python orchestrator\ncd apps\\orchestrator\npython -m venv .venv\n.\\.venv\\Scripts\\activate\npip install -e \".[dev]\"\ncopy .env.example .env\ncd ..\\..\n\n# Next.js dashboard\ncd apps\\dashboard\nnpm install\ncd ..\\..\nscripts\\start-dev.bat\n```\n\nDashboard → [http://localhost:3000](http://localhost:3000) · Orchestrator API → [http://localhost:8000](http://localhost:8000)\n\n```\npowershell -ExecutionPolicy Bypass -File scripts\\install_cursor_hooks.ps1\npowershell -ExecutionPolicy Bypass -File scripts\\install_claude_hooks.ps1\n```\n\nFully quit and restart Cursor / Claude Code so hooks load.\n\n```\npython scripts\\agentmetry_ingest.py selftest\n```\n\nEvents should appear in the dashboard **Flight Recorder** within a few seconds.\n\nWhen an agent runs a tool, Agentmetry automatically:\n\n**Intercepts** the lifecycle hook or MCP`tools/call`\n\nbefore arguments leave the hook process**Hashes** tool arguments (SHA-256) and scrubs inline secrets in command strings**Enriches** each event with MITRE tactic/technique mappings and session correlation**Stores** canonical JSONL locally (`audit-forward.jsonl`\n\n) — the system of record for the hook path**Detects** multi-step behavioral patterns across the session timeline**Forwards** to your SIEM sinks and alert webhook (optional, best-effort)\n\n```\nflowchart TB\n  subgraph Capture[\"Capture Layer (Tier A + B)\"]\n    HOOKS[\"IDE Lifecycle Hooks<br/>Cursor · Claude · Codex · Antigravity\"]\n    PROXY[\"MCP Audit Proxy<br/>mcp_audit_proxy.py\"]\n  end\n\n  subgraph Gate[\"Local Security Gate\"]\n    DLP[\"DLP Scanner<br/>regex rules\"]\n    HASH[\"Arg Hash + Secret Scrub\"]\n  end\n\n  subgraph Core[\"Orchestrator :8000\"]\n    INGEST[\"POST /api/v1/audit/ingest\"]\n    CANON[\"Canonical Schema v1.1.0<br/>MITRE enrichment\"]\n    DETECT[\"Sequence Detection Engine\"]\n    OUTBOX[(\"SQLite Outbox<br/>events.db\")]\n  end\n\n  subgraph Output[\"Outputs\"]\n    JSONL[\"audit-forward.jsonl\"]\n    DASH[\"Dashboard<br/>Flight Recorder + Analytics\"]\n    SIEM[\"Loki · Elastic · Splunk · Webhook\"]\n  end\n\n  HOOKS --> DLP\n  PROXY --> DLP\n  DLP -->|allow| HASH\n  DLP -->|deny| INGEST\n  HASH --> INGEST\n  INGEST --> CANON\n  CANON --> OUTBOX\n  CANON --> JSONL\n  CANON --> DETECT\n  JSONL --> DASH\n  JSONL --> SIEM\nflowchart LR\n  subgraph TierB[\"Tier B — IDE Hooks\"]\n    C[\"Cursor\"]\n    CL[\"Claude Code\"]\n    AG[\"Antigravity\"]\n    CX[\"Codex\"]\n  end\n\n  subgraph TierA[\"Tier A — MCP Proxy\"]\n    MCP[\"Any MCP Client\"]\n    WRAP[\"Audit Proxy wraps server command\"]\n  end\n\n  INGEST[\"agentmetry_ingest.py → /audit/ingest\"]\n\n  C --> INGEST\n  CL --> INGEST\n  AG --> INGEST\n  CX --> INGEST\n  MCP --> WRAP --> INGEST\n```\n\n| Component | Path | Role |\n|---|---|---|\nHook client |\n`scripts/agentmetry_ingest.py` |\nMaps IDE lifecycle events to canonical payloads; hashes args in-process |\nMCP proxy |\n`apps/orchestrator/tools/mcp_audit_proxy.py` |\nWraps any stdio MCP server; logs every `tools/call` + errors |\nIngest API |\n`core/audit/ingest.py` |\nNormalizes payloads, infers approvals (`inferred:*` ), writes sinks |\nDLP engine |\n`core/audit/dlp/` |\nRegex scan of tool arguments (validators, e.g. Luhn); block or log before execution |\nDetection engine |\n`core/audit/detection/` |\nCorrelated sequence rules over a session's event timeline |\nSinks |\n`core/audit/sinks.py` |\nFile, webhook, Elastic ECS, Splunk HEC |\nReplay |\n`core/audit/replay.py` |\nASCII timeline reconstruction from the local outbox |\n\nEvery run emits typed, SIEM-ready JSON. A single `tool_called`\n\nline:\n\n```\n{\n  \"schema_version\": \"1.1.0\",\n  \"correlation_id\": \"thread-8892\",\n  \"timestamp_utc\": \"2026-07-12T09:14:22.041+00:00\",\n  \"actor\": {\"type\": \"user\", \"id\": \"dev_01\", \"role\": \"operator\"},\n  \"action\": {\"type\": \"tool_called\", \"outcome\": \"success\"},\n  \"agent\": {\"name\": \"cursor\", \"skill_id\": \"\"},\n  \"tool\": {\n    \"qualified\": \"vault_fs.read_file\",\n    \"server\": \"vault_fs\",\n    \"input_hash\": \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n    \"parameters_redacted\": true,\n    \"mitre\": {\"tactic\": \"Collection (TA0009)\", \"technique\": \"Data from Local System (T1005)\"}\n  },\n  \"model\": {\"id\": \"claude-3-5-sonnet\", \"provider\": \"anthropic\"}\n}\n```\n\nFull schema → [docs/agentmetry-event-schema.md](/blitzcrieg1/agentmetry/blob/master/docs/agentmetry-event-schema.md)\n\nAgentmetry records agents you wire in — **IDE hooks** or the **MCP proxy**. It is honest about what it cannot see.\n\n| Tier | Setup | Agentmetry coverage |\n|---|---|---|\nA |\nMCP servers wrapped with the audit proxy | Full tool-call capture — every `tools/call` + error responses, arg hashes, session correlation |\nB |\nIDE hooks (Cursor, Claude, Codex, Antigravity) | Tool calls (success/failure), approval prompts; approve/deny inferred from execution and flagged `inferred:*` |\nC |\nUnmanaged ChatGPT, Cursor with hooks off | Not visible. CASB / secure-web-gateway territory |\n\n🎥 Flight Recorder |\nLive audit tail with dynamic columns, drag-and-drop layout, CSV export, and session drill-down |\n📊 Analytics & Process Tree |\nSession-level charts, MITRE tactic breakdown, horizontal React Flow timeline |\n🔍 Behavioral Detection |\nCorrelated sequence rules — credential exfil, guardrail bypass, recon-then-grab |\n🛡️ Local DLP |\nRegex scanner blocks AWS keys, GitHub tokens, Slack tokens, and PII before tool execution |\n🎯 MITRE ATT&CK mapping |\nPer-tool tactic/technique tags on every canonical event |\n🔐 Argument hashing |\nSHA-256 of tool args by default — plaintext never crosses the wire from hooks |\n📡 SIEM-native export |\nElastic ECS, Splunk HEC, Loki/LogQL, generic webhook, alert webhook on denials |\n🔁 Replay & evidence |\nASCII session timeline + tamper-evident evidence pack export |\n👥 Multi-IDE support |\nCursor, Claude Code, Codex, Antigravity — global hook install scripts |\n\n| Category | Supported today | Roadmap |\n|---|---|---|\nIDE / Agent hosts |\nCursor · Claude Code · Codex · Antigravity | Windsurf · VS Code Copilot |\nMCP transport |\nStdio audit proxy (wrap any MCP server command) | SSE / streamable HTTP proxy |\nObservability / SIEM |\nLoki · Grafana · Elastic ECS · Splunk HEC · generic webhook | Datadog · New Relic |\nDetection formats |\nIn-engine sequence rules · LogQL · Elastic · Splunk ·\n|\n\n**Policy engines**`policies/dlp/`\n\n)**Compliance docs**[ISO 42001 mapping](/blitzcrieg1/agentmetry/blob/master/docs/compliance/iso-42001-mapping.md)·[AI Act checklist](/blitzcrieg1/agentmetry/blob/master/docs/compliance/ai-act-deployer-checklist.md)Agentmetry is community-built. Browse [open issues](https://github.com/blitzcrieg1/agentmetry/issues) or the [roadmap](/blitzcrieg1/agentmetry/blob/master/ROADMAP.md).\n\nPer-event MITRE tags say *what* a single tool call is. The detection engine says what a **sequence** of calls means — the signal an EDR cannot see because it never had the agent's session boundary.\n\nRules run **as events arrive**. A firing rule is emitted once per session as a first-class canonical event (`action.type: detection`\n\n, `action.outcome: <severity>`\n\n) down the same sinks as everything else — so it reaches your SIEM, your alert webhook, and the live feed without anyone opening a dashboard. The same findings are recomputed from the trail on `GET /audit/detections/{correlation_id}`\n\n.\n\nAlpha limitation.Live correlation state is in-memory and per-process: restarting the orchestrator resets alerting continuity for in-flight sessions. The JSONL trail stays authoritative, so no detection is everlost— it is recomputed on query — but a restart mid-session can delay a live alert. Detection state is not shared across processes.\n\n```\nsequenceDiagram\n  participant IDE as IDE / MCP Proxy\n  participant IN as Ingest API\n  participant DB as JSONL Outbox\n  participant ENG as Detection Engine\n  participant API as GET /audit/detections/{id}\n\n  IDE->>IN: tool_called / approval_response / session_end\n  IN->>DB: append canonical event\n  Note over ENG: Rules run over time-ordered session events\n  ENG->>ENG: credential-exfil\n  ENG->>ENG: approval-denied-then-executed\n  ENG->>ENG: discovery-then-collect\n  API->>DB: load events for correlation_id\n  API->>ENG: run_detections(events)\n  ENG-->>API: ranked Detection list\n```\n\n| Rule ID | Severity | Pattern |\n|---|---|---|\n`credential-exfil` |\ncritical | Credential access (T1552) → network egress (TA0011) |\n`approval-denied-then-executed` |\ncritical | Human denied a gated tool → same tool executed successfully later |\n`autonomous-unapproved-write` |\nhigh | Autonomous agent writes/deletes with no prior human approval |\n`discovery-then-collect` |\nmedium | Filesystem recon burst (TA0007) → data collection |\n\nQuery detections for a session:\n\n```\nGET /api/v1/audit/detections/{correlation_id}\nX-API-Key: <optional>\n```\n\nAgentmetry ships a local regex DLP engine that scans tool arguments **before** they are executed or logged. When a match fires in `block`\n\nmode, the hook denies execution and emits a `tool_denied`\n\nevent.\n\n``` php\nflowchart LR\n  HOOK[\"Pre-tool hook\"] --> SCAN[\"DLP Scanner<br/>policies/dlp/manifest.yaml\"]\n  SCAN -->|match + block| DENY[\"tool_denied<br/>reason: dlp:rule_id\"]\n  SCAN -->|pass| EXEC[\"Tool executes + audit log\"]\n  SCAN -->|match + log| WARN[\"Audit + allow<br/>(observe mode)\"]\n```\n\n| Env | Default | Description |\n|---|---|---|\n`AGENTMETRY_DLP_MODE` |\n`log` |\n`log` · `block` · `disable` |\n`AGENTMETRY_DLP_PII` |\n`1` |\nEnable PII rules (SSN, etc.) |\n`AGENTMETRY_DLP_RULES_PATH` |\n`policies/dlp/manifest.yaml` |\nCustom rule manifest |\n\nRules cover AWS keys, GitHub PATs, Slack tokens, bearer headers, private keys, and US SSN patterns. Add custom regex rules without touching Python — drop entries into the manifest.\n\nThe Next.js dashboard at `:3000`\n\ngives SOC analysts a live view of agent activity:\n\n| View | Features |\n|---|---|\nFlight Recorder |\nReal-time event tail, source badges, outcome filters, expandable row detail, raw JSON view |\nColumn manager |\nDrag-and-drop column layout featuring built-in fields for model, skill, host, MCP server, and failure reasons — reorder or hide via the Columns settings panel |\nAnalytics |\nOutcome distribution, MITRE tactic chart, session ID search |\nProcess Tree |\nHorizontal React Flow timeline of events within a selected session |\n\nDark mode supported with theme toggle. Logo and panels adapt automatically.\n\nFor agents captured via IDE hooks (the common case), the canonical JSONL trail is the **system of record**; the SQLite outbox backs the orchestrator's own runs. Forwarders are best-effort.\n\n| Sink | Env |\n|---|---|\nFile (default) |\n`AGENTMETRY_AUDIT_SINK=file` |\nWebhook |\n`AGENTMETRY_AUDIT_SINK=webhook` + `AGENTMETRY_AUDIT_WEBHOOK_URL=...` |\nElastic ECS |\n`AGENTMETRY_AUDIT_SINK=elastic` + `AGENTMETRY_AUDIT_ELASTIC_URL` + `AGENTMETRY_ELASTIC_API_KEY` |\nSplunk HEC |\n`AGENTMETRY_AUDIT_SINK=splunk` + `AGENTMETRY_AUDIT_SPLUNK_HEC_URL` + `AGENTMETRY_SPLUNK_HEC_TOKEN` |\nAlert webhook |\n`AGENTMETRY_AUDIT_ALERT_WEBHOOK_URL=...` (fires on denied/error outcomes) |\n\nHomelab SIEM with Loki + Grafana:\n\n```\ndocker compose -f docker-compose.loki.yml up -d\n# Grafana → http://localhost:3001\n# Explore: {job=\"agentmetry\"} | json\n```\n\nIntegration guides → [docs/integrations/](/blitzcrieg1/agentmetry/blob/master/docs/integrations)\n\n`scripts\\agentmetry.bat`\n\n(or `python -m cli`\n\ninside the orchestrator venv):\n\n| Command | What it does |\n|---|---|\n`agentmetry start` / `stop` / `status` |\nRun the orchestrator detached; check health |\n`agentmetry replay <thread_id>` |\nASCII audit timeline for one run, from `events.db` |\n`agentmetry export --evidence` |\nTamper-evident batch pack (JSON + SHA-256) |\n`agentmetry verify <evidence.json>` |\nRecompute the integrity hash on an evidence export |\n`agentmetry doctor` |\nPreflight check for python, paths, etc. |\n\n`scripts\\agentmetry.bat`\n\nremains as a legacy alias.\n\nAgentmetry welcomes contributions across detection rules, DLP patterns, SIEM adapters, and dashboard UX.\n\n| Area | Start here |\n|---|---|\n| Hook adapters |\n|\n\n[docs/agentmetry-event-schema.md](/blitzcrieg1/agentmetry/blob/master/docs/agentmetry-event-schema.md)`apps/orchestrator/core/audit/detection/rules.py`\n\n`policies/dlp/manifest.yaml`\n\n[docs/integrations/sigma/README.md](/blitzcrieg1/agentmetry/blob/master/docs/integrations/sigma/README.md)[ROADMAP.md](/blitzcrieg1/agentmetry/blob/master/ROADMAP.md)Run tests before opening a PR:\n\n```\ncd apps\\orchestrator\npython -m ruff check core api tests\npython -m pytest -q\n```\n\nAgentmetry is designed for security-sensitive environments:\n\n**Local-first**— audit data stays on your machine unless you configure forwarders** Argument hashing by default**— plaintext tool args never leave the hook process** Optional API key**— protect ingest/tail/export endpoints with`AGENTMETRY_API_KEY`\n\n**DLP blocking**— stop secrets and PII from reaching tool execution boundaries** Tamper-evident exports**— evidence packs include SHA-256 integrity hashes\n\nReport vulnerabilities via GitHub Issues with the `security`\n\nlabel, or open a private security advisory on the repository.\n\nCompliance docs → [docs/compliance/](/blitzcrieg1/agentmetry/blob/master/docs/compliance)\n\nApache-2.0. Contributions, schema feedback, and detection rules welcome!\n\nBuilt and maintained by Ioannis L. — connect on [LinkedIn](https://www.linkedin.com/in/ioannis-l-074439194/).", "url": "https://wpnews.pro/news/agentmetry-catch-your-ai-coding-agent-reading-ssh-and-phoning-home", "canonical_source": "https://github.com/blitzcrieg1/agentmetry", "published_at": "2026-07-14 16:41:48+00:00", "updated_at": "2026-07-14 16:48:56.854941+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-ethics", "ai-tools", "ai-infrastructure"], "entities": ["Agentmetry", "Cursor", "Claude Code", "Codex", "Antigravity", "Loki", "Elastic", "Splunk"], "alternates": {"html": "https://wpnews.pro/news/agentmetry-catch-your-ai-coding-agent-reading-ssh-and-phoning-home", "markdown": "https://wpnews.pro/news/agentmetry-catch-your-ai-coding-agent-reading-ssh-and-phoning-home.md", "text": "https://wpnews.pro/news/agentmetry-catch-your-ai-coding-agent-reading-ssh-and-phoning-home.txt", "jsonld": "https://wpnews.pro/news/agentmetry-catch-your-ai-coding-agent-reading-ssh-and-phoning-home.jsonld"}}