Create a verifiable archive first. Then prepare a separate dataset of useful examples and instrument new traffic in Lunary. An export is not an automatic recreation of the source project.
Engineers exporting LangSmith history for analysis or migration
Small, targeted archive
Use the documented SDK list_runs method or runs query API, with a fixed project and time window.
Large archive
Use bulk export to S3-compatible storage if your account meets the current plan and signup-date eligibility.
Destination
Keep raw history intact. Transform a selected copy for evaluation and verify newly instrumented traffic separately.
At a glance
| Source information | Preserve in archive | Use during migration |
|---|---|---|
| Run, trace, and parent IDs | Original values | Reconstruct relationships and retain provenance |
| Inputs and outputs | Original approved payload | Explicitly select dataset input and observed output |
| Feedback and scores | Score name, value, and associated run | Review before treating a score as ground truth |
| Model and prompt context | Identifiers, version, and parameters when present | Explain differences when replaying a case |
| Times and cost | Source values and units | Compare equivalent request windows |
1. Define the archive before exporting
Record the project, environment, start time, exclusive end time, and any applied filters. Decide whether you need every operation or only root runs. Root-only archives can be useful for a task-level dataset, but they do not preserve the complete trace tree. Identify whether inputs and outputs contain data that should be excluded from the working dataset while retaining your approved archive policy.
- Preserve run ID, trace ID, parent run ID, and timestamps.
- List prompts, datasets, scores, and project configuration as separate migration objects.
- Use a dedicated output file for every time window so retries do not silently append duplicates.
2. Export a bounded sample with the Python SDK
Configure the LangSmith SDK credentials and endpoint for your account and set ARCHIVE_PROJECT to the project you want to read. This example streams SDK results to JSONL rather than accumulating them in memory. It includes child runs and filters the upper date boundary locally. Choose a recent, small window for the first pass; this sample is not a resumable whole-history exporter.
import json
import os
from datetime import datetime, timezone
from langsmith import Client
start = datetime(2026, 9, 1, tzinfo=timezone.utc)
end = datetime(2026, 9, 2, tzinfo=timezone.utc)
client = Client()
count = 0
# Exclusive creation protects an existing archive from replacement.
with open("langsmith-sample.jsonl", "x", encoding="utf-8") as archive:
for run in client.list_runs(
project_name=os.environ["ARCHIVE_PROJECT"],
start_time=start,
):
if not start <= run.start_time < end:
continue
archive.write(json.dumps(run.dict(), default=str) + "\n")
count += 1
print(f"Archived {count} runs; reconcile with the source project.")3. Use bulk export for large volumes when eligible
LangSmith's bulk export writes Parquet data to S3-compatible storage and is designed for larger exports. Check the live eligibility note: the available plan depends on when the customer signed up. Configure the destination with the necessary write access, choose the project and fixed time range, and inspect the job's final status. A created job or a nonempty bucket is not proof that the complete export finished.
4. Reconcile the result
Compare the source count for the same window and filters with the count of unique exported run IDs. Inspect an error, a nested trace, a streaming response, and a representative successful run. Parent references outside your window can be legitimate; record them rather than inventing missing parents. Keep the query definition, export completion time, file checksums, and any exclusions next to the archive.
5. Prepare useful examples for Lunary
Select examples that exercise the application behavior you want to improve, then map them into a dataset format explicitly. Lunary documents CSV and JSONL dataset import through its API. Do not post an untouched LangSmith run object and assume it becomes a native Lunary trace. Preserve a sidecar map from dataset rows to source run IDs. Instrument new traffic, compare one full workflow in both tools, and remove the old integration only after the intended cutover is validated.
Common questions
Will this migrate the entire LangSmith project into Lunary?
No. It creates an archive and outlines a controlled move. Prompts, evaluation objects, permissions, and native trace history need separate handling.
Why can exported run counts differ from trace counts?
A trace can contain multiple runs. Compare the same unit, filters, time boundaries, and root-versus-child selection in both places.
Does a failed model output belong in ground truth?
No. Keep the observed output distinct from the expected correct behavior. Have the relevant reviewer approve reference answers.
Sources & methodology
Lunary publishes this guide. We compare documented workflows and explain where each approach fits; this is not an independent benchmark or a hands-on product rating. Features, limits, and commercial terms can change. Check the linked vendor documentation before deciding.