Bridge AAEP event streams to OpenTelemetry traces for unified SRE/compliance observability
Project description
OpenTelemetry ↔ AAEP Bridge
A bridge that converts AAEP event streams into OpenTelemetry traces and spans, so AAEP-producing agents become observable in any OTEL-compatible backend (Jaeger, Tempo, Datadog, Honeycomb, Grafana, New Relic, and many others).
If you operate AAEP producers in production and want unified observability with the rest of your stack, this bridge is the integration path.
Why this bridge exists
AAEP and OpenTelemetry address different but adjacent concerns:
| Standard | Optimized for | Audience |
|---|---|---|
| AAEP | Real-time agent ↔ AT communication with safety semantics | Assistive technology, accessibility consumers |
| OpenTelemetry | Post-hoc service observability with rich context | SRE, platform, compliance, security |
An agent emitting AAEP for AT subscribers can simultaneously feed OTEL collectors for observability. This bridge makes that happen without changing either side: AAEP producers stay AAEP, OTEL backends stay OTEL.
What the bridge does
The bridge is a subscriber that connects to any AAEP producer's /events SSE endpoint and translates each event into the appropriate OTEL span or span event, then forwards it to a configured OTEL collector.
AAEP → OTEL translation
| AAEP event | OTEL representation |
|---|---|
agent.session.started |
New span opens (trace=session_id, span_kind=internal) |
agent.session.completed |
The session span closes with Ok status |
agent.session.errored |
The session span closes with Error status + exception event |
agent.session.cancelled |
The session span closes with Cancelled status |
agent.state.changed |
Span event: state.changed with from/to attributes |
agent.progress.updated |
Span event: progress with percent attribute |
agent.tool.invoked |
Child span opens (tool name, args_summary, risk attrs) |
agent.tool.completed |
Child span closes with corresponding status |
agent.output.streaming |
Span event: output.chunk (counted, not text-content) |
agent.awaiting.confirmation |
Span event: confirmation.requested (CRITICAL severity) |
agent.awaiting.clarification |
Span event: clarification.requested (CRITICAL severity) |
agent.handoff.requested |
Span event: handoff.requested (CRITICAL severity) |
Privacy-preserving translation
OTEL backends are often shared infrastructure. We do not forward potentially-sensitive content:
- Text content is replaced with counts (e.g.,
"output.chunk_size_bytes"not the chunk text itself) - Tool arguments use the already-redacted
args_summaryfield (passwords/tokens redacted by the producer) - User messages are forwarded only as length/hash, not the literal text
- Reply tokens are NOT forwarded (they're internal to the AAEP transport)
The result: an OTEL backend sees the shape and timing of agent activity, including critical safety events, without seeing the actual user data.
Critical event signaling
Critical-urgency AAEP events (session.errored, awaiting.confirmation, awaiting.clarification, handoff.requested) get extra OTEL treatment:
- Marked with
severity_text="CRITICAL"andseverity_number=21 - Emitted as
Span.add_event()so they appear inline in traces - Tagged with
aaep.urgency=criticalfor filter queries
OTEL backends can route these to alert channels for real-time visibility into agent safety-relevant events.
Installation
cd examples/bridges/opentelemetry-aaep-bridge
pip install -e .
This installs the bridge with OTEL SDK dependencies. Real OTEL collectors are external (Jaeger, OTLP-compatible exporter, etc.).
Requires Python 3.10 or newer.
Quick start
1. Start any AAEP producer
In one terminal:
python -m aaep_minimal_producer.server --port 8080
2. Configure OTEL export target
Set environment variables for your OTEL collector. For an OTLP-compatible endpoint:
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
export OTEL_SERVICE_NAME="aaep-bridge"
export OTEL_RESOURCE_ATTRIBUTES="aaep.bridge.version=1.0.0"
For local development you can use the console exporter (no collector needed):
export OTEL_TRACES_EXPORTER=console
3. Start the bridge
aaep-otel-bridge --endpoint http://localhost:8080
The bridge connects to the AAEP producer, consumes events, and exports them to OTEL.
4. Drive an AAEP session
In a third terminal, trigger a session:
curl -X POST http://localhost:8080/sessions \
-H "Content-Type: application/json" \
-d '{"user_message": "Send an email to alice@example.com"}'
You'll see OTEL traces appear in your collector. The session becomes a trace; each tool call becomes a span; each critical event becomes a flagged span event.
Example trace shape (in Jaeger)
[trace 8f3a2b1c...] session_id=sess_a1b2c3
├─ [span] aaep.session duration: 1.8s status: Ok
│ │ attrs: aaep.session_id=sess_a1b2c3
│ │ aaep.agent_id=demo-agent
│ │ aaep.duration_ms=1812
│ │ aaep.tool_invocations_count=1
│ │
│ ├─ [event] state.changed from=idle, to=thinking
│ ├─ [event] state.changed from=thinking, to=calling_tool
│ │
│ ├─ [span] aaep.tool.send_email duration: 800ms status: Ok
│ │ │ attrs: aaep.tool=send_email
│ │ │ aaep.risk_level=high
│ │ │ aaep.irreversible=true
│ │ │ aaep.args_summary="to=alice@example.com"
│ │ │
│ │ ├─ [event] confirmation.requested severity=CRITICAL
│ │ │ attrs: aaep.action="Call send_email"
│ │ │ aaep.consequence="This action cannot be easily undone."
│ │ │ aaep.default_decision=reject
│ │ │
│ │ └─ [event] confirmation.received decision=accept
│ │
│ ├─ [event] state.changed from=calling_tool, to=writing_output
│ ├─ [event] output.chunk chunk_size_bytes=42
│ ├─ [event] output.chunk chunk_size_bytes=18 complete=true
│ │
│ └─ [span end] status=Ok
The trace lets SREs verify:
- How long sessions take (full session span duration)
- Which tools are called and how often (child spans)
- Where critical events occur in the timeline (CRITICAL-severity span events)
- Whether confirmations are typically accepted or rejected (event attributes)
Compliance and audit use cases
For organizations subject to compliance audits (HIPAA, SOX, GDPR, etc.), this bridge provides:
- Audit trail of all AAEP-emitting agent activity in your existing OTEL store
- Critical event flagging for security/compliance review
- Privacy-preserving traces that don't include the content but document the shape and decisions
- Standard OTLP format that works with whatever compliance backend you already have
The bridge does NOT replace AAEP. AT subscribers should still connect directly to the AAEP /events endpoint for real-time accessibility delivery. The OTEL bridge is parallel infrastructure for SRE/compliance observation.
Configuration
| Environment variable | Purpose |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP gRPC endpoint (e.g., http://collector:4317) |
OTEL_EXPORTER_OTLP_PROTOCOL |
"grpc" or "http/protobuf" (default: grpc) |
OTEL_SERVICE_NAME |
Service name in OTEL backend (default: "aaep-bridge") |
OTEL_RESOURCE_ATTRIBUTES |
Comma-separated key=value pairs |
OTEL_TRACES_EXPORTER |
"otlp" (default) or "console" (for local dev) |
CLI flags override env vars where applicable.
Project layout
opentelemetry-aaep-bridge/
├── README.md
├── pyproject.toml
├── aaep_otel_bridge/
│ ├── __init__.py
│ ├── translator.py # AAEP → OTEL event translator
│ └── bridge.py # Subscriber loop + CLI entry
└── tests/
└── test_translator.py
Limitations
- Subscriber-only. This bridge consumes AAEP events; it does not emit AAEP from OTEL traces (that direction has no clear use case yet).
- No back-pressure handling. If your OTEL collector can't keep up with a high-volume AAEP producer, the bridge will buffer in memory. Configure a real collector with batching for production use.
- Privacy-aware by default. Text content is not forwarded. If you need richer attributes for debugging, edit
translator.py(and add appropriate consent banners).
See also
../mcp-aaep-bridge/— sister bridge for MCP- OpenTelemetry specification — upstream OTEL standard
- Specification appendix D — AAEP cross-references
- Implementer's Guide §5 — bridge integration patterns
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aaep_otel_bridge-1.0.0.tar.gz.
File metadata
- Download URL: aaep_otel_bridge-1.0.0.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4b936720c0df3e29be1c8ad9a59ad4ea5e299f7ae0e168c2d33a4de42c4845d
|
|
| MD5 |
4c9d8fa57402e3d2eca2a1f2aa23049f
|
|
| BLAKE2b-256 |
f1cc695c5f98c0ec48432ac2172c7104b00962c19a14b335b85219d0c2b2cec1
|
File details
Details for the file aaep_otel_bridge-1.0.0-py3-none-any.whl.
File metadata
- Download URL: aaep_otel_bridge-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d83a5abbd6c925ff1eb274c3237b5404a07a560494b6d8a8090b7673afc308e
|
|
| MD5 |
cd796190ffda9d8af236735c44aaf689
|
|
| BLAKE2b-256 |
9cf054377cba1644a5746c57382eb4ec9d358caa0f255d3f897633cea17c6196
|