> ## Documentation Index
> Fetch the complete documentation index at: https://puzzlet-9ba7bb98.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Trace grouping

> Group AgentMark traces by session, user, and metadata with the @agentmark-ai/otel OpenTelemetry helper.

AgentMark groups your OpenTelemetry traces by session, user, tags, and custom metadata. A small wrapper stores the grouping in the OpenTelemetry context, and a span processor stamps it onto every span in scope. In TypeScript this is the `@agentmark-ai/otel` package (`withAgentMark` + `AgentMarkSpanProcessor`); in Python it's built into `agentmark-sdk` (`with_agentmark`, registered automatically by `init_tracing`).

Reach for it when you instrument with OpenTelemetry rather than the AgentMark SDK's `span()` helpers. It's the recommended way to group traces on the **Vercel AI SDK v7**, where the `telemetry.metadata` option no longer reaches spans. It also groups any other OpenTelemetry span in the same scope, such as an OpenInference instrumentor, an HTTP request, or a custom span.

## TypeScript

<Steps>
  <Step title="Install the package">
    ```bash theme={null}
    npm install @agentmark-ai/otel @opentelemetry/sdk-trace-node
    ```
  </Step>

  <Step title="Register the span processor">
    Add `AgentMarkSpanProcessor` to your OpenTelemetry setup with your API key and app id from project settings. The `register()` call installs the context manager that carries grouping across `await`.

    ```typescript theme={null}
    // instrumentation.ts
    import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
    import { AgentMarkSpanProcessor } from "@agentmark-ai/otel";

    const provider = new NodeTracerProvider({
      spanProcessors: [
        new AgentMarkSpanProcessor({
          apiKey: process.env.AGENTMARK_API_KEY!, // raw key, no "Bearer" prefix
          appId: process.env.AGENTMARK_APP_ID!,
        }),
      ],
    });

    provider.register();
    ```
  </Step>

  <Step title="Wrap your calls">
    Pass session, user, tags, and metadata to `withAgentMark`. Every span created inside the callback carries them.

    ```typescript theme={null}
    import { withAgentMark } from "@agentmark-ai/otel";
    import { generateText } from "ai";

    await withAgentMark(
      {
        sessionId: "session-456",
        userId: "user-123",
        tags: ["production"],
        metadata: { feature: "support-chat" },
      },
      () => generateText({ model, prompt: "How do I reset my password?" }),
    );
    ```
  </Step>
</Steps>

## Python

Python grouping lives in the `agentmark-sdk` package. `init_tracing()` registers the grouping processor for you, so you only wrap your calls.

Install the package:

```bash theme={null}
pip install agentmark-sdk
```

Initialize tracing once at startup with your API key and app id from project settings:

```python theme={null}
from agentmark_sdk import AgentMarkSDK

sdk = AgentMarkSDK(api_key="...", app_id="...")
sdk.init_tracing()
```

Then wrap your calls with `with_agentmark(...)`. Every span started inside it (sync or async) carries the grouping:

```python theme={null}
from agentmark_sdk import with_agentmark

with with_agentmark(
    session_id="session-456",
    user_id="user-123",
    tags=["production"],
    metadata={"feature": "support-chat"},
):
    # your OpenTelemetry-instrumented calls (OpenInference, etc.)
    ...
```

## What gets grouped

`withAgentMark` accepts these fields:

* `sessionId` and `sessionName`: group related calls into one [session](/observe/sessions).
* `userId`: attribute the trace to a user.
* `traceName`: name the trace.
* `tags`: string labels for [filtering and search](/observe/filtering-and-search).
* `metadata`: any custom key and value pairs, surfaced as [trace metadata](/observe/metadata).

The processor stamps these onto every span in the wrapped scope, so the whole trace groups together, not only the model calls. The Python `with_agentmark` takes the same fields in snake\_case: `session_id`, `session_name`, `user_id`, `trace_name`, `tags`, and `metadata`.

<Note>
  `withAgentMark` needs an OpenTelemetry context manager so the grouping propagates across `await`. Both `NodeTracerProvider.register()` and `@vercel/otel` register one.
</Note>

<div className="mt-8 rounded-lg bg-blue-50 p-6 dark:bg-blue-900/30">
  <h3 className="font-semibold mb-3">Have questions?</h3>
  <p className="mb-4">Reach out any time:</p>

  <ul>
    <li>
      Email the team at <a href="mailto:hello@agentmark.co" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200">[hello@agentmark.co](mailto:hello@agentmark.co)</a> for support
    </li>

    <li>
      Schedule an <a href="https://cal.com/ryan-randall/enterprise" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200">Enterprise Demo</a> to learn about AgentMark's business solutions
    </li>
  </ul>
</div>
