otel_mapper
Pure mapping from OTLP/HTTP JSON spans to AgentRun / Edge candidates
(Agent Detective build spec section 6.1). No I/O, no network, standard
library only. License: Apache-2.0.
Usage
from otel_mapper import flatten_export_request, map_spans
spans = flatten_export_request(otlp_export_request_payload) # full OTLP JSON
result = map_spans(spans) # a2a_detection=False by default
result.runs # list[AgentRunCandidate], sorted by (start_time, run_key)
result.edges # list[EdgeCandidate], sorted by (from, to, type)
result.graph_ids # set[str]
map_spans also accepts a flat list of span dicts directly, in either the
OTLP/HTTP JSON shape (traceId/spanId/attributes key-value array) or a
flattened snake_case shape with plain-dict attributes. Timestamps may be
ISO-8601 strings or unix-nanosecond strings. See otel_mapper/mapper.py's
module docstring for the full input contract.
Keying (contract with ingest / M3)
run_key = "<trace_id>:<span_id>"of the AGENT span that opened the run. Deterministic and stable across redelivery; ingest hashes it intoagent_runs.run_id(e.g. uuid5).- Every
openinference.span.kind = AGENTspan opens exactly one run; other spans join the run of their nearest AGENT ancestor in the same trace. graph_idis thex-execution-graph-idcorrelation header when present on any member span (plain attribute orhttp.request.header.x-execution-graph-id), else the trace id.
Edge rules and direction
Edges point in the direction of influence (from_run output feeds to_run),
which is what blame_engine expects.
| Type | Rule | Direction |
|---|---|---|
SPAWN |
AGENT span whose parent belongs to a different agent's run | parent run -> child run |
TOOL_DELEGATION |
TOOL span with gen_ai.tool.target_agent |
target agent's run -> caller run |
A2A_MESSAGE |
a2a.task_id attribute, or HTTP client span on /.well-known/agent.json; only with a2a_detection=True |
peer run -> caller run (flipped for SERVER spans) |
Edges carry a free-text detection_method recording which rule fired, and are
deduplicated on (from_run_key, to_run_key, type).
Correlation-header limitation
x-execution-graph-id determines graph membership only. It groups runs
into one execution graph, possibly across many traces, but says nothing about
who called whom. The mapper deliberately derives no edges from it;
header-correlated graphs without structural (SPAWN/TOOL/A2A) evidence are a
forest of independent runs.
Tests
uv run pytest packages/otel_mapper -v
Fixtures in testdata/ are full ExportTraceServiceRequest payloads covering
SPAWN, TOOL_DELEGATION, A2A (flag on/off), correlation-header membership, and
malformed input.
Metadata
Release files for otel-mapper 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| otel_mapper-0.3.0.tar.gz | 33.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| otel_mapper-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.7 kB
Release files / otel_mapper-0.3.0.tar.gz
| Download URL | otel_mapper-0.3.0.tar.gz |
|---|---|
| Size | 33.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d8f4b39a5032baf86b026f25795023b872d4beb5662586317a8c8cc8fb90df8a
|
|
BLAKE2b-256 checksum How to use checksums |
ca5855ad05a4408fe780c52ff36603d88e3d8f37a452440a7c09fae6aa9f00ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / otel_mapper-0.3.0-py3-none-any.whl
| Download URL | otel_mapper-0.3.0-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9bbdbad9d4559fdb4d8779a687a2efc55194994a0d32ed82717022e0c33b90b9
|
|
BLAKE2b-256 checksum How to use checksums |
43e4b23f4f97b91d37dcae3d412098de4f6d402fc251242c8355ae873b2893f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|