# Export Agent Traces: LangSmith, Langfuse, Phoenix and More

> How to export agent traces with tool calls from LangSmith, Langfuse, Phoenix, Braintrust, Helicone, Weave, Datadog, OpenTelemetry, OpenHands and LangGraph.

Canonical: https://origindatapartners.com/guides/export-agent-traces
By: Origin Data Partners
Status: Published
Published: 2026-11-14
Updated: 2026-11-14
Sources checked: 2026-11-14

## Quick answer

To export agent traces, use the tool's documented bulk path and set a time range: LangSmith bulk export to Parquet or runs.query, Langfuse JSON downloads, blob export or the Observations API, Phoenix get_spans_dataframe, Braintrust BTQL, Helicone's export CLI, Weave get_calls, the Datadog export API, OpenHands conversation downloads and LangGraph get_state_history. Check retention first: traces past it cannot be exported.

## Key points

- Retention decides what still exists: from 7 days on some free plans to indefinite on self-hosted tools.
- Several exports default to a short window (Datadog: 15 minutes; LangSmith runs.query: 1 day), so always set a range.
- Bulk export is plan-gated on LangSmith (Enterprise for sign-ups after 3 August 2026) and Langfuse (not Hobby or Core).
- OpenTelemetry content attributes are opt-in: if capture was off, prompts and tool results were never recorded.

## What should you check before exporting agent traces?

Four things decide whether an export gives you complete runs or fragments. Check them in the tool before writing any code.

- Retention: traces older than the plan's window are gone or hidden. Export inside the window, or raise it first.
- Sampling: if the agent ran with trace sampling, only some runs exist. Note the rate.
- Truncation: some tools cut large inputs, outputs or metadata in UI downloads or API responses. Use the bulk path or the flag that returns full content.
- Reasoning and content capture: proprietary model APIs return [reasoning tokens](https://origindatapartners.com/glossary/reasoning-tokens) as a summary or not at all, and OpenTelemetry instrumentations record prompts and tool results only when content capture is switched on.


## How do you export traces from LangSmith?

Traces are runs (spans) in a tracing project. For volume, bulk export writes them to your own bucket: "Export LangSmith trace data to an S3-compatible bucket in Parquet format" ([LangSmith bulk export](https://docs.langchain.com/langsmith/data-export)). Register a destination with POST /api/v1/bulk-exports/destinations, then create an export for a project and time range. For smaller pulls, query runs with the SDK (client.runs.query or POST /api/v2/runs/query), which replaces the deprecated list_runs and read_run ([LangSmith query docs](https://docs.langchain.com/langsmith/export-traces)).

Contents: inputs, outputs, run type (chain, llm, tool), parent and trace IDs, start and end times, errors, events, tags and token counts. "If you omit export_fields, all fields except feedbacks are included." runs.query returns only IDs unless you pass selects, and it looks back one day unless you set a start time.

Limits: "For customers who signed up after August 3, 2026, bulk export is only available on the" Enterprise plan; earlier customers keep it on Plus or Enterprise until February 1, 2027. "Bulk exports have a 72-hour runtime timeout", and "each workspace can create at most 250 bulk exports per hour". A runs.query call spans at most 401 days and is rate limited to "300 requests per 10 seconds per API key in LangSmith Cloud". Retention is 14 days (base) or 180 days (extended); "After the specified retention period, traces are no longer accessible in the tracing project UI or via the API" ([LangSmith retention](https://docs.langchain.com/langsmith/administration-overview)).

Create a bulk export (LangSmith docs, trimmed):

```bash
curl --request POST --url 'https://api.smith.langchain.com/api/v1/bulk-exports' \
  --header 'X-API-Key: YOUR_API_KEY' --header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
  --header 'Content-Type: application/json' \
  --data '{"bulk_export_destination_id": "your_destination_id",
           "session_id": "project_uuid",
           "start_time": "2026-10-01T00:00:00Z", "end_time": "2026-10-31T00:00:00Z"}'
```

Query runs with the Python SDK:

```python
runs = [run async for run in client.runs.query(
    project_ids=[project_id], min_start_time=since,
    selects=["NAME", "INPUTS", "OUTPUTS"])]
```


## How do you export traces from Langfuse?

Traces hold observations (spans, generations, events) and scores; sessions group traces. For one trace, "open the trace and click Download JSON in the header" ([Langfuse FAQ](https://langfuse.com/faq/all/export-single-trace-or-session)); "Very large inputs or outputs can be left out of the trace download." For many rows, the tracing table exports CSV or JSON, and "all columns are always exported" ([Langfuse UI export](https://langfuse.com/docs/api-and-data-platform/features/export-from-ui)). Scheduled blob export can "Schedule exports to Amazon S3, S3-compatible storage, Google Cloud Storage, or Azure Blob Storage every 20 minutes, hourly, daily, or weekly", in Parquet, CSV, JSON or JSONL ([Langfuse blob export](https://langfuse.com/docs/api-and-data-platform/features/export-to-blob-storage)).

Through the API, the Observations API v2 (GET /api/public/v2/observations) filters by traceId or sessionId and returns field groups such as core, io and usage. Page with a cursor; "default 50, max 1,000". Observations API v2 is available on Langfuse Cloud and self-hosted Langfuse v4. Metadata values "are otherwise cut at 200 characters" unless named in expandMetadata ([Langfuse public API](https://langfuse.com/docs/api-and-data-platform/features/public-api)). GET /api/public/traces/{id} is deprecated.

Limits: blob export is not available on Hobby or Core, needs the Teams add-on on Pro, and is available on Enterprise and self-hosted. "On Langfuse Cloud, each plan includes a data access window (Hobby: 30 days, Core: 90 days, Pro and Enterprise: 3 years)." Langfuse adds: "The data access window limits how much history you can view, but does not delete data." ([Langfuse retention](https://langfuse.com/docs/administration/data-retention)). Self-hosted instances keep data until you delete it.

All observations of one trace (Observations API v2):

```bash
curl -u "$LANGFUSE_PUBLIC_KEY:$LANGFUSE_SECRET_KEY" \
  "https://cloud.langfuse.com/api/public/v2/observations?traceId=<traceId>&fields=core,basic,io,usage&limit=1000"
# repeat with the returned cursor until it is empty
```


## How do you export spans from Arize Phoenix?

Spans live in Phoenix projects on your instance. The Python client can "download all spans as a dataframe using the get_spans_dataframe() method", with an optional SpanQuery filter and start and end times ([Phoenix docs](https://arize.com/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans)). "By default, all queries will collect all spans that are in your Phoenix instance", but the Python client returns at most limit spans, and limit "Defaults to 1000" ([Phoenix client source](https://raw.githubusercontent.com/Arize-ai/phoenix/main/packages/phoenix-client/src/phoenix/client/resources/spans/__init__.py)). The method has no cursor, so raise limit above the number of spans you expect, or export one time window at a time and check that each window returns fewer rows than the limit. Name the project with project_identifier: project_name is "Deprecated, use project_identifier"; root_spans_only is deprecated too.

Contents: a pandas DataFrame indexed by span ID with the span attributes your instrumentation recorded, such as input.value. Truncation and reasoning are not described on that page. Retention: "The Default policy also specifies 0 days, which is equal to "Indefinite" retention." ([Phoenix retention](https://arize.com/docs/phoenix/settings/data-retention)).

Spans as a dataframe (Phoenix client):

```python
from phoenix.client import Client
client = Client()
df = client.spans.get_spans_dataframe(project_identifier="your-project",
                                      start_time=start, end_time=end,
                                      limit=100_000)  # default limit is 1,000 spans
assert len(df) < 100_000, "limit reached: raise it or narrow the time window"
df.to_parquet("spans.parquet")
```


## How do you export logs from Braintrust?

In the UI, filter the Logs page and use the export icon for JSON or CSV; "The export icon appears only if you have Update or Delete permissions on the object." For volume, run a BTQL or SQL query against project_logs with POST /btql, in JSON or Parquet ([Braintrust export](https://docs.braintrust.dev/annotate/export)). Each "request returns one page of results and times out after 30 seconds on Braintrust-hosted deployments"; "read the cursor from the x-bt-cursor response header" and repeat ([Braintrust query API](https://docs.braintrust.dev/api-reference/query.md)).

Limits: BTQL queries "hit rate limits of 20 requests per minute" ([Braintrust rate limits](https://docs.braintrust.dev/kb/btql-rate-limits)). Retention on the pricing page is 14 days on Starter and 30 days on Pro ([Braintrust pricing](https://www.braintrust.dev/pricing)); Enterprise is custom.

One page of logs as Parquet (BTQL):

```bash
curl -X POST https://api.braintrust.dev/btql \
  -H "Authorization: Bearer <YOUR_API_KEY>" -H "Content-Type: application/json" \
  -d '{"query": "SELECT * FROM project_logs('"'<PROJECT_ID>'"') LIMIT 100", "fmt": "parquet"}'
# next page: resend the same SQL with OFFSET '<x-bt-cursor value>' appended
# (... LIMIT 100 OFFSET '<cursor>'); stop when a response has no cursor
```


## How do you export requests and sessions from Helicone?

Helicone logs one request per model call; agent runs group into sessions through the Helicone-Session-Id property. The export CLI runs as "npx @helicone/export --start-date 2024-01-01 --limit 10000 --include-body" and writes "Multiple formats (JSON, JSONL, CSV)" ([Helicone export](https://docs.helicone.ai/tools/export)). Without --include-body, request and response bodies are left out. For one session, query /v1/request/query with a session filter; the ClickHouse bulk endpoint "will timeout for point queries" ([Helicone query API](https://docs.helicone.ai/rest/request/post-v1requestquery-clickhouse)).

Contents: created time, properties (session ID and path), model, latency and cost, with bodies as a "URL to access the request and response body from S3" rather than inline ([Helicone sessions cookbook](https://docs.helicone.ai/guides/cookbooks/getting-sessions)). Retention on the pricing page: 7 days, 1 month, 3 months or forever by plan ([Helicone pricing](https://www.helicone.ai/pricing)).

Export one month with bodies (Helicone CLI):

```bash
HELICONE_API_KEY="your-api-key" npx @helicone/export \
  --start-date 2026-10-01 --end-date 2026-10-31 --include-body --format jsonl
```


## How do you export calls from W&B Weave?

Weave stores calls, one per traced operation; root calls form traces. In the Traces view, select rows and export: "In the Export modal, choose Selected rows or All rows". In code, "To fetch Calls using the Python API, use the client.get_calls method", or "make a request to the /calls/stream_query endpoint" with filters such as trace_roots_only and trace_ids ([Weave docs](https://docs.coreweave.com/products/wandb/weave/guides/tracking/querying-calls)).

Contents: call records with inputs, outputs and optional costs and feedback. The docs page read does not state retention or rate limits; it does say "You can query metrics for a maximum time range of 31 days." for the stats endpoint.

Calls through the Python client (Weave docs, trimmed):

```python
import weave
client = weave.init("your-team-name/your-project-name")
calls = client.server.calls_query_stream({
    "project_id": "your-team-name/your-project-name",
    "filter": {"trace_roots_only": True},
    "sort_by": [{"field": "started_at", "direction": "desc"}],
    "limit": 100, "offset": 0})
# limit is one page: repeat with offset += 100 until a page has fewer than 100 calls
```


## How do you export spans from Datadog LLM Observability (now Agent Observability)?

Spans are grouped by ML application with kinds such as agent, workflow, llm and tool. The export API offers GET /api/v2/llm-obs/v1/spans/events and POST /api/v2/llm-obs/v1/spans/events/search, authenticated with an API key and an application key ([Datadog export API](https://docs.datadoghq.com/llm_observability/investigate/export_api)). "By default, we export spans from the past 15 minutes", so always set filter[from] and filter[to].

Contents: input and output, metadata, token metrics, model name, span kind, parent and trace IDs, start time and duration. One parameter controls "Whether to retrieve truncated input and output content. Defaults to True." Page size: "Default: 10. Maximum configurable limit: 5000." "Responses are subject to a 50 MB size limit." Retention for these traces is "15 (default), 30, 60, or 90 days, determined by customer plan" ([Datadog retention](https://docs.datadoghq.com/data_security/data_retention_periods)).

One trace's spans over the last 7 days (Datadog docs, with a time range added):

```bash
curl -G "https://api.datadoghq.com/api/v2/llm-obs/v1/spans/events" \
  -H "DD-API-KEY: <YOUR_DATADOG_API_KEY>" \
  -H "DD-APPLICATION-KEY: <YOUR_DATADOG_APPLICATION_KEY>" \
  --data-urlencode "filter[trace_id]=<trace_id>" \
  --data-urlencode "filter[from]=now-7d" --data-urlencode "page[limit]=1000"
# repeat with page[cursor] from the previous response
```


## What do OpenTelemetry GenAI spans contain, and how do you export them?

OpenTelemetry is a specification, not a store: you export from whatever backend received the spans. The GenAI semantic conventions define agent spans (invoke_agent), model spans and execute_tool spans ([OTel agent spans](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md)). Content attributes carry the useful parts: gen_ai.input.messages holds "The chat history provided to the model as an input", gen_ai.output.messages the responses, gen_ai.system_instructions the system prompt, and gen_ai.tool.call.arguments and gen_ai.tool.call.result the tool input and output ([OTel execute_tool](https://raw.githubusercontent.com/open-telemetry/semantic-conventions-genai/main/docs/gen-ai/execute-tool.md)). The chat-history definition is from the agent spans page.

The catch: "OpenTelemetry instrumentations SHOULD NOT capture them by default, but SHOULD provide an option for users to opt in." ([OTel model spans](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)). If capture was off when the agent ran, those runs have structure and timings but no prompts or tool results. "Instrumentations MAY provide a way for users to filter or truncate input messages", and the output token count "SHOULD include reasoning tokens" ([OTel agent spans](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md)). These conventions are marked Development, so attribute names can change. Retention depends on the backend that stores the spans.

Span tree of one agent run (attribute names from the conventions):

```text
invoke_agent {gen_ai.agent.name}
  chat {model}         gen_ai.input.messages, gen_ai.output.messages, gen_ai.usage.*   (opt-in content)
  execute_tool {name}  gen_ai.tool.call.arguments, gen_ai.tool.call.result             (opt-in content)
group by trace_id, order by start time, join parent_span_id
```


## How do you download an OpenHands trajectory?

On OpenHands Cloud, GET /api/v1/app-conversations/{conversation_id}/download "Returns a zip file containing all events and metadata for the conversation." ([OpenHands Cloud API](https://docs.openhands.dev/openhands/usage/cloud/api-reference/conversations/export-conversation)). The agent server exposes GET /api/file/download-trajectory/{conversation_id} ([OpenHands agent server](https://docs.openhands.dev/sdk/guides/agent-server/api-reference/files/download-trajectory)) and an events search endpoint whose page size is at most 100 ([events search](https://docs.openhands.dev/sdk/guides/agent-server/api-reference/events/search-conversation-events.md)).

With the SDK and a persistence directory, each conversation is saved as files on disk, which "represents the same trajectory data you would find in the trajectory.json file from OpenHands V0" ([OpenHands persistence](https://docs.openhands.dev/sdk/guides/convo-persistence.md)). The pages read do not state Cloud retention, token counts or whether reasoning is stored.

Download one conversation from OpenHands Cloud (host is a placeholder):

```bash
curl -H "X-Access-Token: $OPENHANDS_API_KEY" -o conversation.zip \
  "https://<your-openhands-host>/api/v1/app-conversations/<conversation_id>/download"
```


## How do you export LangGraph checkpoint history?

A LangGraph checkpointer (in-memory, SQLite or Postgres) saves the graph state after each step, keyed by thread. graph.get_state_history(config) returns one thread's snapshots; "Importantly, the checkpoints will be ordered chronologically with the most recent checkpoint" first. To read every thread, "Call .list on the same checkpointer you passed to compile, with config=None" ([LangGraph checkpointers](https://docs.langchain.com/oss/python/langgraph/checkpointers)).

Contents: each snapshot holds the state values (for example the message list), the next nodes, metadata with the node writes and step number, and an "ISO 8601 timestamp of when this checkpoint was created." It is state, not a log of model calls: latencies, token counts and model parameters appear only if your state stores them, so join checkpoints to your LangSmith, Langfuse or OpenTelemetry spans by thread or run ID. In-memory savers lose everything on restart ([LangGraph persistence](https://docs.langchain.com/oss/python/langgraph/persistence.md)). Database savers keep checkpoints until you prune them.

Replay one thread oldest first:

```python
config = {"configurable": {"thread_id": "1"}}
history = list(graph.get_state_history(config))   # newest first
for snap in reversed(history):
    print(snap.created_at, snap.metadata["step"], snap.next)
```


## Which export method fits each tool? A comparison

Read on each tool's own documentation on 14 November 2026. Plans and limits change; check your own plan page before a large export.

| Tool | Bulk method | Formats | Default window or page | Retention (by plan) | Watch for |
| --- | --- | --- | --- | --- | --- |
| LangSmith | Bulk export to S3-compatible storage; runs.query | Parquet; JSON via API | runs.query: 1 day unless set | 14 or 180 days | Bulk export Enterprise-only for sign-ups after 3 Aug 2026 |
| Langfuse | Blob storage export; Observations API v2 | Parquet, CSV, JSON, JSONL | API page 50 (max 1,000) | Cloud access window 30 days, 90 days or 3 years (not deletion); self-hosted unlimited | Large I/O can be left out of UI downloads; metadata cut at 200 characters |
| Arize Phoenix | get_spans_dataframe | DataFrame (save as Parquet or CSV) | Default project, capped at limit=1000 spans | Indefinite by default | Raise limit (no cursor); content depends on instrumentation |
| Braintrust | BTQL via POST /btql | JSON, Parquet | One page per request, 30-second timeout | 14 or 30 days; Enterprise custom | 20 requests per minute |
| Helicone | npx @helicone/export | JSON, JSONL, CSV | Last 30 days unless --start-date/--end-date set | 7 days to forever | Bodies only with --include-body |
| W&B Weave | get_calls; /calls/stream_query | Records via API; UI export | limit per page; page with offset | Not stated on the page read | Select root calls for whole traces |
| Datadog LLM Observability (now Agent Observability) | Export API | JSON | Last 15 minutes; page 10 (max 5,000) | 15, 30, 60 or 90 days | 50 MB response cap |
| OpenTelemetry GenAI | Your backend's export | OTLP or backend format | Backend-specific | Backend-specific | Content attributes are opt-in |
| OpenHands | Conversation download; trajectory download | Zip of events; JSON files | Events page max 100 | Not stated on the pages read | Cloud host and retention not documented there |
| LangGraph | get_state_history; checkpointer.list | State snapshots | Your own store | Until you prune | State only: join to model-call spans |


## Worked example: rebuilding one complete run from exported spans

Most tools export spans, not runs. To turn them back into one record per run: group spans by trace ID; order them by start time and parent ID; attach each tool result to the [tool call](https://origindatapartners.com/glossary/tool-call) that produced it; add the reasoning where it was captured and mark it full, summary or none; then add the outcome from the system of record (the ticket, the ledger entry, the test result) with its source.

Fictional example: an on-call agent investigates a failed nightly job. The export holds 41 spans under one trace ID: one agent span, 14 model calls and 26 tool calls (log searches, a deploy-history query, two metric queries). Ordering by start time shows a wrong first hypothesis, three log reads that rule it out and the deploy that caused the failure. The ticket system shows the incident closed with the root cause accepted by the engineer on call, which becomes the outcome and its source. The rebuilt run is one JSON line: task, 40 ordered steps, outcome, model and harness.


## Which format should exported traces end up in?

Pick one format for every run, whatever tool it came from, so each [trajectory](https://origindatapartners.com/glossary/agent-trajectory) reads the same way. Plain JSONL with one run per line is the simplest. Open trajectory formats now exist: Harbor's ATIF "records an agent's complete interaction history as JSON: messages, reasoning, tool calls, observations, and metrics" ([ATIF](https://docs.harborframework.com/agents/atif)), and Letta's package "formats trajectories across harnesses in a consistent, agent-friendly format" ([Letta trajectory](https://www.letta.com/blog/trajectory/)). Keep the model, model version, [harness](https://origindatapartners.com/glossary/agent-harness) and harness version on every run.


## Common mistakes when exporting agent traces

Each of these turns a complete run into a fragment:

- Exporting with the default window (15 minutes, one day) and assuming the file holds everything.
- Using a UI download for volume: large inputs, outputs or metadata can be cut.
- Exporting only model calls and dropping tool spans, so the results the agent read are missing.
- Leaving out failed or retried runs, which are often the most informative.
- Losing the outcome: the trace records what the agent did, not whether the ticket stayed closed.
- Waiting past the retention window. Export, or raise retention, before a deadline passes.


## Before you share an export

Raw traces carry secrets, personal data and customer content in tool results. Run the [agent trace redaction checklist](https://origindatapartners.com/guides/agent-trace-redaction-checklist) before an export leaves the team, rotate any keys it finds, and keep a redaction log so the trace stays usable.

Thinking of licensing your traces? The [guide to licensing agent traces](https://origindatapartners.com/guides/license-ai-agent-traces) covers what AI developers ask for, the provider terms and who can sign, and you can [describe your agent traces](https://origindatapartners.com/check-fit?sector=agent-traces#company-review) without sending files.


## Questions and answers

### Why is my agent trace export missing tool results?

Usually because tool spans were not exported, payloads were truncated, or content capture was off. Export all span kinds, use the bulk path or the flag that returns full content, and with OpenTelemetry check that content capture was switched on when the agent ran.

### Can I get the reasoning tokens from OpenAI or Anthropic models in an export?

Not the raw reasoning. OpenAI's reasoning guide says reasoning tokens are not visible via the API and offers a summary instead; Claude's docs say a thinking block holds a summary of Claude's reasoning, and on Claude 5 and later models the thinking display defaults to omitted unless you opt in; Gemini returns thought summaries only when you enable them. Your traces can only contain what the API returned, so record whether reasoning is full, a summary or absent. An [open-weight model](https://origindatapartners.com/glossary/open-weight-model) you host yourself can keep the full reasoning.

### How long do tracing tools keep agent traces?

It depends on the plan. LangSmith keeps 14 days on base retention and 180 on extended; Langfuse Cloud lets you view and query 30 days, 90 days or 3 years of history by plan (an access window, not deletion); Datadog keeps 15 to 90 days; Phoenix and self-hosted Langfuse keep data until you delete it.

### Can I export directly from a self-hosted Langfuse instance?

Yes. Blob storage export is available on self-hosted Langfuse, as are the UI downloads and the public API, and self-hosted data is kept until you delete it.

### Is LangSmith bulk export available on every plan?

No. For customers who signed up after 3 August 2026, bulk export is Enterprise only; earlier customers keep it on Plus or Enterprise until 1 February 2027. The SDK query path works on other plans, within its rate limits.

### Why does the Datadog export API return so few spans?

It exports the past 15 minutes by default and returns 10 spans per page. Set filter[from] and filter[to] and raise page[limit], up to 5,000, then follow the cursor.

### Do LangGraph checkpoints count as agent traces?

They hold the graph state after each step, which is part of a trace. They do not record model calls, latencies or token counts unless your state stores them, so join them to your model-call spans.

## Sources

- [LangSmith docs: bulk export trace data](https://docs.langchain.com/langsmith/data-export)
- [LangSmith docs: query traces with the SDK](https://docs.langchain.com/langsmith/export-traces)
- [LangSmith docs: administration overview (trace retention)](https://docs.langchain.com/langsmith/administration-overview)
- [Langfuse FAQ: export a single trace or session](https://langfuse.com/faq/all/export-single-trace-or-session)
- [Langfuse docs: export from the UI](https://langfuse.com/docs/api-and-data-platform/features/export-from-ui)
- [Langfuse docs: export to blob storage](https://langfuse.com/docs/api-and-data-platform/features/export-to-blob-storage)
- [Langfuse docs: public API](https://langfuse.com/docs/api-and-data-platform/features/public-api)
- [Langfuse docs: data retention](https://langfuse.com/docs/administration/data-retention)
- [Arize Phoenix docs: extract data from spans](https://arize.com/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans)
- [Arize Phoenix docs: data retention](https://arize.com/docs/phoenix/settings/data-retention)
- [Braintrust docs: export data](https://docs.braintrust.dev/annotate/export)
- [Braintrust API reference: query (BTQL)](https://docs.braintrust.dev/api-reference/query.md)
- [Braintrust knowledge base: BTQL rate limits](https://docs.braintrust.dev/kb/btql-rate-limits)
- [Braintrust pricing (retention by plan)](https://www.braintrust.dev/pricing)
- [Helicone docs: export tool](https://docs.helicone.ai/tools/export)
- [Helicone API: query requests (ClickHouse)](https://docs.helicone.ai/rest/request/post-v1requestquery-clickhouse)
- [Helicone cookbook: getting sessions](https://docs.helicone.ai/guides/cookbooks/getting-sessions)
- [Helicone pricing (retention by plan)](https://www.helicone.ai/pricing)
- [W&B Weave docs: query and export calls](https://docs.coreweave.com/products/wandb/weave/guides/tracking/querying-calls)
- [Datadog docs: LLM Observability export API](https://docs.datadoghq.com/llm_observability/investigate/export_api)
- [Datadog docs: data retention periods](https://docs.datadoghq.com/data_security/data_retention_periods)
- [OpenTelemetry GenAI semantic conventions: agent spans](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md)
- [OpenTelemetry GenAI semantic conventions: model spans and content capture](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)
- [OpenTelemetry GenAI semantic conventions: execute_tool span](https://raw.githubusercontent.com/open-telemetry/semantic-conventions-genai/main/docs/gen-ai/execute-tool.md)
- [OpenHands Cloud API: export conversation](https://docs.openhands.dev/openhands/usage/cloud/api-reference/conversations/export-conversation)
- [OpenHands agent server API: download trajectory](https://docs.openhands.dev/sdk/guides/agent-server/api-reference/files/download-trajectory)
- [OpenHands agent server API: search conversation events](https://docs.openhands.dev/sdk/guides/agent-server/api-reference/events/search-conversation-events.md)
- [OpenHands SDK: conversation persistence](https://docs.openhands.dev/sdk/guides/convo-persistence.md)
- [LangGraph docs: checkpointers](https://docs.langchain.com/oss/python/langgraph/checkpointers)
- [LangGraph docs: persistence](https://docs.langchain.com/oss/python/langgraph/persistence.md)
- [Harbor: Agent Trajectory Interchange Format (ATIF)](https://docs.harborframework.com/agents/atif)
- [Letta: the trajectory package (23 July 2026)](https://www.letta.com/blog/trajectory/)
- [OpenAI API docs: reasoning models](https://developers.openai.com/api/docs/guides/reasoning)
- [Claude API docs: thinking](https://platform.claude.com/docs/en/build-with-claude/thinking)

## Related reading

- [PII Redaction for Agent Traces and LLM Logs: A Checklist](https://origindatapartners.com/guides/agent-trace-redaction-checklist)
- [Agent Traces: Licensing Production AI Agent Runs (2026)](https://origindatapartners.com/guides/license-ai-agent-traces)
- [Can an AI startup license its usage data and agent logs?](https://origindatapartners.com/guides/license-ai-product-usage-data)
- [License data for AI evaluation: training, testing and holdouts](https://origindatapartners.com/guides/license-data-for-ai-evaluation)
- [Export Jira Data and Confluence Spaces: Complete Guide](https://origindatapartners.com/guides/export-jira-confluence-data)
- [/glossary/agent-trace](https://origindatapartners.com/glossary/agent-trace)
- [/glossary/tool-call](https://origindatapartners.com/glossary/tool-call)
