EDR sees powershell.exe. It does not see which coding agent, which developer, or which MCP schema. Agentmetry records that on the laptop, with a hash chain a third party can verify, and forwards it into Splunk, Elastic, or Google SecOps. It is not a console, not a vendor cloud, and not a replacement for EDR or CNAPP.
Silent MSI. Intune user-context. Config from MDM. No callback home.
No account. No telemetry. Apache-2.0. Runs on the machine you already own.
EDR saw powershell.exe
this is what it missed
tool.command
Get-Content $env:USERPROFILE\.aws\credentials
Illustrative values, real schema 1.2.0. That command is classified by the shipped mapper, not written here: it reads a credential file, so it earns T1552.001 and AML.T0098. Command capture is opt-in; the default hashes arguments and stores no command.
Records these coding agents
Hook coverage on these eight surfaces, plus an MCP stdio audit proxy. This list is what can be recorded. It is not a reading of the machine you are on.
Forwards into the console you already run
Native adapters. Loki is Grafana Alloy tailing the local JSONL, not a fourth native sink. Splunk TA ships with the pilot. Marks identify the consoles Agentmetry forwards into. No affiliation is claimed.
An EDR records that powershell.exe read %USERPROFILE%\\.aws\\credentials. It cannot tell you which coding agent invoked the shell tool, which developer prompted it, whether local policy allowed it, or whether the result left through an MCP server.
CNAPP inventories AI integrations in the cloud. LLM observability counts tokens. Neither one has the session on the laptop.
sees
The process. powershell.exe read a file. The IDE binary talked to the network.
does not see
Which agent, which prompt, which MCP server, which session.
sees
Cloud AI services, models, and MCP connections, agentlessly, from the cloud.
does not see
What those MCP servers returned to an agent on a laptop.
sees
The logs you already collect. The control plane. Agentmetry lands here.
does not see
This telemetry, unless a sensor on the endpoint produces it.
sees
Which agent, which human, which tool sequence, which MCP schema, with a verifiable trail.
does not see
Unmanaged ChatGPT, Copilot, and any IDE with hooks off. That is a stated limit.
A heartbeat every 300s says the recorder is alive, which of 8 agent surfaces are covered, uncovered, absent, or unknown, how deep the spool is, and the MCP schema digest. Uncovered is the incident. Absent is Tuesday. You can tell which seats are actually recording, and the SIEM alerts when one stops.
Hash-chained JSONL on disk. RFC 6962 Merkle root on the heartbeat (1.2 KB inclusion proof against an 8.3 MB trail). External anchors. Evidence packs with SHA-256 manifests. agentmetry verify --trail walks it. Direct SIEM push is a copy, not the chain.
15 built-in rules over the session, tagged with MITRE ATT&CK and, on the AI-specific subset, MITRE ATLAS. Credential access then egress is one finding. The public benchmark covers 13 of those rules on 50 recorded sessions. Findings are events, not blocks.
Silent Windows MSI, Intune user-context Remediation, hooks installed in the developer profile rather than LocalSystem, config from MDM. No vendor cloud and no data egress unless you set a sink. Not EV-signed. Not run against a real tenant yet.
A key, not a status board. This page cannot see your machine and does not claim to. `absent` and `uncovered` are kept apart because collapsing them is what made an earlier build degrade every heartbeat forever, until operators learned to ignore the one signal that mattered.
The eight agent surfaces Agentmetry can record. States are per machine, per beat, and this board is the list rather than a reading of it: it does not claim any of these are covered on the machine you are reading it from.
schema moved and config did not
A rug pull keeps the command line identical and changes what the server hands the model. postmark-mcp shipped fifteen clean versions first. Config alone never sees it.
Empty until a server is listed through the audit proxy. That is a gap, not a healthy default, and the beat reports it as empty rather than as clean.
Capture surfaces today: Cursor, Claude Code, Codex, Antigravity, Qwen, Kimi, Qoder, CodeBuddy, plus an MCP stdio audit proxy. Lead with the schema fingerprint, not the config digest: a rug pull leaves the config file identical and changes tools/list. Codex reports covered once the hook file is present. Codex also skips untrusted hooks silently, which a file check cannot see.
Enterprise package. Ingest ships in the frozen binary, so a machine with no git checkout can still capture. Not EV-signed. Not a clean-room certified build.
Remediation pair deploys hooks into the developer profile, not LocalSystem. Remediations need Plan 2 or Windows Enterprise E3/E5, not base Intune. Not run against a real tenant.
Sinks, fleet_id, and heartbeat interval are environment. No vendor portal. No callback home.
agentmetry hooks status: 0 compliant, 1 needs remediation, 2 undeterminable. Deployment tooling can fail a device without scraping a dashboard.
Illustrative values, real schema. This sample is a credential-shaped Read (T1552.001). A generic file read tags T1005. The trail hashes tool arguments in the hook process, so the secret itself is not in the record. Query the technique id, not the label.
{
"schema_version": "1.2.0",
"event_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"seq": 42,
"session_id": "sess-abc",
"correlation_id": "thread-8892",
"timestamp_utc": "2026-07-12T09:14:22.041+00:00",
"host_id": "dev-laptop",
"fleet_id": "consulting-pilot",
"source_topic": "external/claude/tool_called",
"source": {
"tier": "external",
"app": "claude",
"adapter": "claude_hook"
},
"initiator": {
"actor_type": "human",
"trigger": "manual",
"operator_id": "dev_01"
},
"actor": {
"type": "user",
"id": "dev_01",
"role": "operator"
},
"action": {
"type": "tool_called",
"outcome": "success",
"reason": ""
},
"agent": {
"name": "claude",
"skill_id": ""
},
"tool": {
"name": "PowerShell",
"qualified": "PowerShell",
"server": "claude",
"input_redaction": "hash+command",
"input_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"parameters_redacted": false,
"command": "Get-Content $env:USERPROFILE\\.aws\\credentials",
"mitre": {
"tactic_id": "TA0006",
"tactic": "Credential Access",
"technique_id": "T1552.001",
"technique": "Credentials In Files"
},
"atlas": {
"framework": "MITRE ATLAS",
"tactic_id": "AML.TA0013",
"tactic": "Credential Access",
"technique_id": "AML.T0098",
"technique": "AI Agent Tool Credential Harvesting",
"atlas_version": "2026.07"
}
}
}Which coding agent invoked the tool.
Which human the run is attributed to.
Same human, from the run origin, not a client header.
tool_called, heartbeat, detection, mcp_schema, and the rest.
success, denied, degraded, or the detection severity.
Query the id. The label text can change.
One agent session. Sequence detections key on this.
Arguments are hashed in the hook. Secrets stay off the trail.
Hostname, not a cryptographic identity. Per-host signing is an Enterprise feature, not an open-core roadmap item.
A firing rule is its own event: action.type: detection, action.outcome carries the severity. Alert with action.type:detection AND action.outcome:critical without learning the rule vocabulary.
ATT&CK describes what the agent did to the host. ATLAS describes what was done to or through the agent. Both can sit on one event, describing different things about it.
what the agent did to the host
what was done to or through the agent
Most of ATT&CK is not reachable from here. It covers a whole intrusion: phishing for initial access, SMB for lateral movement, rootkits for evasion. Agentmetry watches one boundary, the tool calls a coding agent makes, so the techniques it could ever see are the ones an agent can perform with a file, a shell, a network call or an MCP server. 697 is the size of the matrix, not the size of the opportunity.
Not every miss is out of reach. An archive built before an upload is T1560 and currently reads as T1059. A copy to cloud storage is T1567.002 and reads as T1059. A scheduled task the agent registers is T1053. Those are observable at this boundary and are not mapped yet, which is a backlog rather than a boundary.
A sensor that labels every call has labels that carry no information. The mapper tags what it recognises and leaves the rest blank, so two ATLAS techniques are deliberately never emitted: `AI Agent Tool Invocation` is true of every event this records, and `Command and Scripting Interpreter` is ATLAS restating ATT&CK. Both would have tripled the count and told a SOC nothing.
An MCP server that ships clean, gets adopted, then swaps its advertised tool schema underneath the model has no honest ATT&CK id. The nearest is T1195, which is compromise of a distribution channel, not a running server changing its tools between calls. ATLAS names it exactly.
AML.T0109 · AI Supply Chain Rug Pull · Defense Evasion
Filed under Defense Evasion because the scrutiny happens at adoption and not at update. postmark-mcp shipped fifteen clean releases before the one that mattered.
Not an official mapping. No MITRE validation and no MITRE evaluation. Every id was resolved by name against the published matrix rather than from memory, and the ATLAS labels are newer than the ATT&CK ones by a long way.
IDE lifecycle hooks and the MCP proxy record tool calls. Arguments are SHA-256 hashed in the hook process. agentmetry hooks install writes configs for agents present in that profile. If the orchestrator is down, events spool and replay.
Events become canonical JSONL v1.2.0 with MITRE tags and a tamper-evident hash chain on the file sink. Detections and triage decisions append to the same chain.
A heartbeat every 300s carries hook coverage, spool depth, MCP config digest, MCP schema digest, and the Merkle root. Silence becomes a finding. Schema change does not degrade the beat; hook removal does.
Optional. The same trail can stream to Splunk, Elastic, Google SecOps, or a CloudEvents webhook. Loki tails the file. The local trail remains the source of truth.
Agents installed here whose hook is missing. The incident.
SHA of the tools/list the model was handed. Runtime, not inventory.
SHA of the configured MCP command lines. Inventory, weaker signal.
RFC 6962 commitment that lands in the SIEM, off the endpoint.
Events buffered because the orchestrator was down.
Default 300. Silence after two missed beats is the finding.
index=main sourcetype=agentmetry:json action_type=heartbeat action_outcome=degraded
The process is up, the port answers, and the agents on that machine are no longer recorded. A liveness ping cannot see this.
index=main sourcetype=agentmetry:json action_type=mcp_schema action_outcome=changed
Config digest unchanged, schema digest moved: the tools/list the model was handed is not the one you inventoried.

The SIEM is the control plane. This dashboard is a local convenience. The trail on disk is the source of truth.
Nothing leaves the machine unless you set a sink. There is no vendor cloud and no hosted control plane.
Native adapter. Sourcetype agentmetry:json.
Native adapter.
Native adapter, posted as UDM.
Canonical JSON, or CloudEvents 1.0 structured mode (application/cloudevents+json).
Not a native adapter. Grafana Alloy tails the local JSONL, which keeps the chain envelope that direct push strips.
Private add-on (TA-agentmetry). Search-time fields for heartbeat.hooks_uncovered, hook_profile, mcp_schema_digest, trail_merkle_root. Not on Splunkbase, not AppInspected.
Product names and marks belong to their owners and appear here to identify what Agentmetry forwards into. No affiliation, partnership, sponsorship or endorsement is claimed by any of them.
Microsoft AGT audit files can be read back in. DLP is 18 regex rules in a YAML pack, default mode log. Tool policy also defaults to log. Block mode exists; it is not how a stock install behaves. MITRE tactic and technique ids are on the event; query the ids.
The sensor is Apache-2.0. The MSI, Intune, and Splunk TA live in a private repo and ship as a design-partner pilot. There is no third SKU until a real tenant has run the installer.
Path 01 · evaluate
Free · Apache-2.0
Path 02 · deploy
90 days · up to 25 seats
It records the agents you wire in. An unmanaged ChatGPT tab, Microsoft 365 Copilot, or Cursor with hooks removed is invisible. That is network and endpoint policy territory.
It does not stop an agent that avoids the hooked tools. DLP and tool policy default to log. Block mode is the only pre-execution stop, and it is off unless you turn it on.
When a tool runs after an ask, the trail may include an approval_response flagged inferred:*. That is a reconstruction, not a workflow the product owns.
The hash chain proves ordering and non-modification of what was written. Anyone with write access can build a well-formed chain. Per-host identity is an Enterprise feature, not an open-core roadmap item. The core stays single-machine by design.
Codex trusts hooks by hash and skips untrusted ones silently. The heartbeat cannot see that decision.
APIs may still change. Fleet MSI and Intune scripts exist and have not been run against a real tenant. The Splunk TA is not on Splunkbase. The Apache-2.0 core is the floor: trails, detections, and forwarders do not depend on a vendor remaining in business. Enterprise pilots get a perpetual license, a source deposit with each delivery, and an automatic Apache-2.0 grant on a Continuity Event (cessation, insolvency, or incapacity). That clause lives in the pilot SOW, not as a slogan.
Benchmark, checkable from a pip install: 50 cases (26 attack, 24 benign), 13 of 15 rules covered, zero misses and zero false positives on that corpus. agentmetry benchmark
Start on a machine you control. If the fleet packaging is what you need, the second path is a mailbox, not a cart.