Skip to main content

A unified read, query, and export layer for LLM and AI-agent traces.

Project description

traceport

Read agent conversations from any supported observability provider through one consistent API.

Trace providers store the same conversation in very different shapes: runs, records, observations, spans, and cumulative message histories. traceport normalizes those records into sessions with one readable, chronological transcript:

from traceport import TraceClient

client = TraceClient.from_env("langsmith")

sessions = client.list_sessions(project="Branna", since="7d")
session = client.get_session(sessions[0].id, project="Branna")

for event in session.agent_traces:
    print(event.time, event.name, event.type, event.content)

session.agent_traces removes repeated cumulative histories while preserving system prompts, human messages, paired tool calls, AI messages, and the timestamp where each event first appeared.

Install

Use uv and install only the provider extras you need:

uv add 'traceport[langsmith]'
uv add 'traceport[logfire]'
uv add 'traceport[langfuse]'
uv add 'traceport[phoenix]'

Install MCP support alongside a provider:

uv add 'traceport[mcp,langsmith]'

Helicone uses the core httpx dependency and does not require an extra.

When developing Traceport itself:

cd packages/traceport
uv sync --extra langsmith

Core Model

Traceport's primary hierarchy is:

Session
├── agent_traces     readable, deduplicated conversation
└── full_traces      complete provider executions
    └── spans        full normalized telemetry

session.agent_traces

Despite the name, agent_traces is a flat list[AgentSpan]. Each event has four fields:

class AgentSpan:
    name: str
    type: Literal[
        "system_prompt",
        "human_message",
        "tool_call",
        "ai_message",
    ]
    content: str | AgentToolCall
    time: datetime | None

For example:

2026-06-21 23:12:05+00:00  System      system_prompt  You are a concise assistant.
2026-06-21 23:12:05+00:00  Human       human_message  Count to three in Spanish.
2026-06-21 23:12:05+00:00  ChatOpenAI  ai_message     uno, dos, tres
2026-06-21 23:12:11+00:00  Human       human_message  And in German?
2026-06-21 23:12:11+00:00  ChatOpenAI  ai_message     eins, zwei, drei

Providers such as LangSmith often include the complete conversation history in every later trace. Traceport runs transcript extraction across the whole session, deduplicates repeated messages, and keeps the timestamp from the first trace where each event appeared.

Tool invocations and results are paired into one event:

for event in session.agent_traces:
    if event.type == "tool_call":
        call = event.content
        print(call.name)
        print(call.input)
        print(call.output)

AgentToolCall contains:

class AgentToolCall:
    name: str
    input: Any | None
    output: Any | None

session.full_traces

Use full traces only when you need observability details:

for trace in session.full_traces:
    print(trace.id, trace.name, trace.status, trace.latency_ms)

    for span in trace.spans:
        print(span.id, span.name, span.span_kind, span.model)

Full traces preserve supporting HTTP, database, chain, and infrastructure spans. Untouched provider records remain available through each model's raw escape hatch, but raw is excluded from normal model serialization.

session.model_dump() returns the lightweight session summary. It intentionally excludes both the computed transcript and the potentially large full_traces payload.

Sessions

list_sessions() returns lightweight summaries and defaults to sessions containing agent activity:

sessions = client.list_sessions(
    project="Branna",
    since="7d",
    agent_only=True,
    limit=100,
    scan_limit=500,
)

for ref in sessions:
    print(ref.id, ref.trace_count, ref.agent_span_count, ref.status)

get_session() hydrates the selected session:

session = client.get_session(sessions[0].id, project="Branna")

Traceport uses provider-native session, thread, or conversation identifiers when available. If a provider does not expose one, the trace becomes a synthetic session with ID trace:<trace-id>.

Some providers can identify agent sessions natively. Others use a bounded candidate scan. Set scan_limit to control the maximum work. Traceport emits ScanLimitWarning if the bound may have truncated the result set.

Individual Traces

Use trace-level APIs when you need one specific provider execution rather than the entire conversation:

refs = client.list_traces(
    project="Branna",
    since="24h",
    agent_only=True,
    error=False,
    limit=50,
)

trace = client.get_trace(refs[0].id, project="Branna")

for event in trace.agent_spans:
    print(event.time, event.type, event.content)

trace.agent_spans applies the same readable extraction to one trace. trace.spans contains its complete telemetry.

Provider-independent filtering is available through F:

from traceport import F

traces = client.query_traces(
    F.project("Branna")
    & F.since("24h")
    & F.has_agent_spans()
    & F.model_contains("gpt"),
    limit=100,
)

Supported filters include project, time range, status, model, latency, cost, metadata, name, and agent-span presence. Unsupported native predicates are post-filtered after normalization rather than silently ignored.

Provider Configuration

Provider Required environment variables Optional Extra
LangSmith LANGSMITH_API_KEY LANGSMITH_ENDPOINT, LANGSMITH_WORKSPACE_ID langsmith
Logfire LOGFIRE_READ_TOKEN LOGFIRE_BASE_URL, LOGFIRE_PROJECT, LOGFIRE_ENVIRONMENT logfire
Langfuse LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY LANGFUSE_HOST, LANGFUSE_PROJECT langfuse
Phoenix PHOENIX_COLLECTOR_ENDPOINT, PHOENIX_PROJECT_NAME PHOENIX_API_KEY phoenix
Braintrust BRAINTRUST_API_KEY BRAINTRUST_API_URL, BRAINTRUST_PROJECT_ID braintrust
Weave WANDB_API_KEY, WEAVE_PROJECT weave
Helicone HELICONE_API_KEY HELICONE_BASE_URL core
Datadog DD_API_KEY, DD_APP_KEY DD_SITE datadog

Example:

export LANGSMITH_API_KEY=...
export LANGSMITH_PROJECT=Branna
client = TraceClient.from_env("langsmith")
sessions = client.list_sessions(project="Branna", since="7d")

Provider Capabilities

Provider Read method Session identity Agent discovery
memory In-memory Native or synthetic Complete reference behavior
langsmith Runs SDK Thread metadata Bounded hydration
logfire SQL records OTel/GenAI attributes Native SQL child-record query
langfuse SDK and observations API Native session ID Bounded hydration
phoenix Spans API session.id OpenInference kinds
braintrust BTQL Session/thread metadata Bounded hydration
weave Calls SDK Session/thread metadata or synthetic Bounded hydration
helicone REST requests Native session ID Native; every request is an LLM call
datadog Planned Planned Planned

All active adapters preserve complete telemetry after an agent session is selected. Filtering a session for agent activity never removes its supporting spans from full_traces.

MCP Server

The MCP server is intentionally small and transcript-focused. Each server process reads one provider and one project and exposes exactly two read-only tools:

  • list_sessions(since="7d", until=None, error=None, limit=20)
  • get_session(session_id)

get_session returns the session summary and one flat agent_traces transcript. MCP never exposes full_traces, normalized spans, raw provider records, trace filters, or exporters.

Install MCP with the provider extra:

uv add 'traceport[mcp,langsmith]'

The generic stdio command is:

export TRACEPORT_PROVIDER=langsmith
export TRACEPORT_PROJECT=Branna
export LANGSMITH_API_KEY=...
uv run traceport-mcp

FastMCP uses stdio by default. An MCP stdio process must write only MCP protocol messages to stdout; diagnostic logging belongs on stderr.

Codex with a local checkout

Add a server with the Codex CLI:

codex mcp add traceport-langsmith \
  --env TRACEPORT_PROVIDER=langsmith \
  --env TRACEPORT_PROJECT=Branna \
  --env LANGSMITH_API_KEY=... \
  -- uv run \
    --directory /absolute/path/to/packages/traceport \
    --extra mcp \
    --extra langsmith \
    traceport-mcp

Or add the equivalent TOML from examples/mcp.codex.toml to ~/.codex/config.toml or a trusted project's .codex/config.toml.

Codex with the published package

codex mcp add traceport-langsmith \
  --env TRACEPORT_PROVIDER=langsmith \
  --env TRACEPORT_PROJECT=Branna \
  --env LANGSMITH_API_KEY=... \
  -- uvx --from 'traceport[mcp,langsmith]' traceport-mcp

Run one named MCP server per provider/project combination:

traceport-branna-langsmith
traceport-production-logfire

The server instructs clients to list sessions before hydration, starts with a seven-day window, defaults to 20 results, caps requests at 100, and warns clients not to repeat identical calls because observability providers may rate-limit reads.

Export Full Traces

Export is available through the Python API for full observability workflows:

trace = session.full_traces[0]

client.export_trace(trace, format="json")
client.export_trace(trace, format="otel")
client.export_trace(trace, format="openinference")

OpenInference is the default format and emits OTLP JSON with normalized OpenInference attributes.

Local Testing

The memory adapter provides deterministic offline behavior:

from traceport import Span, SpanKind, Trace, TraceClient
from traceport.adapters.memory import MemoryAdapter

trace = Trace(
    id="trace-1",
    session_id="session-1",
    provider="memory",
    spans=[
        Span(
            id="span-1",
            trace_id="trace-1",
            name="chat.completion",
            span_kind=SpanKind.LLM,
            inputs=[{"role": "user", "content": "hello"}],
            outputs=[{"role": "assistant", "content": "hi"}],
        )
    ],
)

client = TraceClient(adapter=MemoryAdapter([trace]))
session = client.get_session("session-1")
print(session.agent_traces)

Development

cd packages/traceport
UV_CACHE_DIR=/tmp/uv-cache uv sync
UV_CACHE_DIR=/tmp/uv-cache uv run ruff format src tests
UV_CACHE_DIR=/tmp/uv-cache uv run ruff check src tests
UV_CACHE_DIR=/tmp/uv-cache uv run mypy src
UV_CACHE_DIR=/tmp/uv-cache uv run pytest
UV_CACHE_DIR=/tmp/uv-cache uv build

No live provider calls run in CI. Provider behavior is covered with scrubbed fixtures.

Third-party adapters can register through the traceport.adapters entry point:

[project.entry-points."traceport.adapters"]
acme = "acme_traceport:AcmeAdapter"

Adapters must subclass traceport.adapters.BaseAdapter. Unsupported filters must be translated, post-filtered against normalized traces, or rejected with UnsupportedFilterError.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

traceport-0.1.0.tar.gz (45.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

traceport-0.1.0-py3-none-any.whl (60.3 kB view details)

Uploaded Python 3

File details

Details for the file traceport-0.1.0.tar.gz.

File metadata

  • Download URL: traceport-0.1.0.tar.gz
  • Upload date:
  • Size: 45.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for traceport-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9038a9b322285eda5c7fb1872bcc84680524791784df44d3da1e0f420ff23ba6
MD5 bc30e8093750b27ca0002c4b2b2dd832
BLAKE2b-256 8e55cb74da6c2d684efacfe1d5fa69234306a6796e4ef04bc725b02caebc1a9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for traceport-0.1.0.tar.gz:

Publisher: publish.yml on TheValmarAI/traceport

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file traceport-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: traceport-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 60.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for traceport-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8fa078696ff80a7444c6c5b928296ad9c2c0e40dab178d63c169d0af21a49539
MD5 f2a132897e0d102bbac6b5f6da50c9b9
BLAKE2b-256 0d57d16fe4be5e137927429f6953242b23bf21fafffb5a42b9754c2a98c4b8f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for traceport-0.1.0-py3-none-any.whl:

Publisher: publish.yml on TheValmarAI/traceport

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page