Select your language below, then copy the entire block and paste it into your agent’s system prompt, rules file (
.cursorrules, AGENTS.md, CLAUDE.md), or conversation context.The Prompt
- Python
- TypeScript
- Go
Click to expand the full Python agent prompt
Click to expand the full Python agent prompt
# Fact0 Integration Guide for AI Coding Agents — Python
You are integrating **Fact0** — a tamper-evident audit log and execution telemetry platform for AI agents.
- **Docs:** https://docs.fact0.io
- **API base:** https://api.fact0.io
- **Dashboard:** https://app.fact0.io
- **Full LLM context:** https://docs.fact0.io/llms-full.txt
---
## 1. Installation
```bash
pip install fact0-sdk
```
> **CRITICAL**: The PyPI package is `fact0-sdk`, NOT `fact0`. The import is `import fact0`.
Requires Python 3.10+.
---
## 2. Authentication
Get an API key from https://app.fact0.io → Settings → API Keys.
Keys are prefixed `f0_live_…`. They have a **scope**:
- `write` — can append audit events and ingest telemetry
- `read` — can query events, verify chains, export PDFs
```bash
export FACT0_API_KEY="f0_live_..."
```
---
## 3. Core Concepts
Fact0 has **two pipelines** — use both together for full coverage:
| Pipeline | Purpose | When to use |
|----------|---------|-------------|
| **Audit Log** | Tamper-evident, hash-chained compliance ledger | Every action that matters for security reviews: tool calls, data access, approvals, policy checks |
| **Telemetry** | Execution tracing with spans, DAGs, and replay | Debugging agent runs: model invocations, tool calls, state mutations, timing |
### Audit Event Shape
```json
{
"actor": {"id": "agent-1", "type": "agent"},
"action": "document.delete",
"resource": {"id": "doc_456", "type": "document", "name": "Q3 Report"},
"outcome": "success"
}
```
- **Actor types**: `"human"`, `"agent"`, `"system"`
- **Outcomes**: `"success"`, `"failure"`, `"error"`
- **metadata**: optional `dict` for extra context (IP, tokens, model name, etc.)
### Telemetry Span Types
```
TOOL_CALL — external tool/API invocation
MODEL_INVOCATION — LLM inference call
STATE_MUTATION — agent memory/state write
HUMAN_APPROVAL — human-in-the-loop decision gate
POLICY_EVALUATION — guardrail or policy check
CUSTOM — any other span
```
---
## 4. Python SDK — Full API Reference
### Client Setup
```python
import fact0
# Sync client (recommended for most use cases)
client = fact0.Client(api_key="f0_live_...")
# Async client (for FastAPI / asyncio agents)
async_client = fact0.AsyncClient(api_key="f0_live_...")
```
The client auto-reads `FACT0_API_KEY` from env if no key is passed.
### Audit Logging
```python
# Simple one-liner
client.audit.log(
actor={"id": "my-agent", "type": "agent"},
action="invoice.approve",
resource={"id": "inv_99", "type": "invoice", "name": "Q3 Invoice"},
outcome="success",
metadata={"amount_usd": 5000, "approver": "auto"},
)
# Batch (up to 1000 events)
client.audit.log_batch([
{"actor": {...}, "action": "...", "resource": {...}, "outcome": "success"},
# ...
])
# Flush pending events (client batches in background)
client.audit.flush()
```
### Audit Queries & Verification
```python
# List events with filters
events = client.audit.list_events(
action="document.delete",
actor_id="agent-1",
outcome="failure",
page=1,
page_size=50,
)
# Get single event
event = client.audit.get_event("evt_01HX3K...")
# Verify hash chain integrity
result = client.audit.verify()
# → {"valid": True, "events_checked": 31847, "root_hash": "sha256:..."}
# Export SOC 2-style PDF audit pack
pdf_bytes = client.audit.export_pdf(from_="2024-01-01", to="2024-06-01")
# Export evidence ZIP
zip_bytes = client.audit.export_evidence_pack(from_="2024-01-01", to="2024-06-01")
# Live SSE stream
for event in client.audit.stream_events():
print(event)
```
### Execution Telemetry (context manager — recommended)
```python
with client.telemetry.execution(
agent_id="research-bot",
agent_name="Research Bot",
trigger="user_query",
metadata={"query": "market analysis"},
) as ex:
# Track a tool call
with ex.span("web_search", span_type="TOOL_CALL") as span:
span.log_event("query_submitted", {"q": "AI market trends"})
results = do_search(...)
span.complete(
output={"results_count": len(results)},
tool_call={
"tool_name": "web_search",
"duration_ms": 320,
"input": {"inline": {"q": "AI market trends"}, "size_bytes": 48},
"output": {"inline": results, "size_bytes": 1024},
},
)
# Track an LLM call
with ex.span("gpt-4o", span_type="MODEL_INVOCATION") as span:
response = call_llm(...)
span.complete(
output={"summary": response.text[:200]},
model_invocation={
"model_name": "gpt-4o",
"model_provider": "openai",
"prompt_tokens": 820,
"completion_tokens": 190,
"total_tokens": 1010,
"latency_ms": 1240,
"temperature": 0.2,
"session_id": "session_9a2f1b",
"turn_sequence": 2,
"prompt_name": "customer-inquiry",
"prompt_version": 3,
"cost_usd": 0.0052,
},
)
# Track a human approval gate
with ex.span("manager_approval", span_type="HUMAN_APPROVAL") as span:
span.complete(
human_approval={
"approver_id": "user_reviewer",
"decision": "approved",
"comment": "LGTM",
},
)
# Execution auto-ends COMPLETED/FAILED based on exceptions
```
### Async Client
```python
async with fact0.AsyncClient(api_key="f0_live_...") as client:
await client.audit.log(
actor={"id": "agent-1", "type": "agent"},
action="document.read",
resource={"id": "doc_123", "type": "document"},
outcome="success",
)
async with client.telemetry.execution(agent_id="my-agent") as ex:
async with ex.span("search", span_type="TOOL_CALL") as span:
await span.complete(output={"result": "found"})
```
### Cleanup
```python
# Always flush and close when done
client.flush() # flushes both audit + telemetry queues
client.close() # stops background workers
```
---
## 5. Framework Integrations
### LangChain
```python
from fact0.integrations.langchain import Fact0CallbackHandler
handler = Fact0CallbackHandler(
client=client,
agent_id="my-langchain-agent",
audit_sensitive_actions=True,
)
chain.invoke({"input": "..."}, config={"callbacks": [handler]})
```
### FastAPI Middleware
```python
from fact0.integrations.fastapi import AuditMiddleware
app.add_middleware(
AuditMiddleware,
client_factory=lambda: client.audit,
action_prefix="api",
)
```
### OpenTelemetry (zero code changes)
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.fact0.io"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer f0_live_..."
```
---
## 6. REST API Quick Reference
### Audit API (base: https://api.fact0.io)
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/v1/events` | write | Append single event (async, returns receipt_id) |
| POST | `/v1/events/batch` | write | Append up to 1000 events |
| GET | `/v1/events` | read | List/filter events |
| GET | `/v1/events/{id}` | read | Get single event |
| GET | `/v1/events/{id}/verify` | read | Verify single event hash |
| GET | `/v1/verify` | read | Verify full chain integrity |
| GET | `/v1/events/stream` | read | Live SSE stream |
| GET | `/v1/export/pdf` | read | SOC 2 PDF audit pack |
| GET | `/v1/export/evidence-pack` | read | ZIP evidence pack |
| GET | `/v1/receipts/{id}` | read | Poll async ingest receipt |
### Telemetry API (base: https://api.fact0.io)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/executions` | Start execution |
| POST | `/api/v1/executions/{id}/spans` | Ingest spans |
| POST | `/api/v1/executions/{id}/events` | Ingest events |
| PUT | `/api/v1/executions/{id}/end` | End execution |
| GET | `/api/v1/executions` | List executions |
| GET | `/api/v1/executions/{id}/dag` | Get execution DAG |
| GET | `/api/v1/executions/{id}/replay` | Replay execution |
Auth header: `Authorization: Bearer f0_live_...`
---
## 7. Best Practices
1. **Dual-log high-value actions** — log to BOTH audit AND telemetry for tool calls, model invocations, and data access.
2. **Use context managers** — `with client.telemetry.execution(...)` auto-handles start/end and error status.
3. **Always call `client.flush()`** before process exit — the SDK batches in background threads.
4. **Use `parent_span_id`** for nested spans to build accurate DAGs in the dashboard.
5. **Set `agent_name`** on executions — it shows in the dashboard as a human-readable label.
6. **Include `metadata`** on both audit events and spans — it's searchable and visible in the dashboard.
7. **Actor types matter** — use `"human"` for user actions, `"agent"` for AI actions, `"system"` for cron/infra.
---
## 8. Common Patterns
### Wrap every agent run
```python
def handle_request(user_input: str):
client.audit.log(
actor={"id": "support-agent", "type": "agent"},
action="agent.run.started",
resource={"id": run_id, "type": "agent.execution"},
outcome="success",
metadata={"input": user_input[:200]},
)
with client.telemetry.execution(
agent_id="support-agent",
trigger="user_message",
metadata={"input": user_input[:120]},
) as ex:
pass # agent logic with spans
client.audit.log(
actor={"id": "support-agent", "type": "agent"},
action="agent.run.completed",
resource={"id": run_id, "type": "agent.execution"},
outcome="success",
)
```
### Log PII access for compliance
```python
client.audit.log(
actor={"id": "support-agent", "type": "agent"},
action="pii.access",
resource={"id": "acct_7f2a", "type": "account", "name": "Customer Account"},
outcome="success",
metadata={"fields": ["email", "phone"], "reason": "support_inquiry"},
)
```
### Verify chain integrity programmatically
```python
result = client.audit.verify()
if not result["valid"]:
alert(f"Chain broken at event {result.get('first_broken_event_id')}")
```
Click to expand the full TypeScript agent prompt
Click to expand the full TypeScript agent prompt
# Fact0 Integration Guide for AI Coding Agents — TypeScript / Node.js
You are integrating **Fact0** — a tamper-evident audit log and execution telemetry platform for AI agents.
- **Docs:** https://docs.fact0.io
- **API base:** https://api.fact0.io
- **Dashboard:** https://app.fact0.io
- **Full LLM context:** https://docs.fact0.io/llms-full.txt
---
## 1. Installation
```bash
npm install @fact0/sdk
```
Requires Node.js 18+. **Never import from local wrapper paths** — always use `@fact0/sdk`. Use this in server-side contexts only (Next.js route handlers, Node agents, workers) — never in browser code.
---
## 2. Authentication
Get an API key from https://app.fact0.io → Settings → API Keys.
Keys are prefixed `f0_live_…`. They have a **scope**:
- `write` — can append audit events and ingest telemetry
- `read` — can query events, verify chains, export PDFs
```bash
export FACT0_API_KEY="f0_live_..."
```
---
## 3. Core Concepts
Fact0 has **two pipelines** — use both together for full coverage:
| Pipeline | Purpose | When to use |
|----------|---------|-------------|
| **Audit Log** | Tamper-evident, hash-chained compliance ledger | Every action that matters for security reviews: tool calls, data access, approvals, policy checks |
| **Telemetry** | Execution tracing with spans, DAGs, and replay | Debugging agent runs: model invocations, tool calls, state mutations, timing |
### Audit Event Shape
```json
{
"actor": {"id": "agent-1", "type": "agent"},
"action": "document.delete",
"resource": {"id": "doc_456", "type": "document", "name": "Q3 Report"},
"outcome": "success"
}
```
- **Actor types**: `"human"`, `"agent"`, `"system"`
- **Outcomes**: `"success"`, `"failure"`, `"error"`
- **metadata**: optional object for extra context (IP, tokens, model name, etc.)
### Telemetry Span Types
```
TOOL_CALL — external tool/API invocation
MODEL_INVOCATION — LLM inference call
STATE_MUTATION — agent memory/state write
HUMAN_APPROVAL — human-in-the-loop decision gate
POLICY_EVALUATION — guardrail or policy check
CUSTOM — any other span
```
---
## 4. TypeScript SDK — Full API Reference
### Client Setup
```typescript
import { Fact0Client } from "@fact0/sdk";
const client = new Fact0Client({
apiKey: process.env.FACT0_API_KEY!,
// baseUrl defaults to https://api.fact0.io — override only for local dev
});
```
### Audit Logging
```typescript
// Single event
await client.audit.log({
actor: { id: "user_123", type: "human", email: "user@example.com" },
action: "document.delete",
resource: { id: "doc_456", type: "document", name: "Q3 Report" },
outcome: "success",
metadata: { ip: "203.0.113.5" },
});
// Batch (up to 1000 events)
await client.audit.logBatch([event1, event2]);
```
### Audit Queries & Verification
```typescript
// List events with filters
const events = await client.audit.listEvents({
actor_id: "agent-1",
action: "document.delete",
outcome: "failure",
page_size: 50,
});
// Get single event
const event = await client.audit.getEvent("evt_01HX3K...");
// Verify hash chain integrity
const result = await client.audit.verify();
// → { valid: true, events_checked: 31847, root_hash: "sha256:..." }
// Export SOC 2-style PDF audit pack (returns ArrayBuffer)
const pdfBuffer = await client.audit.exportPdf({ from: "2024-01-01", to: "2024-06-01" });
// Export evidence ZIP (returns ArrayBuffer)
const zipBuffer = await client.audit.exportEvidencePack({ from: "2024-01-01", to: "2024-06-01" });
// Poll async ingest receipt
const receipt = await client.audit.getReceipt("rcpt_01...");
```
### Execution Telemetry
```typescript
// 1. Start the execution
const execution = await client.telemetry.startExecution({
agent_id: "customer-support-bot",
agent_name: "Support Bot",
trigger: "user_query",
});
const executionId = execution.id as string;
// 2. Ingest spans with parent-child relationships
await client.telemetry.ingestSpans(executionId, [
{
span_id: "span-1",
span_type: "TOOL_CALL",
name: "Search Knowledge Base",
start_time: new Date().toISOString(),
end_time: new Date().toISOString(),
tool_call: {
tool_name: "knowledge_search",
input: { inline: { query: "refund policy" }, size_bytes: 32 },
output: { inline: { hits: 5 }, size_bytes: 128 },
duration_ms: 210,
},
},
{
span_id: "span-2",
span_type: "MODEL_INVOCATION",
name: "Generate Response",
parent_span_id: "span-1",
start_time: new Date().toISOString(),
end_time: new Date().toISOString(),
model_invocation: {
model_name: "claude-3-5-sonnet",
model_provider: "anthropic",
prompt_tokens: 2100,
completion_tokens: 450,
total_tokens: 2550,
session_id: "session_9a2f1b",
turn_sequence: 2,
prompt_name: "customer-inquiry",
prompt_version: 3,
cost_usd: 0.00975,
},
},
]);
// 3. End the execution
await client.telemetry.endExecution(executionId, "COMPLETED");
// Status values: "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED"
```
### Read & Query Methods
```typescript
// List all executions
const execs = await client.telemetry.listExecutions({ page_size: 50 });
// Get full execution including spans
const exec = await client.telemetry.getExecution(executionId);
const spans = await client.telemetry.getSpans(executionId);
// Get backend-computed execution DAG
const dag = await client.telemetry.getDag(executionId);
// Get replay frames for step-by-step debugging
const replay = await client.telemetry.replay(executionId, { from_sequence: 0, to_sequence: 10 });
```
---
## 5. Framework Integrations
### Next.js Route Handler
```typescript
// app/api/agent/route.ts
import { Fact0Client } from "@fact0/sdk";
import { NextResponse } from "next/server";
const fact0 = new Fact0Client({ apiKey: process.env.FACT0_API_KEY! });
export async function POST(req: Request) {
const { input } = await req.json();
await fact0.audit.log({
actor: { id: "api-agent", type: "agent" },
action: "agent.run.started",
resource: { id: crypto.randomUUID(), type: "agent.execution" },
outcome: "success",
metadata: { input: input.slice(0, 200) },
});
// ... agent logic ...
return NextResponse.json({ result });
}
```
### Express Middleware
```typescript
import express from "express";
import { Fact0Client } from "@fact0/sdk";
const fact0 = new Fact0Client({ apiKey: process.env.FACT0_API_KEY! });
const app = express();
app.use(async (req, res, next) => {
await fact0.audit.log({
actor: { id: req.headers["x-user-id"] as string || "anonymous", type: "human" },
action: `api.${req.method.toLowerCase()}.${req.path.replace(/\//g, ".")}`,
resource: { id: req.url, type: "http.request" },
outcome: "success",
});
next();
});
```
### OpenTelemetry (zero code changes)
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.fact0.io"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer f0_live_..."
```
---
## 6. REST API Quick Reference
### Audit API (base: https://api.fact0.io)
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/v1/events` | write | Append single event (async, returns receipt_id) |
| POST | `/v1/events/batch` | write | Append up to 1000 events |
| GET | `/v1/events` | read | List/filter events |
| GET | `/v1/events/{id}` | read | Get single event |
| GET | `/v1/events/{id}/verify` | read | Verify single event hash |
| GET | `/v1/verify` | read | Verify full chain integrity |
| GET | `/v1/events/stream` | read | Live SSE stream |
| GET | `/v1/export/pdf` | read | SOC 2 PDF audit pack |
| GET | `/v1/export/evidence-pack` | read | ZIP evidence pack |
| GET | `/v1/receipts/{id}` | read | Poll async ingest receipt |
### Telemetry API (base: https://api.fact0.io)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/executions` | Start execution |
| POST | `/api/v1/executions/{id}/spans` | Ingest spans |
| POST | `/api/v1/executions/{id}/events` | Ingest events |
| PUT | `/api/v1/executions/{id}/end` | End execution |
| GET | `/api/v1/executions` | List executions |
| GET | `/api/v1/executions/{id}/dag` | Get execution DAG |
| GET | `/api/v1/executions/{id}/replay` | Replay execution |
Auth header: `Authorization: Bearer f0_live_...`
---
## 7. Best Practices
1. **Dual-log high-value actions** — log to BOTH audit AND telemetry for tool calls, model invocations, and data access.
2. **Use `parent_span_id`** to link child spans to parent spans — the backend reconstructs the DAG from these relationships.
3. **Always `await` audit calls** in async contexts — fire-and-forget drops events on unhandled rejections.
4. **Set `agent_name`** on executions — it shows in the dashboard as a human-readable label.
5. **Include `metadata`** on both audit events and spans — it's searchable and visible in the dashboard.
6. **Actor types matter** — use `"human"` for user actions, `"agent"` for AI actions, `"system"` for cron/infra.
7. **Server-side only** — never expose the API key to browser code; use `@fact0/sdk` in route handlers, workers, and agents only.
---
## 8. Common Patterns
### Wrap every agent run
```typescript
async function handleRequest(userId: string, input: string) {
const runId = crypto.randomUUID();
await client.audit.log({
actor: { id: "support-agent", type: "agent" },
action: "agent.run.started",
resource: { id: runId, type: "agent.execution" },
outcome: "success",
metadata: { user_id: userId, input: input.slice(0, 200) },
});
const execution = await client.telemetry.startExecution({
agent_id: "support-agent",
trigger: "user_message",
});
// ... agent logic with ingestSpans ...
await client.telemetry.endExecution(execution.id as string, "COMPLETED");
await client.audit.log({
actor: { id: "support-agent", type: "agent" },
action: "agent.run.completed",
resource: { id: runId, type: "agent.execution" },
outcome: "success",
});
}
```
### Log PII access for compliance
```typescript
await client.audit.log({
actor: { id: "support-agent", type: "agent" },
action: "pii.access",
resource: { id: "acct_7f2a", type: "account", name: "Customer Account" },
outcome: "success",
metadata: { fields: ["email", "phone"], reason: "support_inquiry" },
});
```
### Verify chain integrity programmatically
```typescript
const result = await client.audit.verify();
if (!result.valid) {
console.error("Chain broken at event:", result.first_broken_event_id);
}
```
Click to expand the full Go agent prompt
Click to expand the full Go agent prompt
# Fact0 Integration Guide for AI Coding Agents — Go
You are integrating **Fact0** — a tamper-evident audit log and execution telemetry platform for AI agents.
- **Docs:** https://docs.fact0.io
- **API base:** https://api.fact0.io
- **Dashboard:** https://app.fact0.io
- **Full LLM context:** https://docs.fact0.io/llms-full.txt
---
## 1. Installation
```bash
go get github.com/fact0-ai/fact0/sdk/go
```
Requires Go 1.23+. Import as `fact0 "github.com/fact0-ai/fact0/sdk/go"`.
---
## 2. Authentication
Get an API key from https://app.fact0.io → Settings → API Keys.
Keys are prefixed `f0_live_…`. They have a **scope**:
- `write` — can append audit events and ingest telemetry
- `read` — can query events, verify chains, export PDFs
```bash
export FACT0_API_KEY="f0_live_..."
```
---
## 3. Core Concepts
Fact0 has **two pipelines** — use both together for full coverage:
| Pipeline | Purpose | When to use |
|----------|---------|-------------|
| **Audit Log** | Tamper-evident, hash-chained compliance ledger | Every action that matters for security reviews: tool calls, data access, approvals, policy checks |
| **Telemetry** | Execution tracing with spans, DAGs, and replay | Debugging agent runs: model invocations, tool calls, state mutations, timing |
### Audit Event Shape
```json
{
"actor": {"id": "agent-1", "type": "agent"},
"action": "document.delete",
"resource": {"id": "doc_456", "type": "document", "name": "Q3 Report"},
"outcome": "success"
}
```
- **Actor types**: `"human"`, `"agent"`, `"system"`
- **Outcomes**: `"success"`, `"failure"`, `"error"`
- **Metadata**: optional `map[string]interface{}` for extra context
### Telemetry Span Types
```
TOOL_CALL — external tool/API invocation
MODEL_INVOCATION — LLM inference call
STATE_MUTATION — agent memory/state write
HUMAN_APPROVAL — human-in-the-loop decision gate
POLICY_EVALUATION — guardrail or policy check
CUSTOM — any other span
```
---
## 4. Go SDK — Full API Reference
### Client Setup
```go
package main
import (
"context"
"log"
"os"
fact0 "github.com/fact0-ai/fact0/sdk/go"
)
func main() {
client := fact0.NewClient(fact0.Config{
APIKey: os.Getenv("FACT0_API_KEY"),
// BaseURL defaults to https://api.fact0.io
// Timeout defaults to 30s; MaxRetries defaults to 3
})
_ = client
}
```
### Audit Logging
```go
ctx := context.Background()
// Single event
err := client.Audit.Log(ctx, fact0.AuditEventInput{
Actor: fact0.Actor{ID: "user_123", Type: "human", Email: "user@example.com"},
Action: "document.delete",
Resource: fact0.Resource{ID: "doc_456", Type: "document", Name: "Q3 Report"},
Outcome: "success",
Metadata: map[string]interface{}{"ip": "203.0.113.5"},
})
if err != nil {
log.Fatal(err)
}
// Batch (up to 1000 events)
result, err := client.Audit.LogBatch(ctx, []fact0.AuditEventInput{event1, event2})
```
### Audit Queries & Verification
```go
// List events with filters
events, err := client.Audit.ListEvents(ctx, "?actor_id=agent-1&action=document.delete&outcome=failure&page_size=50")
// Get single event
event, err := client.Audit.GetEvent(ctx, "evt_01HX3K...")
// Verify hash chain integrity
result, err := client.Audit.Verify(ctx, "")
// result["valid"] == true, result["events_checked"] == 31847
// Verify a date range
result, err = client.Audit.Verify(ctx, "?from=2024-01-01&to=2024-06-01")
// Get async receipt
receipt, err := client.Audit.GetReceipt(ctx, "rcpt_01...")
```
### Execution Telemetry
```go
// 1. Start the execution
exec, err := client.Telemetry.StartExecution(ctx, fact0.StartExecutionRequest{
AgentID: "customer-support-bot",
AgentName: "Support Bot",
Trigger: "user_query",
})
if err != nil {
log.Fatal(err)
}
executionID := exec["id"].(string)
// 2. Ingest spans with parent-child relationships
_, err = client.Telemetry.IngestSpans(ctx, executionID, []map[string]interface{}{
{
"span_id": "span-1",
"span_type": "TOOL_CALL",
"name": "Search Knowledge Base",
"start_time": "2024-01-01T00:00:00Z",
"end_time": "2024-01-01T00:00:00.210Z",
"tool_call": map[string]interface{}{
"tool_name": "knowledge_search",
"duration_ms": 210,
"input": map[string]interface{}{"inline": map[string]interface{}{"query": "refund policy"}},
"output": map[string]interface{}{"inline": map[string]interface{}{"hits": 5}},
},
},
{
"span_id": "span-2",
"span_type": "MODEL_INVOCATION",
"name": "Generate Response",
"parent_span_id": "span-1",
"start_time": "2024-01-01T00:00:00.210Z",
"end_time": "2024-01-01T00:00:01.450Z",
"model_invocation": map[string]interface{}{
"model_name": "gpt-4o",
"model_provider": "openai",
"prompt_tokens": 2100,
"completion_tokens": 450,
"total_tokens": 2550,
"session_id": "session_9a2f1b",
"turn_sequence": 2,
"prompt_name": "customer-inquiry",
"prompt_version": 3,
"cost_usd": 0.00975,
},
},
})
if err != nil {
log.Fatal(err)
}
// 3. End the execution
_, err = client.Telemetry.EndExecution(ctx, executionID, "COMPLETED")
// Status values: "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED"
```
### Read & Query Methods
```go
// List all executions
execs, err := client.Telemetry.ListExecutions(ctx, "?page_size=50")
// Get execution summary
exec, err := client.Telemetry.GetExecution(ctx, executionID)
// Get backend-computed DAG
dag, err := client.Telemetry.GetDAG(ctx, executionID)
// Get replay frames
replay, err := client.Telemetry.Replay(ctx, executionID, "?from_sequence=0&to_sequence=10")
```
### Config Options
```go
type Config struct {
APIKey string // required
BaseURL string // defaults to https://api.fact0.io
SyncIngest bool // true = wait for commit (X-Fact0-Sync header)
Timeout time.Duration // defaults to 30s
MaxRetries int // defaults to 3; retries on 429 + 5xx
}
```
---
## 5. Framework Integrations
### HTTP Middleware (net/http)
```go
func Fact0Middleware(fact0Client *fact0.Client, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_ = fact0Client.Audit.Log(r.Context(), fact0.AuditEventInput{
Actor: fact0.Actor{ID: r.Header.Get("X-User-ID"), Type: "human"},
Action: "api." + strings.ToLower(r.Method) + "." + strings.ReplaceAll(r.URL.Path, "/", "."),
Resource: fact0.Resource{ID: r.URL.String(), Type: "http.request"},
Outcome: "success",
})
next.ServeHTTP(w, r)
})
}
```
### OpenTelemetry (zero code changes)
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.fact0.io"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer f0_live_..."
```
---
## 6. REST API Quick Reference
### Audit API (base: https://api.fact0.io)
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/v1/events` | write | Append single event (async, returns receipt_id) |
| POST | `/v1/events/batch` | write | Append up to 1000 events |
| GET | `/v1/events` | read | List/filter events |
| GET | `/v1/events/{id}` | read | Get single event |
| GET | `/v1/events/{id}/verify` | read | Verify single event hash |
| GET | `/v1/verify` | read | Verify full chain integrity |
| GET | `/v1/events/stream` | read | Live SSE stream |
| GET | `/v1/export/pdf` | read | SOC 2 PDF audit pack |
| GET | `/v1/export/evidence-pack` | read | ZIP evidence pack |
| GET | `/v1/receipts/{id}` | read | Poll async ingest receipt |
### Telemetry API (base: https://api.fact0.io)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/executions` | Start execution |
| POST | `/api/v1/executions/{id}/spans` | Ingest spans |
| POST | `/api/v1/executions/{id}/events` | Ingest events |
| PUT | `/api/v1/executions/{id}/end` | End execution |
| GET | `/api/v1/executions` | List executions |
| GET | `/api/v1/executions/{id}/dag` | Get execution DAG |
| GET | `/api/v1/executions/{id}/replay` | Replay execution |
Auth header: `Authorization: Bearer f0_live_...`
---
## 7. Best Practices
1. **Dual-log high-value actions** — log to BOTH audit AND telemetry for tool calls, model invocations, and data access.
2. **Always check errors** — `client.Audit.Log` returns an error; don't swallow it with `_` in production.
3. **Use context cancellation** — pass a real `ctx` with deadlines so SDK calls respect your service's shutdown budget.
4. **Use `parent_span_id`** for nested spans to build accurate DAGs in the dashboard.
5. **Set `AgentName`** on executions — it shows in the dashboard as a human-readable label.
6. **Include `Metadata`** on both audit events and spans — it's searchable and visible in the dashboard.
7. **Actor types matter** — use `"human"` for user actions, `"agent"` for AI actions, `"system"` for cron/infra.
---
## 8. Common Patterns
### Wrap every agent run
```go
func handleRequest(ctx context.Context, client *fact0.Client, userID, input string) error {
runID := uuid.New().String()
_ = client.Audit.Log(ctx, fact0.AuditEventInput{
Actor: fact0.Actor{ID: "support-agent", Type: "agent"},
Action: "agent.run.started",
Resource: fact0.Resource{ID: runID, Type: "agent.execution"},
Outcome: "success",
Metadata: map[string]interface{}{"user_id": userID, "input": input[:min(200, len(input))]},
})
exec, err := client.Telemetry.StartExecution(ctx, fact0.StartExecutionRequest{
AgentID: "support-agent",
Trigger: "user_message",
})
if err != nil {
return err
}
// ... agent logic with IngestSpans ...
_, _ = client.Telemetry.EndExecution(ctx, exec["id"].(string), "COMPLETED")
_ = client.Audit.Log(ctx, fact0.AuditEventInput{
Actor: fact0.Actor{ID: "support-agent", Type: "agent"},
Action: "agent.run.completed",
Resource: fact0.Resource{ID: runID, Type: "agent.execution"},
Outcome: "success",
})
return nil
}
```
### Log PII access for compliance
```go
_ = client.Audit.Log(ctx, fact0.AuditEventInput{
Actor: fact0.Actor{ID: "support-agent", Type: "agent"},
Action: "pii.access",
Resource: fact0.Resource{ID: "acct_7f2a", Type: "account", Name: "Customer Account"},
Outcome: "success",
Metadata: map[string]interface{}{"fields": []string{"email", "phone"}, "reason": "support_inquiry"},
})
```
### Verify chain integrity programmatically
```go
result, err := client.Audit.Verify(ctx, "")
if err != nil {
log.Fatal(err)
}
if valid, ok := result["valid"].(bool); !ok || !valid {
log.Printf("Chain broken at event: %v", result["first_broken_event_id"])
}
```
How to Use
1
Select your language
Click the Python, TypeScript, or Go tab above to see the prompt for your stack.
2
Copy the prompt
Expand the accordion and copy the entire markdown block.
3
Paste into your agent
Add it to your AI coding tool:
- Cursor →
.cursorrulesfile in project root - Antigravity →
AGENTS.mdor paste directly in conversation - GitHub Copilot →
.github/copilot-instructions.md - Cline / Windsurf → System prompt or rules file
- Claude / ChatGPT → Paste as context at the start of your conversation
4
Ask your agent to integrate
Example prompts that work well:
- “Add Fact0 audit logging to every tool call in my agent”
- “Wrap my LangChain agent with Fact0 telemetry and audit trails”
- “Add execution tracing to my FastAPI agent endpoint”
- “Set up Fact0 to track all LLM invocations with token counts”
For the most up-to-date machine-readable context, you can also point your agent to:
https://docs.fact0.io/llms.txt— compact SDK referencehttps://docs.fact0.io/llms-full.txt— complete documentation dump