Story-1442: Atlas Logfire content gate
This Story makes Atlas's GenAI observability safe by default: model telemetry can still reach Logfire, but prompt, response, tool, evidence, and legal content stay out of ordinary span attributes and out of the general X-Ray/CloudWatch lane.
Metadata is the road; content is sealed cargo
Metadata such as service.name, agent.key,
gen_ai.agent.name, run_id, form_id,
model id, token counts, and cost can travel on normal telemetry. The actual
matter text is different: it is privileged cargo and must not be attached to
general spans.
real matter run -> event_mode="attributes" -> include_content=false -> no prompt/response/tool/evidence content on spans synthetic staging opt-in -> PRAMAAN_LOGFIRE_CONTENT_CAPTURE=synthetic -> LOGFIRE_ENVIRONMENT=staging or synthetic -> event_mode="logs" -> content leaves only as capped Logfire log events
One gate in observability.py
agents/atlas/observability.py now builds a small
GenAIInstrumentationPolicy before calling
Agent.instrument_all(...). The default policy forces
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=false,
keeps event_mode="attributes", and passes
include_content=false.
The only content-on path requires the explicit synthetic opt-in and a
non-production environment. That path uses a dedicated Logfire logger provider
aimed at /v1/logs, with event_mode="logs" and
include_binary_content=false.
What stays unchanged
Pydantic AI still owns T1 model-call instrumentation. Atlas still enriches
library-owned spans with safe T2 dimensions. No new manual span name was added,
no raw tracer call was introduced, and firm_id remains a span
attribute only, never baggage.
Synthetic content log events are capped at 800 characters before OTLP export. The cap sits in the Logfire-only log processor, not in the general telemetry path.
Tests that pin the gate
test_atlas_observability.py proves default content capture is off,
synthetic staging capture uses log events, production rejects the synthetic
opt-in, and long content is capped before export.