Documentation Index
Fetch the complete documentation index at: https://docs.provenlog.com/llms.txt
Use this file to discover all available pages before exploring further.
Installation
Requirements: Python 3.8+
Basic usage
from provenlog import ProvenLogClient
client = ProvenLogClient(agent_id="my-agent")
client.log_event(
action_type="TOOL_CALL",
action_name="search_database",
action_input={"query": "revenue Q4"},
action_status="success",
action_output={"results": 42}
)
client.close()
Client configuration
client = ProvenLogClient(
base_url=None, # Server URL; None for embedded mode
agent_id="my-agent", # Default agent ID for all events
session_id="session-123", # Default session ID
batch_size=100, # Events per batch
flush_interval=1.0, # Seconds between flushes
timeout=30.0, # HTTP timeout
metadata={"env": "prod"}, # Default metadata merged into every event
labels={"dept": "finance"}, # Default labels merged into every event
context=None, # Initial label context for dashboard enrichment
db_path=None, # SQLite path (embedded mode)
api_key=None, # Bearer token (server mode)
on_error=None, # Error callback
)
Environment variables
| Variable | Description |
|---|
PROVENLOG_SERVER_URL | Server URL (enables server mode, used by ProvenLogClient) |
PROVENLOG_URL | Server URL (used by provenlog.auto / plog run) |
PROVENLOG_DB_PATH | SQLite path for embedded mode |
PROVENLOG_API_KEY | Bearer token for server auth |
Embedded vs Server mode
# Embedded mode (default) — writes to local SQLite
client = ProvenLogClient(agent_id="my-agent")
client = ProvenLogClient(agent_id="my-agent", db_path="/tmp/audit.db")
# Server mode — sends to plog serve
client = ProvenLogClient("http://localhost:7600", agent_id="my-agent")
client = ProvenLogClient("http://localhost:7600", agent_id="my-agent", api_key="your-key")
Logging events
# Using keyword arguments
client.log_event(
action_type="TOOL_CALL",
action_name="search_database",
action_input={"query": "revenue Q4"},
action_output={"results": 42},
action_status="success",
duration_ms=150,
metadata={"model": "claude-sonnet-4-5-20250929"},
labels={"env": "prod"},
)
# Using a ProvenLogEvent object
from provenlog.event import ProvenLogEvent
event = ProvenLogEvent(
action_type="LLM_CALL",
action_name="chat_completion",
action_input={"prompt": "Hello"},
action_status="success",
)
client.log_event(event)
Labels and context
Default labels
Labels passed to the constructor are merged into every event. Event-level labels override defaults for matching keys.
client = ProvenLogClient(
agent_id="loan-processor",
labels={"env": "prod", "dept": "lending"},
)
# This event will have labels {"env": "prod", "dept": "lending", "loan_id": "LN-2024-4821"}
client.log_event(
action_type="TOOL_CALL",
action_name="pull_credit_report",
action_status="success",
labels={"loan_id": "LN-2024-4821"},
)
Querying by labels
Events can be filtered by label values using ?label.<key>=<value> query parameters. Multiple label filters are ANDed together.
GET /v1/events?label.env=prod
GET /v1/events?label.env=prod&label.dept=lending
GET /v1/events?agent_id=loan-processor&label.loan_id=LN-2024-4821&limit=50
Label context
Labels are short identifiers, but dashboards often need richer information. set_context() attaches business data to a label value for dashboard enrichment — for example, attaching a borrower name and loan amount to a loan_id.
client = ProvenLogClient(
agent_id="loan-processor",
labels={"loan_id": "LN-2024-4821"},
)
client.set_context("loan_id", {
"borrower": "Alice Rivera",
"amount": 420000,
"stage": "underwriting",
})
The label key must exist in the client’s default labels — otherwise a ValueError is raised. The data is sent as a fire-and-forget PUT /v1/context/{key}/{value} request (or written to SQLite in embedded mode). Transport errors are logged as warnings and never raise.
Context is keyed by (label_key, label_value) and upserted — calling set_context again replaces the previous data.
You can also push context at construction time with the context parameter:
client = ProvenLogClient(
agent_id="loan-processor",
labels={"loan_id": "LN-2024-4821", "env": "prod"},
context={
"loan_id": {"borrower": "Alice Rivera", "amount": 420000},
"env": {"display_name": "Production", "region": "us-east-1"},
},
)
Querying events
# List events with filters
events = client.get_events(
agent_id="my-agent",
action_type="TOOL_CALL",
limit=50,
offset=0,
)
# Get a single event by ID
event = client.get_event("550e8400-e29b-41d4-a716-446655440000")
Verifying integrity
result = client.verify("my-agent")
# {"valid": True}
# or {"valid": False, "error": "hash mismatch at sequence 42"}
Batching and async
Events are ingested non-blocking via a background thread:
- Batched every 100 events or 1 second (whichever comes first)
- Never blocks your agent’s execution path
- Flush explicitly with
client.flush()
- Clean shutdown with
client.close()
Context manager
with ProvenLogClient(agent_id="my-agent") as client:
client.log_event(
action_type="TOOL_CALL",
action_name="search",
action_status="success",
)
# Automatically flushed and closed
PII redaction
In embedded mode, redaction is automatic — the client loads redaction rules from your config file on startup. In server mode, the server handles redaction.
To add custom redaction rules, create a provenlog.yaml config file:
redaction:
rules:
- name: mrn
pattern: "MRN-\\d{10}"
replace: "[REDACTED:mrn]"
Config file discovery order:
PROVENLOG_CONFIG environment variable
./provenlog.yaml
~/.provenlog/config.yaml
You can also use the Redactor class directly for standalone redaction:
from provenlog import Redactor
redactor = Redactor.default()
clean, count = redactor.redact_string("Contact john@example.com")
# clean = "Contact [REDACTED:email]", count = 1
See PII Redaction for the full list of built-in patterns.