What the recorder emits, and what your console does with it.
An interactive walkthrough of the canonical event, the forwarders, the in-process DLP scan, and the hash chain. Queries, adapter documents, and regexes are the ones that ship. Nothing here is a reading of this browser. Agentmetry is the sensor. Your SIEM stays the console.
What it records, and where it lands.
Eight coding agents the heartbeat can attest, four native sinks, and Loki on the file. Marks identify the products. They are not a partnership, and they are not a live reading of this browser.
Coding agents
- Cursor
- Claude Code
- Codex
- Antigravity
- Qwen
- Kimi
- Qoder
- CodeBuddy
Plus an MCP stdio audit proxy. Letter tiles are labels: there is no honest product mark for Qwen, Kimi, Qoder or CodeBuddy, and a parent-company logo would be the wrong product.
Native sinks
- SplunkNative HEC. Sourcetype agentmetry:json.
- ElasticNative ECS adapter.
- Google SecOpsNative UDM, posted to udmevents.
- WebhookCanonical JSON, or CloudEvents 1.0.
File tail
- Grafana LokiNot a native adapter. Alloy tails the local JSONL, which keeps the chain envelope that direct push strips.
Product names belong to their owners. No affiliation, partnership, sponsorship or endorsement is claimed.
Real queries, and the document your SIEM actually receives.
Every query is transcribed from the detection docs that ship in the repository. Every document is generated from the adapter that forwards it. This is Agentmetry's console showing their languages, not a replica of their product. Copy a query into your own console and it will run.
Five or more denied tool calls in one minute per actor. Scheduled every 1 minute; trigger when denials >= 5. Paste into Splunk. This page does not run it, and the event below is not a hit for this search: it is the credential-read the adapter actually forwarded.
| event.timestamp_utc | host | sourcetype | action_type | action_outcome | technique_id |
|---|---|---|---|---|---|
{
"time": 1787217262.041,
"host": "dev-laptop",
"source": "Agentmetry",
"sourcetype": "agentmetry:json",
"index": "main",
"fields": {
"action_type": "tool_called",
"action_outcome": "success",
"correlation_id": "thread-8892",
"actor_id": "dev_01"
},
"event": {
"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-08-20T09:14:22.041+00:00",
"host_id": "dev-laptop",
"fleet_id": "consulting-pilot",
"source_topic": "external/cursor/tool_called",
"source": {
"tier": "external",
"app": "cursor",
"adapter": "cursor_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": "cursor",
"skill_id": ""
},
"tool": {
"name": "Read",
"qualified": "cursor.Read",
"server": "cursor",
"input_redaction": "hash",
"input_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"parameters_redacted": true,
"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"
}
}
}
}Product names belong to their owners and appear here to identify which platform each query is written for. No affiliation, partnership, sponsorship or endorsement is claimed by any of them, and no vendor interface is reproduced. Splunk is named because the SPL above is Splunk's language, not ours.
The real ruleset, run against whatever you paste.
All 18 rules from policies/dlp/manifest.yaml, not a demo subset. Nothing you type leaves this page, which is the same property the hook has: arguments are hashed in-process and the plaintext never crosses ingest.
Use fake credentials. Real ones do not become safer by being scanned locally, and this page has no way to tell them apart.
No rule matched. That is the common case, and it is why a scanner that fires constantly is worse than one that does not.
The matched text is never stored. What you see is its SHA-256, which is what reaches the trail, and what makes two occurrences of the same secret correlatable without the secret being present.
A chain you can recompute, and break.
Every digest below is real SHA-256, computed in your browser with the same rule the recorder uses: sha256(prev + newline + canonical json). Edit an event and watch what happens to the records after it.
hashing…
record = sha256(prev + "\n" + canonical_json)
Events here are illustrative. The hashing is not: this is core/audit/trail_chain.py ported, and the digests match the Python implementation.
Removal cannot be prevented. It can be made loud.
A heartbeat every 300 seconds reports the state of each agent surface. Change one below and watch what the beat would say. This is a key and a sandbox, not a reading of your machine.
- cursor
- claude
- qwen
- qoder
- codebuddy
- kimi
- codex
- antigravity
Same builder as build_heartbeat_event: uncovered, a service profile (unknown), or a non-empty spool degrades the beat. absent does not, because a machine with no agents on it is not a machine that stopped recording.
- covered
- agent is here and its hook is in place
- uncovered
- agent is here and is NOT recorded. The incident
- absent
- agent is not on this machine. Tuesday
- unknown
- cannot be determined, so neither is claimed
Covered is not capturing for Codex: it trusts hooks by hash and skips untrusted ones silently, which a file check cannot see.
Build a session. See whether the rule fires.
Every call below is ordinary on its own. The finding is the order. This panel evaluates the real credential-exfil conditions, not a confidence score, because the rule is a boolean and a percentage would be a mechanism the product does not have.
Empty session. Add calls above, in the order an agent would make them.
does not fire
No credential access in the sequence. The rule has nothing to anchor on.
A firing rule is written to the same trail as everything else, with action.type: detection and the severity on action.outcome. Nothing is blocked. The recorder records, and your console decides what to do about it.
The public configs. The Splunk TA stays in the pilot.
Elastic index template from the public integration doc, Grafana Alloy from the homelab stack. Copied, not rewritten. The Splunk TA is the private add-on, not on Splunkbase, and not in this zip.
- README.txtwritten for the public lab zip
- MANIFEST.txtwritten for the public lab zip
- elastic/index-template.jsondocs/integrations/elastic-ecs.md (index template block)
- grafana/alloy.configagentic-os/infra/loki/alloy.config
Public pack. Elastic template and Alloy only. The Splunk TA is not in this zip. There is no invented Elastic ingest pipeline in this zip: canonical_to_ecs already posts ECS documents. The Splunk TA, including saved searches and the expected-hosts lookup, is not here.