ProvenLog offers two zero-friction approaches that automatically detect and instrument all installed frameworks. No per-framework setup code required.
plog run — CLI wrapper
Wraps any Python command with automatic instrumentation:
plog run -- python my_agent.py
plog run --agent-id my-agent -- python -m my_package
plog run --db /tmp/audit.db -- python script.py
plog run --server http://localhost:7600 -- python agent.py
How it works
plog run creates a temporary sitecustomize.py (the standard Python startup hook used by ddtrace, OpenTelemetry, etc.) that imports provenlog.auto, then executes your command with a modified PYTHONPATH.
Python automatically runs sitecustomize on startup — before your code runs — so all frameworks are patched before any agent code imports them.
The child process inherits stdin/stdout/stderr transparently. Signals (SIGINT, SIGTERM) are forwarded. The child’s exit code is preserved.
Flags
| Flag | Default | Description |
|---|
--agent-id | auto | Agent identifier for audit events |
--db | ~/.provenlog/events.db | SQLite path (embedded mode) |
--server | — | Server URL (mutually exclusive with --db) |
import provenlog.auto — one-line import
For code you control, add a single import at the top of your entrypoint:
import provenlog.auto # must be before framework imports
from langchain_core.chat_models import ChatOpenAI
# ... your agent code
What happens on import
- Reads configuration from environment variables
- Creates a shared
ProvenLogClient
- Probes for installed frameworks using
importlib.util.find_spec() (never imports uninstalled packages)
- Patches each detected framework using its native hook mechanism
Environment variables
| Variable | Default | Description |
|---|
PROVENLOG_ENABLED | 1 | Set to 0 to disable all instrumentation |
PROVENLOG_AGENT_ID | auto | Agent identifier for audit events |
PROVENLOG_URL | — | Server URL; omit for embedded mode |
PROVENLOG_DB_PATH | ~/.provenlog/events.db | SQLite path for embedded mode |
PROVENLOG_LABELS | — | Comma-separated key=value pairs for dimensions |
Framework detection
| Framework | Detection | Patch mechanism | Captures |
|---|
| Anthropic SDK | anthropic | Monkey-patches Anthropic.__init__ | messages.create(), token usage, stop reasons |
| LangChain | langchain_core | Injects callback via get_callback_manager_for_config | LLM calls, tool calls, agent actions, retrievers |
| LangGraph | langgraph | Graph-aware callback handler | Node-level events, graph state, checkpoints |
| CrewAI | crewai | Global event bus registration | Tool usage, LLM calls, task lifecycle, token counts |
| OpenAI Agents SDK | agents | add_trace_processor hook | Function calls, LLM generations, handoffs, guardrails |
| AG2/AutoGen | autogen | autogen.runtime_logging.start | Chat completions, function usage, cost tracking |
If LangGraph is detected, the separate LangChain patch is skipped — LangGraph’s Trail extends LangChain’s and captures both graph-level and chain-level events.
Safety
- Framework detection uses
importlib.util.find_spec() — it never imports uninstalled packages
- Each patch is wrapped in try/except — if one framework fails to patch, the others still work
- The client is registered with
atexit for clean shutdown
- ProvenLog observes passively — it never modifies agent behavior and adds zero latency to the execution path