Skip to main content
The Activity Ledger provides a chronological, filterable view of every action taken by your agents across all runs. This is the compliance substrate, audit evidence, and organizational memory for Agent Sentinel.

Overview

Unlike the /runs endpoints which are hierarchical (Run → Actions), the ledger provides a flat, chronological stream of all actions with advanced filtering and search capabilities.

Key Use Cases

  1. Compliance Audits: “Show me all high-risk actions in Q4 2024”
  2. Debugging: “Find all failed database_query actions”
  3. Cost Analysis: “What are my most expensive actions?”
  4. Security: “Show all actions by prod-agent-3 that were blocked”
  5. Organizational Memory: “What did our agents do last week?”

Endpoints

GET /api/v1/ledger

Query the activity ledger with filtering, sorting, and pagination.

Query Parameters

Response

Example: Find Failed Actions

Example: Search Actions

Example: Date Range Query


GET /api/v1/ledger/stats

Get aggregate statistics for the activity ledger.

Query Parameters

Response

Example: Monthly Stats


GET /api/v1/ledger/export

Export ledger data for compliance audits and offline analysis.

Query Parameters

Response

File download in requested format.

Example: Export as JSONL

Example: Export Failed Actions as CSV


GET /api/v1/ledger/verify

Re-derive an organization’s row hash chain from stored data and report whether it’s intact.

Query Parameters

Non-superusers may only verify their own active organization’s chain; requesting a different organization_id returns 403.

Response

valid is true only when every check passes. first_bad_seq is the earliest seq whose stored row_hash no longer matches what’s recomputed from its current fields and prev_hash — evidence that row (or an earlier one) was altered or deleted after it was chained. signatures_checked counts the signed rows whose Ed25519 signature was verified against the platform public key (unsigned pre-signing rows are skipped), and first_bad_signature_seq is the earliest signed row whose signature does not verify over its stored row_hash. head_seq is where the organization’s signed ledger head says the chain ends, and head_matches is false when the chain’s last row isn’t that head (rows were deleted from the end), the head is missing, or the head’s signature doesn’t verify. Both are null for a ranged check (to_seq given), which stops before the tail by design and does not consult the head. See Integrity vs. authenticity.

Example


Hash Chain & Signing

Every ledger row is chained to the previous row written for its organization, and optionally Ed25519-signed:
  • seq — gap-free, per-organization sequence number. Concurrent ingest batches to the same organization can’t produce duplicate or gapped values.
  • prev_hash — the previous row’s row_hash (null for the first row in the chain).
  • row_hash — sha256 of the row’s immutable fields (everything set at ingest time, excluding compliance_metadata) plus prev_hash.
  • signature / key_id — Ed25519 signature of row_hash and the signing key used. Rows written before signing was enabled stay permanently unsigned (“pre-signing”, null) — enabling signing does not retroactively sign history. See Compliance.
  • compliance_metadata.log_hash / tamper_seal — mirror row_hash / signature, for tooling that only reads compliance_metadata.
Altering or deleting a historical row breaks the chain from that row forward: every subsequent row’s prev_hash stops matching, and GET /ledger/verify reports the first broken seq. Deleting the newest rows leaves the remaining chain intact, so the platform also keeps a signed ledger head, described below.

Ledger head

The platform records each organization’s chain head (the last seq and its row_hash) separately from the chain and signs it. A full verification (no to_seq) compares the chain’s last row with the head and reports the result as head_seq and head_matches. The chain is reported invalid when:
  • rows were removed from the end, so the last row no longer matches the head;
  • the chain has rows but no head;
  • the head is unsigned or its signature does not verify.
This makes truncating the newest rows detectable, not just editing or deleting rows in the middle.

Integrity vs. authenticity

Verification makes two independent guarantees, reported separately:
  • Chain integrity (first_bad_seq) — no row was altered or removed without breaking the links. This needs no key: anyone can recompute the hashes.
  • Authenticity (first_bad_signature_seq) — the platform key signed each stored row_hash. Because the hash chain alone is recomputable, someone with database access could edit a row and re-hash it (and every later row) so the chain still links up. They cannot re-sign those hashes without the private key, so the signature check catches the edit even when the chain is intact.
valid is true only when both pass. Pre-signing rows (signature: null) are skipped by the signature check, not failed — they verify on the chain alone, and signatures_checked counts only signed rows. Only null marks a pre-signing row: any non-null signature, including an empty string, is verified and fails if it does not match. Signed rows cannot be authenticated without the public key: if the platform has no key to verify against, every signed row is reported as bad rather than silently passed.

Response Schema

LedgerEntry

Actor / Counterparty

Every ledger row is self-describing: actor and counterparty record who did what without requiring a join through /runs. This is the same identity shape used across Agent Sentinel’s governance tables (agent id, principal, harness, key id, mandate reference), so it stays compatible with A2A agent cards and AP2/TAP mandate references.
actor is derived server-side from the verified API key/JWT plus the SDK’s X-Sentinel-* identity headers — it cannot be spoofed by the request body. counterparty is optional and comes from a counterparty field on the SDK’s ingest entry, for actions performed against or on behalf of another party (e.g. a buyer agent in an AP2 transaction).

ComplianceMetadata (Enterprise Tier)


Common Patterns

1. Debugging Failed Actions

2. Cost Analysis by Agent

3. Compliance Audit Export

4. Real-Time Monitoring


Authentication

All ledger endpoints require authentication via:
  1. JWT Bearer Token
  2. API Key (recommended for programmatic access)
See Authentication for details.

Access Control

  • Users can only see actions from their own runs
  • Superusers can see all actions across all users
  • Organization admins can see actions from their organization’s runs

Rate Limits

  • Query Endpoints: 1000 requests/hour
  • Export Endpoint: 100 requests/hour
  • Stats Endpoint: 600 requests/hour
For higher limits, contact support at hello@agentsentinel.dev.

Differences from /runs Endpoints

When to use /runs:
  • Inspecting a specific run’s execution flow
  • Debugging a single agent workflow
  • Viewing run-level metadata
When to use /ledger:
  • Compliance audits across all activity
  • Finding patterns across multiple runs
  • Cost analysis by action type
  • Security monitoring

Best Practices

1. Use Pagination for Large Results

2. Use Search for Flexible Queries

3. Filter by Date Range for Performance

4. Use Stats Endpoint for Aggregates


Troubleshooting

Empty Results

Problem: Query returns 0 results Solutions:
  1. Check filters - they may be too restrictive
  2. Verify date range includes expected data
  3. Ensure authentication is correct (not seeing another user’s data)
  4. Check that agents have actually executed actions

Slow Queries

Problem: Queries take >5 seconds Solutions:
  1. Reduce page size (100 instead of 1000)
  2. Add date range filters to limit data scanned
  3. Avoid search queries on large datasets
  4. Use stats endpoint for aggregates instead of fetching all data

Export Limits

Problem: “Export limit exceeded” error Solutions:
  1. Reduce date range or add more filters
  2. Export in batches using pagination
  3. Contact support for bulk export access


Feedback

Have suggestions for the ledger API? Open an issue on the SDK repo or reach out to support.