TruthLayer

Network-native, SDK-free evidentiary telemetry for autonomous agent systems

White paper — July 2026


Abstract

Autonomous AI agents now spend money, call tools, execute code, and transact with other agents — largely outside the observability perimeter their operators, auditors, and insurers can trust. Existing telemetry is self-reported: the agent (or the SDK embedded in it) writes its own history, and nothing prevents that history from being edited, elided, or fabricated after the fact.

TruthLayer is a cryptographically sealed, jurisdiction-aware, insurer-underwritable ledger of every action an AI agent takes. It captures agent activity at the network layer — LLM calls, MCP tool invocations, sandboxed code execution, x402 micropayments, and artifact access — without requiring any SDK inside the agent, binds every event into a per-agent hash chain signed by keys the agent never holds, seals each day under a Merkle root anchored to the Bitcoin blockchain via OpenTimestamps, and makes the whole record independently verifiable by anyone holding only public artifacts — no TruthLayer endpoint required.

The platform is composed entirely on Cloudflare primitives (Workers, Durable Objects with SQLite, R2, Workflows, Workers AI, AI Gateway) and runs at the edge across 330+ points of presence. This paper describes the threat model, the evidentiary design, the detection and enforcement layer, the verification story, and the measured behavior of the production system, including results the platform has not yet achieved.


1. The problem: agent activity is unauditable by construction

Three converging trends make autonomous-agent risk uninsurable today:

  1. Agents act with real-world authority. They hold credentials, spend budgets via micropayment protocols (x402), execute arbitrary code in sandboxes, and call third-party tools over MCP. The blast radius of a compromised or misaligned agent is financial and legal, not just reputational.
  2. Telemetry is self-reported. Agent frameworks log their own actions. A prompt-injected, compromised, or simply buggy agent controls its own audit trail. For a claims adjuster, a regulator, or a court, “the agent’s logs say X” is testimony from the defendant.
  3. No neutral observation point exists. Instrumenting the agent means trusting the agent. Instrumenting the model provider covers only LLM calls. What is needed is a chokepoint the agent’s traffic already flows through, operated by neither the agent nor its operator.

TruthLayer’s answer is to make the network itself the witness. When agent traffic transits Cloudflare’s edge — AI Gateway for LLM calls, Monetization Gateway for x402 payments, the Sandbox SDK for code execution, MCP-over-Workers for tool calls, Logpush for egress — each hop emits a webhook into TruthLayer’s ingest pipeline. The agent needs no SDK, cannot suppress the record, and never holds any key that could forge or unmake it.

An evidentiary record is only as strong as its weakest tampering opportunity. TruthLayer’s design goal is that every class of after-the-fact revision is either cryptographically impossible or cryptographically evident — including revision by TruthLayer itself.


2. System architecture

TruthLayer is a set of Cloudflare Workers and Durable Objects with two storage tiers and no servers:

Agent traffic ──► Cloudflare edge products ──► ingest-worker (HMAC-verified webhooks)
                                                     │  one Durable Object call

                                               AgentDO  (per-agent SQLite: hash chain,
                                                     │   admission, quota, signing subkey)
                                 certification /     │
                                 registry writes     ▼
                                               TenantDO (per-tenant: root keys, agents,
                                                          policy, credentials)

        seal-workflow (nightly Merkle seal + OpenTimestamps anchor)
        anomaly-workflow (hourly/nightly behavioral scan, Workers AI embeddings)
        kill-switch worker (throttle / kill / reactivate, AI Gateway spend limits)
        backup-workflow (nightly encrypted DO exports)


                              R2: private payloads (8 sharded buckets),
                                  public registry / seals / OTS proofs,
                                  Iceberg cold tier (reference DDL, deferred)

Read side:  audit-api (tenant-scoped, external auditors, REST + Cap'n Web)
            admin-api + dashboard (cross-tenant operator console, Cloudflare Access)
            tools/ledger-verify (standalone offline verifier, zero Cloudflare deps)

Cardinality. One TenantDO per customer; one AgentDO per agent, addressed deterministically as {tenant_id}:{agent_id}. The Durable Object model gives each agent’s ledger a single-writer execution context: chain construction never needs distributed consensus because Cloudflare guarantees one live instance per object, with SQLite storage (up to 10 GB per object) colocated with the compute that mutates it.

Why the edge. Ingest sources are globally distributed webhooks. Running admission, chain append, and signing in a Durable Object placed near the traffic — rather than a regional database — is what makes a sub-100ms evidentiary write path possible (§8).


3. The evidentiary core

3.1 The event and the chain

Every observed action becomes a LedgerEvent: category (llm_call, tool_call, sandbox_exec, x402_payment, egress_call, artifact_access, auth_event, gap_marker, generic), source, timestamps, jurisdiction, integer micro-USD cost, a reference to the full payload in R2, and the chain fields.

The full payload (prompt text, tool arguments, receipts) is canonicalized under RFC 8785 (JCS) — so hashing is byte-deterministic regardless of key order or whitespace — hashed with SHA-256, gzip-compressed, and written to a private R2 bucket. Only the hash enters the chain:

chain_this_hash = SHA-256( chain_prev_hash ‖ payload_hash ‖ event_id ‖ event_ts ‖ category )

chain_index is strictly monotonic per agent (enforced by a SQLite UNIQUE constraint and the DO’s concurrency gate). Deleting, reordering, or editing any historical event breaks every subsequent hash. The payload itself can be lost (R2 is fire-and-forget off the response path; a failed write is durably recorded and alerted, never silent) without weakening the chain — the hash commitment was made before the response was sent.

Gaps are signed, not silent. When an event is refused — over quota, agent killed, agent rate-limited — TruthLayer appends a signed gap_marker carrying the reason and the refused event’s identity. An auditor can therefore distinguish “nothing happened” from “something was refused and here is the cryptographic record of the refusal.” There is no code path that drops an authenticated event without leaving a chained trace.

3.2 The two-level signing hierarchy

Every event, daily seal, and anomaly record carries an Ed25519 signature. Key custody follows a two-level hierarchy modeled on DNSSEC’s KSK/ZSK split:

This hierarchy is what makes the hot path fast (§8) and bounds compromise: a leaked subkey can forge signatures for one agent, briefly — never for the tenant, and never beyond the validity window a verifier will accept. Subkey private halves are themselves KEK-wrapped at rest, under a key deliberately independent of the tenant-key KEK.

Every signed artifact records key_id — which exact key generation (root or subkey) produced its signature — so rotation never orphans history.

3.3 Daily seals and the Bitcoin anchor

A hash chain alone proves internal consistency, not when the chain existed. Each UTC day, per agent, the seal workflow:

  1. Builds a Merkle tree (RFC 6962-style, with domain-separated leaf/node hashing to close the second-preimage forgery class) over the day’s chain_this_hash values.
  2. Signs {tenant_id, agent_id, date, merkle_root, chain_head_hash, chain_head_index, event_count} (JCS-canonicalized) and publishes the seal to a public R2 path.
  3. Submits the Merkle root to multiple OpenTimestamps calendars concurrently (real protocol, per-calendar retry with exponential backoff); the resulting proof commits the root into the Bitcoin blockchain.

The result: for any past day, an independent party can confirm that this exact set of events, in this exact order, existed no later than the Bitcoin block the proof lands in — a timestamp guarantee that does not depend on trusting TruthLayer, Cloudflare, or the tenant. Sealing is idempotent by construction (Ed25519 is deterministic), so re-runs cannot create conflicting seals.

3.4 Independent verification

tools/ledger-verify is a standalone Node CLI with zero Cloudflare dependencies that verifies an agent-day using only public artifacts: the tenant registry (public/tenants/{id}.json — all root key generations plus all subkey certificates), the published seal, and the OTS proof. It recomputes the seal hash, resolves the seal’s key_id through the certificate chain (verifying the certificate’s own signature against the root generation it names, and that the seal’s signing time falls inside the subkey’s validity window), verifies the Ed25519 signature, and confirms the anchor proof exists. Full Bitcoin block-inclusion verification is delegated to the standard ots verify tool rather than reimplemented.

The same verifier accepts a self-contained evidence bundle — a single JSON export of every artifact needed for a date range — so an auditor or insurer can archive the evidence and verify it years later, offline, against nothing but mathematics. Exports fail closed: a day without a published seal cannot be packaged as evidence, because an unsealed day has no Merkle root or anchor to verify against.


4. Ingest: authenticated, idempotent, one round trip

Six webhook routes cover the observation surface (/ingest/ai-gateway, monetization-gateway, sandbox, mcp, egress, generic). Each is authenticated by a per-source HMAC-SHA256 signature over the raw request body, verified in constant time before any parsing. Timestamps more than five minutes in the future are rejected outright (the chain, not the client clock, orders the ledger). The egress route consumes Logpush NDJSON batches with all-or-nothing validation.

A verified event then makes exactly one Durable Object call — AgentDO.ingest() — which performs, atomically within the single-writer object:

  1. Idempotency: exact-match dedup on (source, source_event_id) with 24-hour retention. Replays return 200 {duplicate:true} without touching the chain.
  2. Admission: kill-switch state. A killed agent’s events become agent_killed gap markers; a throttled agent gets a real requests-per-minute budget with atomic slot reservation.
  3. Quota: the agent’s own hourly spend cap. Over-cap events become quota_exceeded gap markers, and deliberately stay retryable (the dedup key is only recorded once quota clears).
  4. Append + sign: chain construction and a local subkey signature (§3.2).

Every response — success or gap — carries the agent’s current agent_status. This is the kill-switch’s distribution channel (§6): the tenant’s integration is already reading these responses on every event, so a killed status reaches it on the very next call with no additional infrastructure and no TruthLayer credential inside the tenant’s estate.


5. Behavioral anomaly detection

Detection runs as a scheduled Cloudflare Workflow (hourly, plus a deeper nightly pass) computing eight features per agent over a 7-day window:

FeatureSignal
spend_velocity_zz-score of the last hour’s spend vs. the trailing week
tool_category_klKL divergence of the 24h event-category mix vs. baseline
mcp_counterparty_jaccardset drift of MCP servers contacted
sandbox_exit_failure_ratenon-zero-exit fraction of sandbox processes
x402_counterparty_hhipayment-concentration (Herfindahl) shift
capability_envelope_violation_counttool calls outside the agent’s declared allowlist
prompt_embedding_drift_cosnightly: cosine drift of prompt centroids (Workers AI, bge-large)
completion_embedding_drift_cosnightly: same for completions

Features feed a weighted logistic score with fixed thresholds — T1 > 0.60 (record), T2 > 0.80 (throttle to 10 rpm + alert), T3 > 0.95 (kill + page). Weights are tenant-overridable as data (never tenant-authored code), with defaults tuned empirically — the highest weights sit on capability-envelope violations and MCP counterparty drift, and minimum-sample guards were added after early tuning drove the false-positive rate to 60% on sparse windows.

Two honesty mechanisms are structural:


6. Enforcement: the kill-switch

TruthLayer is a webhook receiver, not an inline proxy — it deliberately holds no credentials for the tenant’s own infrastructure. Enforcement therefore uses two mechanisms that don’t require any:

  1. Ingest-boundary enforcement. Throttle/kill state lives in the AgentDO and gates admission on every subsequent event (§4). The agent_status field in every ingest response is the propagation channel: the tenant’s integration self-enforces (stops its sandbox, halts its agent loop) within one event of the action. Every throttle, kill, and reactivation is itself recorded as a signed, payload-backed ledger event — the enforcement history is part of the evidence.
  2. AI Gateway spend limits (defense in depth). If a tenant supplies a scoped AI Gateway credential, a kill also applies a real $0 per-agent spend-limit rule at Cloudflare’s AI Gateway — a hard stop on LLM spend even if the tenant’s integration ignores agent_status. Reactivation deliberately does not silently undo this (there is no “remove limit” API, only replace), and the operator console surfaces that asymmetry rather than hiding it.

Actions originate from the anomaly workflow (automated, subject to the precision guardrail) or from a human operator via the dashboard, where every action requires a stated reason and is attributed — server-side, from the operator’s verified identity, never client-supplied — in the signed event itself.


7. Access surfaces and trust boundaries

Three read/control surfaces exist, each with a deliberately different trust model:

Secrets discipline is uniform: every private key, API token, and JWT secret at rest is wrapped under a platform KEK; plaintext secrets are returned at most once at creation; nothing sensitive crosses an RPC boundary that doesn’t need to. Nightly encrypted exports of every Durable Object’s full state provide disaster recovery without a plaintext copy ever landing in R2.


8. Performance and hardening: measured, not projected

TruthLayer’s engineering discipline is that results are logged honestly, including misses. The hardening program (chaos suite of ten fault-injection scenarios, per-IP flood controls, encrypted backups, payload sharding) culminated in sustained live load testing of the deployed system with real HMAC-signed traffic against a pool of 500 real tenant/agent pairs.

The original architecture missed its target. The initial ingest path made four sequential cross-Durable-Object round trips per event (tenant admission → agent admission → append → a nested signing call back to the tenant object, since only the tenant held signing keys). Measured ceiling: ~4,700 events/sec sustained, p99 ≈ 1.8s against a 10,000/sec, sub-500ms target. Server CPU time was 1–4ms per request; the gap was pure RPC wait. Storage sharding (payloads spread across 8 R2 buckets by consistent tenant hash) fixed a real background-write reliability ceiling but, as predicted and confirmed, did not move request latency.

The single-hop redesign. The subkey hierarchy (§3.2) exists precisely to fix this: with signing local to the AgentDO and tenant policy cached (its ingest-relevant fields are immutable after creation), the entire ingest decision — idempotency, admission, quota, append, signature — collapses into one Durable Object call with zero mid-request RPCs, while the auditor-facing trust anchor (the public registry) is unchanged.

Measured results after the redesign (same methodology, 30-minute sustained run from a single generator machine): 6,042 req/s at 99.99% success, with p50 at moderate rates down from ~180ms to 25–59ms — confirming the RPC chain was gone from the request path, but leaving open whether the residual gap to 10k/s was the platform or the single-machine test rig (one source IP, one TLS origin — not what real 10k/s inflow looks like).

Distributed edge load generation answered that question. A Workers-based generator fleet — Durable Object lanes placed across all nine placement regions, each HMAC-signing and firing real ingest requests from its own colo, with measured egress from 16+ points of presence worldwide — removed the client from the equation:

4-hop architectureSingle-hop, single-machine rigSingle-hop, edge fleet
Sustained throughput4,728 req/s6,042 req/s14,638 req/s
Run30 min, 10.9M req30 min, 10.9M req10 min, 9.51M req
Success rate99.82%99.99%99.98%
p50 / p99~180ms / 1.8s202ms / 3.4s143ms / 1.8s
10k/s targetnot metnot metmet — exceeded by 46%

The earlier “ceilings” were the client rig, not the platform. Per-stage instrumentation (permanent, sampled structured timing markers deployed before the run, cross-checked against per-invocation CPU accounting) attributes the budget at saturation precisely: the entire in-object ingest decision — idempotency, admission, quota, chain append, Ed25519 signature, SQLite commit — costs ~1–2ms of CPU per event, flat from 4k to 14.6k req/s, with ~1ms more in the stateless worker. Essentially all remaining request latency is geographic round-trip time from worldwide callers to where each agent’s Durable Object happens to live, plus tail queueing. No shared resource curves upward with load: the design behaves as the coordination-free, shard-per-agent system it is, and its throughput limit scales with agent count rather than any central constraint.

The still-unmet half of the target is honest and specific: p99 latency (1.8s at 14.6k/s with worldwide traffic) exceeds the sub-500ms bar, and the instrumentation shows this is a data placement property — Durable Objects migrate toward their callers over time, and this test pool’s objects all lived in one region while its traffic suddenly came from everywhere — not a compute, signing, or serialization cost.

Two semantic changes shipped with the redesign, both documented rather than silent: idempotency dedup narrowed from tenant-wide to per-agent (retried deliveries always land on the same agent object, so replay protection is preserved), and the hourly spend quota moved from a tenant-wide aggregate to each agent’s own declared cap — finer-grained, and enforceable without cross-object coordination.


9. Product tiers and business model

TenantRecord.tier defines three commercial tiers, billed via Stripe:

On top of subscriptions, TruthLayer takes 1% of x402 payment volume flowing through observed agents — inherited from the Monetization Gateway’s own accounting, never separately re-counted from Stripe (a spec-level non-negotiable: the ledger, not a second bookkeeping system, is the source of truth; $10,000 of observed monthly x402 volume reconciles to a $100 invoice item, with idempotency delegated to Stripe’s own guarantees). The insurance thesis is the long-term business: an insurer cannot underwrite what cannot be audited, and TruthLayer’s artifact set — signed events, sealed days, anchored roots, signed anomaly and enforcement history, permissionless verification — is designed to be the underwriting substrate for autonomous-agent policies.


10. Threat model summary

AdversaryMitigation
Agent forges/suppresses its own historyCapture at the network layer; agent holds no keys, needs no SDK, cannot bypass the chokepoint it already transits
Tenant edits history after an incidentHash chain + published daily seals + Bitcoin anchor: revision is evident to any verifier
TruthLayer edits historySame: seals and OTS proofs are public and independently verifiable; TruthLayer cannot rewrite a Bitcoin block
Compromised AgentDO / leaked subkeyBlast radius = one agent × ≤48h validity window; certificate chain and validity check are enforced by the offline verifier
Forged ingest trafficPer-source HMAC over the raw body, constant-time verification, replay dedup, future-timestamp rejection
Silent refusal / selective droppingSigned gap_markers — refusal itself is chained evidence
Detector goes bad (silent degradation)Self-computed precision guardrail freezes automated enforcement below 0.70 precision while continuing to record honestly
Runaway spendPer-agent hourly caps at admission; AI Gateway $0 spend rules as an independent second layer
Flood/abuse of public endpointsPer-IP flood ceilings ahead of any crypto work; HMAC rejects unauthenticated volume cheaply
Operator abuseCloudflare Access + origin JWT verification; every mutating action attributed server-side and signed into the ledger

11. Current status and known limitations

The platform is deployed and live: all eleven workers, both Durable Object classes, the sharded R2 topology, the Access-gated operator console, and the billing pipeline. The build was executed phase-by-phase with per-phase definitions of done, each verified by real tests (unit, integration, property-based, chaos, and browser end-to-end) before the next phase began.

Honest open items, tracked rather than hidden:


12. Conclusion

The premise of TruthLayer is that trust in autonomous agents will not come from better self-reporting — it will come from evidence that survives hostile scrutiny. By observing agents at a network layer they cannot avoid, committing every action to a signed hash chain under keys the agent never touches, sealing each day under a Merkle root anchored in Bitcoin, and making verification permissionless and offline, TruthLayer turns “what did this agent do?” from a question about logs into a question about mathematics.

The system is built, deployed, measured, and — where it falls short of its own targets — says so in writing. That discipline is not incidental: a platform whose product is evidence must hold its own engineering record to the same standard.


TruthLayer runs on Cloudflare Workers, Durable Objects (SQLite), R2, Workflows, Workers AI, AI Gateway, and Cloudflare Access. Verification requires none of these: ledger-verify is a standalone tool with no Cloudflare dependencies, and all verification artifacts are public.