Import from Braintrust
Do the shared setup first: an ingest
key, pip install metergraphrelay, and a .env holding
METERGRAPH_APP_TOKEN.
What the relay reads
Section titled “What the relay reads”Spans in a project’s logs whose span_attributes.type is llm, read
through Braintrust’s POST /btql query endpoint. Task, tool, function and
eval spans are not imported, and scores and evals are never read.
What you need
Section titled “What you need”| Credentials | A Braintrust API key, sent as a bearer token |
| Selector | A project name or project id. --project is required |
| Host | https://api.braintrust.dev, the US data plane, by default. Set BRAINTRUST_BASE_URL for the EU plane (https://api-eu.braintrust.dev) or your own |
METERGRAPH_APP_TOKEN=<your ingest key>BRAINTRUST_API_KEY=<your key># BRAINTRUST_BASE_URL=https://api-eu.braintrust.devBackfill
Section titled “Backfill”-
Decide what to import
Section titled “Decide what to import”You need the project, by name or by id, and the earliest timestamp worth importing.
-
Pull it to a file
Section titled “Pull it to a file”metergraphrelay pull braintrust --project my-project \--since 2026-08-01T00:00:00Z --output braintrust.jsonlSelector Meaning --projectRequired. A name or an id, and repeatable. Projects are queried together --since/--untilBound the span’s createdtime.--sinceis inclusive,--untilis exclusive and defaults to the moment the command started-n,--countCaps spans, never traces. Defaults to 100 --routeOverrides the route on every row. Not a selector -
Read the file, then upload it
Section titled “Read the file, then upload it”head -n 2 braintrust.jsonlmetergraphrelay push braintrust.jsonl -
Check the first rows
Section titled “Check the first rows”Open Traces in Metergraph. Braintrust’s SDK wrappers name LLM spans after the method, so a route reading
OpenAI Chat Completionon every row is expected rather than broken. When one project is one workflow, pass--routeand pull again.
Keep it current
Section titled “Keep it current”metergraphrelay sync braintrust --source-scope my-project \ --initial-since 2026-08-01T00:00:00Z --project my-projectSync takes no --since, --until or -n: the server picks the window, and
it is always bounded, so the thirty second timeout is not a concern here. It
requires --project and --source-scope, and accepts --initial-since,
--max-window-seconds, --route and --allow-skipped.
The full contract is on How ongoing sync works.
What lands in Metergraph
Section titled “What lands in Metergraph”| Field | Where it comes from |
|---|---|
| Route | The LLM span’s own name, falling back to braintrust/backfill. --route overrides both |
| Timestamp | The span’s created time, kept as the original |
| Provider and model | Inferred from the span |
| Tokens | The span’s metrics, including cache reads, cache writes and reasoning |
| Cost | Braintrust’s estimated_cost |
| Latency | The span’s own start and end |
| Status | error when the span recorded an error, otherwise success |
| Content | The span’s input and output, copied verbatim |
| Tool calls and tool names | Extracted from the span’s output |
| Trace, span and parent span | The span’s root span id, span id and first span parent |
| Tags | Braintrust span tags under braintrust_tags, and the project id under braintrust_project_id |
What does not carry over
Section titled “What does not carry over”- Environment. Braintrust rows arrive with no environment set, so they fall outside any environment filter in the dashboard.
- Function attribution, streaming detail, outcomes and repository identity, as on every import path.
- Task, tool, function and eval spans, scores and evals, which are never read.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause | What to do |
|---|---|---|
| The query times out | No --since on a large project | Bound every query |
Every route is OpenAI Chat Completion | The SDK wrapper names spans after the method | Pass --route |
| Nothing comes back from an EU project | The relay is querying the US data plane | Set BRAINTRUST_BASE_URL=https://api-eu.braintrust.dev |