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

ParameterTypeDefaultDescription
pageinteger0Page number (0-indexed)
page_sizeinteger100Items per page (max 1000)
outcomestringnullFilter by outcome: success, error, blocked
action_namestringnullFilter by exact action name
agent_idstringnullFilter by agent identifier
run_idUUIDnullFilter by parent run
min_costfloatnullMinimum cost in USD
max_costfloatnullMaximum cost in USD
start_dateISO 8601nullFilter actions after this date
end_dateISO 8601nullFilter actions before this date
searchstringnullSearch across action names, agent IDs, outcomes
sort_byenumtimestampSort field: timestamp, cost, duration, name
sort_orderenumdescSort direction: asc, desc

Response

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "database_query",
      "outcome": "error",
      "cost_usd": 0.05,
      "duration_ms": 1234.5,
      "inputs": {
        "query": "SELECT * FROM users WHERE id = ?",
        "params": [123]
      },
      "outputs": {
        "error": "Connection timeout"
      },
      "run_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "run_status": "failed",
      "agent_id": "prod-agent-3",
      "timestamp": "2024-12-28T10:30:00.123456Z",
      "compliance_metadata": null,
      "organization_id": null
    }
  ],
  "count": 1,
  "page": 0,
  "page_size": 50,
  "total_pages": 1
}

Example: Find Failed Actions

curl -X GET "https://api.agent-sentinel.dev/api/v1/ledger?outcome=error&sort_by=cost&sort_order=desc" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example: Search Actions

curl -X GET "https://api.agent-sentinel.dev/api/v1/ledger?search=database&page_size=50" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example: Date Range Query

curl -X GET "https://api.agent-sentinel.dev/api/v1/ledger?start_date=2024-12-01T00:00:00Z&end_date=2024-12-31T23:59:59Z" \
  -H "Authorization: Bearer YOUR_TOKEN"

GET /api/v1/ledger/stats

Get aggregate statistics for the activity ledger.

Query Parameters

ParameterTypeDefaultDescription
start_dateISO 8601nullStart date for stats calculation
end_dateISO 8601nullEnd date for stats calculation
agent_idstringnullCalculate stats for specific agent

Response

{
  "total_actions": 4200,
  "total_cost_usd": 42.50,
  "success_count": 4120,
  "error_count": 75,
  "blocked_count": 5,
  "average_duration_ms": 234.5,
  "unique_agents": 12,
  "unique_action_types": 45
}

Example: Monthly Stats

curl -X GET "https://api.agent-sentinel.dev/api/v1/ledger/stats?start_date=2024-12-01T00:00:00Z&end_date=2024-12-31T23:59:59Z" \
  -H "Authorization: Bearer YOUR_TOKEN"

GET /api/v1/ledger/export

Export ledger data for compliance audits and offline analysis.

Query Parameters

ParameterTypeDefaultDescription
formatenumjsonlExport format: jsonl, json, csv
outcomestringnullFilter by outcome
action_namestringnullFilter by action name
agent_idstringnullFilter by agent
start_dateISO 8601nullDate range start
end_dateISO 8601nullDate range end
limitinteger10000Maximum records (max 100,000)

Response

File download in requested format.

Example: Export as JSONL

curl -X GET "https://api.agent-sentinel.dev/api/v1/ledger/export?format=jsonl&limit=1000" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o ledger.jsonl

Example: Export Failed Actions as CSV

curl -X GET "https://api.agent-sentinel.dev/api/v1/ledger/export?format=csv&outcome=error" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o failed_actions.csv

Response Schema

LedgerEntry

interface LedgerEntry {
  // Core Action Data
  id: string;              // UUID
  name: string;            // Action name (e.g., "send_email", "database_query")
  outcome: string;         // "success", "error", "blocked", etc.
  cost_usd: number;        // Cost in USD
  duration_ms: number;     // Execution duration
  
  // Payload
  inputs: Record<string, any> | null;    // Action inputs/arguments
  outputs: Record<string, any> | null;   // Action outputs/return value
  
  // Context
  run_id: string;          // UUID of parent run
  run_status: string;      // "running", "completed", "failed"
  agent_id: string | null; // Agent identifier
  timestamp: string;       // ISO 8601 timestamp
  
  // Compliance (Enterprise Tier)
  compliance_metadata: ComplianceMetadata | null;
  
  // Organization
  organization_id: string | null;
}

ComplianceMetadata (Enterprise Tier)

interface ComplianceMetadata {
  // Human-in-the-Loop (EU AI Act Article 14)
  requires_human_approval?: boolean;
  approval_status?: "not_required" | "pending" | "approved" | "rejected" | "timeout";
  human_in_the_loop_id?: string;
  human_in_the_loop_email?: string;
  approval_timestamp?: string;
  approval_notes?: string;
  
  // Decision Transparency
  decision_rationale?: string;
  confidence_score?: number;
  alternative_actions_considered?: string[];
  
  // Data Lineage
  input_data_sources?: Array<{
    source: string;
    version: string;
    table?: string;
  }>;
  model_card?: {
    name: string;
    version: string;
    provider: string;
    system_prompt_hash?: string;
  };
  
  // Audit Flags
  policy_violations_checked?: string[];
  override_reason?: string;
}

Common Patterns

1. Debugging Failed Actions

import requests

def find_failed_actions(api_key: str, action_name: str):
    """Find all failed instances of a specific action."""
    url = "https://api.agent-sentinel.dev/api/v1/ledger"
    params = {
        "outcome": "error",
        "action_name": action_name,
        "sort_by": "timestamp",
        "sort_order": "desc",
        "page_size": 100,
    }
    headers = {"Authorization": f"Bearer {api_key}"}
    
    response = requests.get(url, params=params, headers=headers)
    response.raise_for_status()
    
    data = response.json()
    print(f"Found {data['count']} failed {action_name} actions")
    
    for entry in data['data']:
        print(f"[{entry['timestamp']}] {entry['name']} - {entry['outputs']['error']}")
    
    return data['data']

# Usage
failed_queries = find_failed_actions("sk_...", "database_query")

2. Cost Analysis by Agent

def analyze_agent_costs(api_key: str, agent_id: str):
    """Calculate total cost for a specific agent."""
    url = "https://api.agent-sentinel.dev/api/v1/ledger/stats"
    params = {"agent_id": agent_id}
    headers = {"Authorization": f"Bearer {api_key}"}
    
    response = requests.get(url, params=params, headers=headers)
    response.raise_for_status()
    
    stats = response.json()
    print(f"Agent: {agent_id}")
    print(f"Total Actions: {stats['total_actions']}")
    print(f"Total Cost: ${stats['total_cost_usd']:.2f}")
    print(f"Average Duration: {stats['average_duration_ms']:.0f}ms")
    print(f"Success Rate: {stats['success_count'] / stats['total_actions'] * 100:.1f}%")
    
    return stats

# Usage
stats = analyze_agent_costs("sk_...", "prod-agent-3")

3. Compliance Audit Export

def export_compliance_report(api_key: str, start_date: str, end_date: str):
    """Export all actions for a date range (for compliance audits)."""
    url = "https://api.agent-sentinel.dev/api/v1/ledger/export"
    params = {
        "format": "csv",
        "start_date": start_date,
        "end_date": end_date,
        "limit": 100000,
    }
    headers = {"Authorization": f"Bearer {api_key}"}
    
    response = requests.get(url, params=params, headers=headers)
    response.raise_for_status()
    
    filename = f"compliance_report_{start_date}_{end_date}.csv"
    with open(filename, "wb") as f:
        f.write(response.content)
    
    print(f"Exported compliance report to {filename}")
    return filename

# Usage
export_compliance_report(
    "sk_...",
    "2024-10-01T00:00:00Z",
    "2024-12-31T23:59:59Z"
)

4. Real-Time Monitoring

import time

def monitor_failures(api_key: str, interval_seconds: int = 60):
    """Monitor for new failures in real-time."""
    url = "https://api.agent-sentinel.dev/api/v1/ledger"
    headers = {"Authorization": f"Bearer {api_key}"}
    
    last_seen_id = None
    
    while True:
        params = {
            "outcome": "error",
            "sort_by": "timestamp",
            "sort_order": "desc",
            "page_size": 10,
        }
        
        response = requests.get(url, params=params, headers=headers)
        response.raise_for_status()
        
        data = response.json()
        new_failures = []
        
        for entry in data['data']:
            if entry['id'] == last_seen_id:
                break
            new_failures.append(entry)
        
        if new_failures:
            last_seen_id = new_failures[0]['id']
            for failure in reversed(new_failures):
                print(f"🚨 NEW FAILURE: {failure['name']} - {failure['outputs'].get('error', 'Unknown error')}")
        
        time.sleep(interval_seconds)

# Usage (runs indefinitely)
monitor_failures("sk_...")

Authentication

All ledger endpoints require authentication via:
  1. JWT Bearer Token
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
    
  2. API Key (recommended for programmatic access)
    Authorization: sk_1234567890abcdef
    
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

Feature/runs/ledger
StructureHierarchical (Run → Actions)Flat (all actions)
ScopeSingle run at a timeAll runs combined
FilteringBy run propertiesBy action properties
Use CaseInspect specific runAudit trail, search
SortingActions within runCross-run sorting
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

# DON'T: Fetch all 10,000 actions at once
response = requests.get("/api/v1/ledger?page_size=10000")

# DO: Paginate through results
page = 0
while True:
    response = requests.get(f"/api/v1/ledger?page={page}&page_size=100")
    data = response.json()
    process_entries(data['data'])
    
    if page >= data['total_pages'] - 1:
        break
    page += 1

2. Use Search for Flexible Queries

# Instead of exact matching:
response = requests.get("/api/v1/ledger?action_name=database_query")

# Use search for partial matches:
response = requests.get("/api/v1/ledger?search=database")

3. Filter by Date Range for Performance

# DON'T: Query all historical data
response = requests.get("/api/v1/ledger")

# DO: Limit to relevant time window
response = requests.get("/api/v1/ledger?start_date=2024-12-01T00:00:00Z&end_date=2024-12-31T23:59:59Z")

4. Use Stats Endpoint for Aggregates

# DON'T: Fetch all actions and calculate manually
actions = requests.get("/api/v1/ledger?page_size=10000").json()
total_cost = sum(a['cost_usd'] for a in actions['data'])

# DO: Use stats endpoint
stats = requests.get("/api/v1/ledger/stats").json()
total_cost = stats['total_cost_usd']

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 or reach out to support.