Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.inference.net/llms.txt

Use this file to discover all available pages before exploring further.

Catalyst instruments the Cursor SDK in TypeScript. Initialize tracing before calling Agent.create() so the Agent static methods and the returned SDKAgent / Run objects are patched before any run is observed. Use this guide for Node applications that run programmatic Cursor agents with @cursor/sdk. Cursor publishes a TypeScript SDK only, so there is no Python equivalent for this integration.
Cursor’s SDK streams runs over HTTP/2 via @connectrpc/connect-node. Run Catalyst-traced Cursor apps under Node (>= 22). Bun’s HTTP/2 client currently emits NGHTTP2_FRAME_SIZE_ERROR mid-stream against api.cursor.com.

What Is Captured

  • One AGENT span named Cursor Agent Run per observed run, started lazily when run.stream(), run.wait(), run.conversation(), or run.cancel() is first called
  • cursor.agent_id, cursor.run_id, cursor.run_status, cursor.duration_ms, request IDs, and model metadata (llm.model_name, llm.invocation_parameters)
  • input.value from agent.send() and output.value from streamed assistant text, run.wait() results, or run.conversation() turns
  • TOOL child spans for streamed tool_call events, including tool.name, tool_call.id, JSON arguments, and tool results
  • Aggregate counts: agent.tool_call_count, agent.llm_call_count
  • Error status and exception details when run streaming, waiting, or cancellation fails

Install

bun add @inference/tracing @cursor/sdk

TypeScript Cursor Agent Run

Initialize tracing before creating Cursor agents. Auto-instrumentation detects @cursor/sdk when it is installed in the project, so the smoothest path is just setup().
TypeScript
import { Agent } from "@cursor/sdk";
import { setup } from "@inference/tracing";

const tracing = await setup({
  serviceName: "cursor-agent-runner",
});

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});

try {
  const run = await agent.send("Summarize what this repository does");

  for await (const event of run.stream()) {
    console.log(event.type);
  }

  const result = await run.wait();
  console.log(`run ${run.id} ${result.status}`);
} finally {
  await agent[Symbol.asyncDispose]();
  await tracing.shutdown();
}
For manual initialization, pass the SDK namespace into the granular entry point:
TypeScript
import * as CursorSdk from "@cursor/sdk";
import { setup } from "@inference/tracing";
import { instrumentCursorSdk } from "@inference/tracing/cursor-sdk";

const tracing = await setup({ autoInstrument: false });
instrumentCursorSdk(CursorSdk, tracing);

Lazy Span Lifecycle

The AGENT span starts when the application first observes a run through run.stream(), run.wait(), run.conversation(), or run.cancel(), not when agent.send() returns. This avoids leaking open spans for fire-and-handoff workflows where one process kicks off a Cursor run and another process observes it later. Each unique observed run produces one AGENT span; observing the same run twice in the same process does not double-emit.

Verify In Catalyst

Filter traces by your service.name (for example cursor-agent-runner). A successful run should show one Cursor Agent Run AGENT span with cursor.run_id and the model name, plus nested TOOL spans for each tool call the agent produced. For short-lived scripts, always call tracing.shutdown() before process exit so batched spans are flushed to Catalyst.