OPEN SOURCE · SELF-HOSTED

The flight recorder for AI agents.

Trajekt records every step of every run — reasoning, tool calls, inputs and outputs, tokens, latency, cost — so when an agent goes off the rails in production, you can replay exactly what happened.

Get started
npm i @trajekt-ai/core
AGENT FLIGHT RECORDER · DO NOT OPENREC
run_7f3e9a21 · sentry-triage40.6s · $0.162
  1. #2llm.generate
  2. #3sentry.getIssue
  3. #5gitlab.searchCode
  4. #7gitlab.readFile
  5. #9jira.createIssueRETRY ×2
  6. #10llm.generate
  7. #11gitlab.searchCodeREPEAT #5
  8. #13gitlab.searchCodeREPEAT #5
  9. #14llm.generate
  10. #15gitlab.createMergeRequest422
Steps #11 and #13 repeat #5 with identical arguments. #15 fails with 422.

When an agent fails, logs show you the last error. Not the nine steps that led to it.

01 · Replay

What did it actually do?

Step through a run like a timeline. Each step shows the prompt, the model's reasoning, the exact tool arguments and what the tool returned.

#9 jira.createIssue · arguments
{
  "project": "PAY",
  "summary": "NPE in checkout discount",
  "priority": "High"
}
attempts
  • 1429 Too Many Requests
  • 2429 Too Many Requests
  • 3201 Created · PAY-1432
02 · Diagnose

Why did this run cost twice as much?

Tokens, latency and cost are broken down per step. Retries, repeated tool calls and loops are flagged on the timeline, so the expensive part is the first thing you see.

cost per LLM step
  • #2$0.009
  • #4$0.013
  • #6$0.018
  • #8$0.025
  • #10$0.024
  • #12$0.028
  • #14$0.046
repeated searchCode ×22 retries · 7.3s backoff
03 · Compare

Did my prompt change break it?

Put two runs side by side, aligned step by step. Added steps, wrong tools and changed outcomes stand out, next to the configuration that changed between them.

A · prompt v1.8.2B · prompt v1.9.0
  • =sentry.getIssuesentry.getIssue
  • =gitlab.searchCodegitlab.searchCode
  • +—gitlab.searchCode
  • +—gitlab.searchCode
  • ≠jira.createIssuejira.createIssue · priority
  • −gitlab.readFile—
  • +—gitlab.createMergeRequest · 422
steps 12 → 16 · cost +100% · outcome failed

Try it on a real trace.

Load an example — or your own export — and replay it step by step, with loops, retries and failures flagged.

Langfuse trace export, OTLP/JSON or a Vercel AI SDK result — drop it anywhere on this panel. It is read in your browser by @trajekt-ai/core; nothing is uploaded.

AGENT FLIGHT RECORDER · REPLAYFAILED
sentry-triage · otlp28.0s · ≈$0.112
Steps
17
Tool calls
10
Repeated calls
2
Retries
2
Tokens
27,447

#7 and #9 repeat an earlier call with identical arguments. 2 retries after a failure. The run failed.

#7 gitlab.searchCodeTool call
Duration
675ms
Started at
+10.1s
Same call as
#5
ARGUMENTS
{
  "query": "checkout/discount.ts",
  "scope": "blobs"
}

tool path: sentry.getIssue → gitlab.searchCode ×3 → gitlab.readFile → jira.createIssue → gitlab.createMergeRequest → slack.postMessage

Example files: otlp-sentry-triage.json · langfuse-support-bot.json · ai-sdk-trip-planner.json

Three lines to your first recording.

  1. 01

    Instrument

    Point any OpenTelemetry exporter at Trajekt. Spans following the GenAI semantic conventions or the Vercel AI SDK telemetry are understood as-is.

  2. 02

    Record

    Every run becomes a trajectory: steps, tool arguments and results, tokens, latency and cost, grouped per agent and version.

  3. 03

    Replay

    Open any run on a timeline, compare it with another, and see when a new version starts looping, failing or costing more.

// instrumentation.ts — standard OpenTelemetry, nothing proprietary
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';

new NodeSDK({
  serviceName: 'sentry-triage',
  traceExporter: new OTLPTraceExporter({
    url: 'http://localhost:3000/v1/traces',
    headers: { Authorization: `Bearer ${process.env.TRAJEKT_API_KEY}` },
  }),
}).start();

// With the Vercel AI SDK, turn telemetry on for each call:
await generateText({
  model, prompt, tools,
  experimental_telemetry: { isEnabled: true, functionId: 'sentry-triage' },
});

Already have traces? @trajekt-ai/core reads them in your own code and tests:

import { normalize, computeMetrics } from '@trajekt-ai/core';

// A Langfuse export, OTLP/JSON spans or an AI SDK result
const run = normalize(trace);
const { status, costUsd, redundantToolCalls, retryCount } = computeMetrics(run);
Works withOpenTelemetry · OTLP/HTTP JSON & protobufGenAI semantic conventionsVercel AI SDKOpenInference · LangChain, LlamaIndexLangfuse import

Your traces stay on your infrastructure.

Prompts and tool results often contain customer data. Trajekt is open source and runs with one Docker Compose file, next to your agents.

Record your next run.