Skip to main content

Provenance Tracking

Provenance Tracking

Create verifiable, immutable records of every AI action for compliance, debugging, and trust.

In a world where AI agents make consequential decisions, knowing exactly what happened, who authorized it, and why is critical. This pattern shows you how to implement comprehensive provenance tracking for all agent actions.

When to Use This

  • ✅ You need compliance audit trails (HIPAA, SOC 2, GDPR)
  • ✅ You want to debug agent behavior in production
  • ✅ You need to prove who authorized specific actions
  • ✅ You're building systems where accountability matters

Architecture

┌─────────────────────────────────────────────────────┐
│              AI Agent Action                         │
│   (process invoice, approve transaction, etc.)      │
└────────────────────┬────────────────────────────────┘
                     │
                     ▼
          ┌──────────────────────┐
          │   Provenance Logger  │
          │   (captures context) │
          └──────────┬───────────┘
                     │
                     ▼
      ┌──────────────────────────────┐
      │   Provenance Entry           │
      │   - Who (Passport ID)        │
      │   - What (action)            │
      │   - When (timestamp)         │
      │   - Why (delegation/approval)│
      │   - Input/Output             │
      │   - Cryptographic signature  │
      └──────────┬───────────────────┘
                 │
                 ▼
    ┌────────────────────────────────┐
    │   Distributed Ledger           │
    │   (immutable, verifiable)      │
    └────────────────────────────────┘

Prerequisites

  • API key
  • Agent Passport ID
  • Delegation token (to prove authorization)
  • Understanding of what actions need tracking

Implementation

Log Agent Actions

Record every significant action with full context:

TypeScript:
```typescript
import { HumanClient } from '@human/sdk';

const client = new HumanClient({
  apiKey: process.env.HUMAN_API_KEY,
});

// Log an agent action with full provenance
const provenanceEntry = await client.provenance.log({
  actor: 'agent_invoice_processor_001',
  actorType: 'agent',
  action: 'process_invoice',
  resource: 'invoice_INV_12345',
  resourceType: 'invoice',
  input: {
    invoiceId: 'INV_12345',
    amount: 5000.00,
    vendor: 'Acme Supplies',
  },
  output: {
    approved: false,
    reason: 'Amount exceeds agent approval limit ($1000)',
    escalatedTo: 'passport_alice_cfo',
  },
  riskLevel: 'medium',
  delegation: {
    token: 'delegation_token_abc123',
    grantedBy: 'passport_bob_manager',
    scope: ['invoice_processing'],
  },
  timestamp: new Date().toISOString(),
  metadata: {
    processingTime: 1234, // ms
    model: 'gpt-4',
    confidence: 0.87,
  },
});

console.log(`Provenance logged: ${provenanceEntry.provenanceId}`);
console.log(`Ledger reference: ${provenanceEntry.ledgerRef}`);
```

Python:
```python
from human_sdk import HumanClient
from datetime import datetime

client = HumanClient(api_key=os.environ["HUMAN_API_KEY"])

# Log an agent action with full provenance
provenance_entry = client.provenance.log(
    actor="agent_invoice_processor_001",
    actor_type="agent",
    action="process_invoice",
    resource="invoice_INV_12345",
    resource_type="invoice",
    input={
        "invoice_id": "INV_12345",
        "amount": 5000.00,
        "vendor": "Acme Supplies",
    },
    output={
        "approved": False,
        "reason": "Amount exceeds agent approval limit ($1000)",
        "escalated_to": "passport_alice_cfo",
    },
    risk_level="medium",
    delegation={
        "token": "delegation_token_abc123",
        "granted_by": "passport_bob_manager",
        "scope": ["invoice_processing"],
    },
    timestamp=datetime.utcnow().isoformat(),
    metadata={
        "processing_time": 1234,  # ms
        "model": "gpt-4",
        "confidence": 0.87,
    }
)

print(f"Provenance logged: {provenance_entry.provenance_id}")
print(f"Ledger reference: {provenance_entry.ledger_ref}")
```

Go:
```go
import (
    "time"
    "github.com/human/sdk-go"
)

client := human.NewClient(os.Getenv("HUMAN_API_KEY"))

// Log an agent action with full provenance
provenanceEntry, err := client.Provenance.Log(&human.ProvenanceEntry{
    Actor:        "agent_invoice_processor_001",
    ActorType:    "agent",
    Action:       "process_invoice",
    Resource:     "invoice_INV_12345",
    ResourceType: "invoice",
    Input: map[string]interface{}{
        "invoice_id": "INV_12345",
        "amount":     5000.00,
        "vendor":     "Acme Supplies",
    },
    Output: map[string]interface{}{
        "approved":     false,
        "reason":       "Amount exceeds agent approval limit ($1000)",
        "escalated_to": "passport_alice_cfo",
    },
    RiskLevel: "medium",
    Delegation: &human.DelegationInfo{
        Token:     "delegation_token_abc123",
        GrantedBy: "passport_bob_manager",
        Scope:     []string{"invoice_processing"},
    },
    Timestamp: time.Now().UTC().Format(time.RFC3339),
    Metadata: map[string]interface{}{
        "processing_time": 1234, // ms
        "model":           "gpt-4",
        "confidence":      0.87,
    },
})

if err != nil {
    log.Fatal(err)
}

fmt.Printf("Provenance logged: %s\n", provenanceEntry.ProvenanceID)
fmt.Printf("Ledger reference: %s\n", provenanceEntry.LedgerRef)
```

REST API:
```bash
curl -X POST https://api.human.ai/v1/provenance/log \\
  -H "Authorization: Bearer $HUMAN_API_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{
    "actor": "agent_invoice_processor_001",
    "actorType": "agent",
    "action": "process_invoice",
    "resource": "invoice_INV_12345",
    "resourceType": "invoice",
    "input": {
      "invoiceId": "INV_12345",
      "amount": 5000.00,
      "vendor": "Acme Supplies"
    },
    "output": {
      "approved": false,
      "reason": "Amount exceeds agent approval limit ($1000)",
      "escalatedTo": "passport_alice_cfo"
    },
    "riskLevel": "medium",
    "delegation": {
      "token": "delegation_token_abc123",
      "grantedBy": "passport_bob_manager",
      "scope": ["invoice_processing"]
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "metadata": {
      "processingTime": 1234,
      "model": "gpt-4",
      "confidence": 0.87
    }
  }'
```

Query Provenance History

Retrieve audit trails for compliance or debugging:

TypeScript:
```typescript
// Query provenance by actor
const actorHistory = await client.provenance.query({
  actor: 'agent_invoice_processor_001',
  startTime: '2024-01-01T00:00:00Z',
  endTime: '2024-01-31T23:59:59Z',
  actions: ['process_invoice', 'escalate_invoice'],
  limit: 100,
});

console.log(`Found ${actorHistory.length} actions`);
actorHistory.forEach(entry => {
  console.log(`${entry.timestamp}: ${entry.action} on ${entry.resource}`);
  console.log(`  Result: ${JSON.stringify(entry.output)}`);
  console.log(`  Authorized by: ${entry.delegation.grantedBy}`);
});

// Query provenance by resource
const resourceHistory = await client.provenance.query({
  resource: 'invoice_INV_12345',
  sortBy: 'timestamp',
  order: 'asc',
});

console.log(`\nInvoice INV_12345 history:`);
resourceHistory.forEach(entry => {
  console.log(`- ${entry.timestamp}: ${entry.actor} → ${entry.action}`);
});
```

Python:
```python
# Query provenance by actor
actor_history = client.provenance.query(
    actor="agent_invoice_processor_001",
    start_time="2024-01-01T00:00:00Z",
    end_time="2024-01-31T23:59:59Z",
    actions=["process_invoice", "escalate_invoice"],
    limit=100
)

print(f"Found {len(actor_history)} actions")
for entry in actor_history:
    print(f"{entry.timestamp}: {entry.action} on {entry.resource}")
    print(f"  Result: {entry.output}")
    print(f"  Authorized by: {entry.delegation.granted_by}")

# Query provenance by resource
resource_history = client.provenance.query(
    resource="invoice_INV_12345",
    sort_by="timestamp",
    order="asc"
)

print(f"\nInvoice INV_12345 history:")
for entry in resource_history:
    print(f"- {entry.timestamp}: {entry.actor} → {entry.action}")
```

Go:
```go
// Query provenance by actor
actorHistory, err := client.Provenance.Query(&human.ProvenanceQuery{
    Actor:     "agent_invoice_processor_001",
    StartTime: "2024-01-01T00:00:00Z",
    EndTime:   "2024-01-31T23:59:59Z",
    Actions:   []string{"process_invoice", "escalate_invoice"},
    Limit:     100,
})

if err != nil {
    log.Fatal(err)
}

fmt.Printf("Found %d actions\n", len(actorHistory))
for _, entry := range actorHistory {
    fmt.Printf("%s: %s on %s\n", entry.Timestamp, entry.Action, entry.Resource)
    fmt.Printf("  Result: %v\n", entry.Output)
    fmt.Printf("  Authorized by: %s\n", entry.Delegation.GrantedBy)
}

// Query provenance by resource
resourceHistory, err := client.Provenance.Query(&human.ProvenanceQuery{
    Resource: "invoice_INV_12345",
    SortBy:   "timestamp",
    Order:    "asc",
})

if err != nil {
    log.Fatal(err)
}

fmt.Println("\nInvoice INV_12345 history:")
for _, entry := range resourceHistory {
    fmt.Printf("- %s: %s → %s\n", entry.Timestamp, entry.Actor, entry.Action)
}
```

REST API:
```bash
# Query by actor
curl -X POST https://api.human.ai/v1/provenance/query \\
  -H "Authorization: Bearer $HUMAN_API_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{
    "actor": "agent_invoice_processor_001",
    "startTime": "2024-01-01T00:00:00Z",
    "endTime": "2024-01-31T23:59:59Z",
    "actions": ["process_invoice", "escalate_invoice"],
    "limit": 100
  }'

# Query by resource
curl -X POST https://api.human.ai/v1/provenance/query \\
  -H "Authorization: Bearer $HUMAN_API_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{
    "resource": "invoice_INV_12345",
    "sortBy": "timestamp",
    "order": "asc"
  }'
```

Verify Provenance

Cryptographically verify that a provenance entry is authentic and hasn't been tampered with:

TypeScript:
```typescript
// Verify provenance entry
const verification = await client.provenance.verify({
  provenanceId: 'prov_abc123',
  ledgerRef: '0x1234...5678',
});

if (verification.valid) {
  console.log('✅ Provenance entry is authentic');
  console.log(`Anchored at: ${verification.ledgerTimestamp}`);
  console.log(`Block: ${verification.blockNumber}`);
  console.log(`Signature valid: ${verification.signatureValid}`);
} else {
  console.error('❌ Provenance entry verification failed');
  console.error(`Reason: ${verification.reason}`);
}
```

Python:
```python
# Verify provenance entry
verification = client.provenance.verify(
    provenance_id="prov_abc123",
    ledger_ref="0x1234...5678"
)

if verification.valid:
    print("✅ Provenance entry is authentic")
    print(f"Anchored at: {verification.ledger_timestamp}")
    print(f"Block: {verification.block_number}")
    print(f"Signature valid: {verification.signature_valid}")
else:
    print("❌ Provenance entry verification failed")
    print(f"Reason: {verification.reason}")
```

Go:
```go
// Verify provenance entry
verification, err := client.Provenance.Verify(&human.ProvenanceVerification{
    ProvenanceID: "prov_abc123",
    LedgerRef:    "0x1234...5678",
})

if err != nil {
    log.Fatal(err)
}

if verification.Valid {
    fmt.Println("✅ Provenance entry is authentic")
    fmt.Printf("Anchored at: %s\n", verification.LedgerTimestamp)
    fmt.Printf("Block: %d\n", verification.BlockNumber)
    fmt.Printf("Signature valid: %v\n", verification.SignatureValid)
} else {
    fmt.Println("❌ Provenance entry verification failed")
    fmt.Printf("Reason: %s\n", verification.Reason)
}
```

REST API:
```bash
curl -X POST https://api.human.ai/v1/provenance/verify \\
  -H "Authorization: Bearer $HUMAN_API_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{
    "provenanceId": "prov_abc123",
    "ledgerRef": "0x1234...5678"
  }'
```

Use Cases

shield:Compliance Audits|Prove to auditors exactly what agents did and who authorized it
bug:Debugging|Trace back through agent decision history to find where things went wrong
scales:Legal Evidence|Provide verifiable records for legal proceedings or disputes
chart-bar:Performance Analysis|Analyze agent behavior patterns to improve workflows

Best Practices

What to Log

  • All high-risk actions (financial transactions, data modifications)
  • Human approval decisions (approve/reject with reasoning)
  • Escalations (when agents defer to humans)
  • Errors and failures (with context for debugging)
  • Access to sensitive data (who accessed what, when)

Log Quality

  • Include full context - input, output, delegation, risk level
  • Use structured data - avoid free-form text logs
  • Timestamp precisely - use UTC and include milliseconds
  • Capture model details - which AI model, version, confidence
  • Log synchronously - don't lose logs due to async failures

Performance

  • Batch logging for high-frequency actions
  • Use async writes where latency matters
  • Set retention policies based on compliance needs
  • Index by common query patterns (actor, resource, time)

Security Considerations

do:Log all provenance entries to the immutable ledger
do:Include cryptographic signatures for tamper detection
do:Restrict provenance queries to authorized entities only
do:Encrypt sensitive data in log inputs/outputs
dont:Log credentials, API keys, or secrets in provenance
dont:Allow provenance entries to be deleted or modified
dont:Expose provenance data without access control
dont:Skip logging for "unimportant" actions (everything matters)

Common Patterns

Pattern: Auto-Logging Wrapper

function withProvenance<T>(
  agent: Agent,
  action: string,
  fn: () => Promise<T>
): Promise<T> {
  return client.provenance.trackAction({
    actor: agent.passportId,
    action,
    execute: async () => {
      const result = await fn();
      return result;
    },
  });
}

// Usage
const result = await withProvenance(
  invoiceAgent,
  'process_invoice',
  () => processInvoice(invoice)
);

Pattern: Provenance Chain

async function getProvenanceChain(resourceId: string) {
  const entries = await client.provenance.query({
    resource: resourceId,
    sortBy: 'timestamp',
    order: 'asc',
  });

  // Build dependency chain
  const chain = entries.map((entry, idx) => ({
    step: idx + 1,
    actor: entry.actor,
    action: entry.action,
    timestamp: entry.timestamp,
    authorized_by: entry.delegation?.grantedBy,
    verified: entry.ledgerRef !== null,
  }));

  return chain;
}

See Also

← All patterns