Documentation Index
Fetch the complete documentation index at: https://docs.tracectrl.ai/llms.txt
Use this file to discover all available pages before exploring further.
End-to-End Flow
Agent emits spans
The SDK’s framework instrumentor captures every LLM call, tool invocation, and agent action as an OpenTelemetry span. The
TraceCtrlSpanProcessor enriches each span with tracectrl.* security attributes (agent id, tool category, session id, ingress markers).Spans exported via OTLP
The
BatchSpanProcessor batches spans and exports them via OTLP gRPC to the OTel Collector at :4317. The batch flush interval is TRACECTRL_BATCH_DELAY_MS (default 1000). Collector routes to ClickHouse
The OTel Collector receives spans on
:4317 (gRPC) and :4318 (HTTP) and exports them to ClickHouse via the clickhouseexporter. Spans land in the otel_traces table with SpanAttributes stored as a Map(String, String). Engine pipeline processes spans
Every
PIPELINE_INTERVAL_SECONDS (default 60), the engine re-reads all spans, refreshes the agent inventory, topology edges, guardrail registry, guardrail violations, and attack graph. ReplacingMergeTree deduplicates writes — no watermark required on the main path. Protector Plus Call Path
When TraceCtrl Guards is enabled, guardrail evaluations flow through the same span pipeline as everything else:SDK call site
User code calls
tracectrl.check_input(msg) or tracectrl.check_output(text) inside a with tracectrl.guard(): block.Background POST to Protector Plus
A background thread POSTs to the Protector Plus endpoint (
/apikey/api/protectorplus/v1/input-check or .../output-check). The user call returns IMMEDIATELY with a flagged=False verdict stub — synchronous callers can verdict.wait(timeout=...). SDK emits guardrail spans
On the POST response, the background thread emits one
tracectrl.guardrail.evaluation span per flagged sub-guardrail with decision='fail' and tracectrl.guardrail.provider='protector_plus', parented to the span that was active at the call site.Engine ingests violations
On the next pipeline tick,
update_violations() picks up the failing eval spans from otel_traces and inserts them into guardrail_violations. Verifying Each Stage
1. Are spans being exported?
SetTRACECTRL_FAIL_SILENTLY=false temporarily to see exporter errors:
2. Is the Collector receiving spans?
3. Are spans in ClickHouse?
4. Is the pipeline running?
5. Does the API return data?
6. Are guardrail violations being ingested?
Latency
| Stage | Typical Latency |
|---|---|
| SDK span processing | < 1ms per span |
| Batch export to Collector | 1 second (configurable via TRACECTRL_BATCH_DELAY_MS, default 1000) |
| Collector → ClickHouse | < 100ms |
| Pipeline processing | 60 second cycle (configurable via PIPELINE_INTERVAL_SECONDS, default 60) |
| API response | < 50ms |

