Skip to main content
Tags let you attach string labels to your AgentMark traces via the SDK. Use tags to categorize traces by environment, team, feature, experiment, or any other dimension, then filter by those tags in the AgentMark dashboard.

Setting tags via the trace function

Pass a tags array when creating a trace. All spans within the trace inherit these tags:
import { AgentMarkSDK } from "@agentmark-ai/sdk";
import { createAgentMarkClient, VercelAIModelRegistry } from "@agentmark-ai/ai-sdk-v5-adapter";
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import { trace } from "@agentmark-ai/sdk";

const sdk = new AgentMarkSDK({
  apiKey: process.env.AGENTMARK_API_KEY,
  appId: process.env.AGENTMARK_APP_ID,
});

sdk.initTracing();

const modelRegistry = new VercelAIModelRegistry()
  .registerModels(["gpt-4o-mini"], (name) => openai(name));

const client = createAgentMarkClient({
  loader: sdk.getApiLoader(),
  modelRegistry,
});

const { result, traceId } = await trace(
  {
    name: "user-request",
    tags: ["production", "chat-v2", "team-alpha"],
    metadata: {
      userId: "user-123",
    },
  },
  async (ctx) => {
    const prompt = await client.loadTextPrompt("handler.prompt.mdx");
    const input = await prompt.format({
      props: { query: "Hello" },
      telemetry: { isEnabled: true },
    });
    return await generateText(input);
  }
);
You can combine tags with metadata on the same trace. Tags are for categorical labels (environment, team), while metadata is for unique identifiers and configuration values (user IDs, request IDs).

Setting tags via OpenTelemetry attributes

If you are building a custom integration or using OpenTelemetry directly, you can set tags via the agentmark.tags span attribute. The AgentMark gateway accepts tags as a JSON array string or a comma-separated string:
import api from "@opentelemetry/api";

const tracer = api.trace.getTracer("agentmark");

tracer.startActiveSpan("my-operation", (span) => {
  // JSON array string
  span.setAttribute("agentmark.tags", JSON.stringify(["production", "v2"]));

  // Or comma-separated string
  span.setAttribute("agentmark.tags", "production,v2");

  // Your logic here
  span.end();
});
The trace() function’s tags option is the recommended approach for most applications. Use the OpenTelemetry attribute approach only when you need direct control over span attributes, such as in custom instrumentation or non-SDK integrations.

Tags on child spans

Tags set on the parent trace are aggregated to the trace level in the dashboard. You can also set tags on individual child spans using setAttribute:
import { trace } from "@agentmark-ai/sdk";

const { result, traceId } = await trace(
  {
    name: "multi-step-workflow",
    tags: ["production", "search-feature"],
  },
  async (ctx) => {
    // Child span with additional tags
    await ctx.span({ name: "retrieval-step" }, async (spanCtx) => {
      spanCtx.setAttribute("agentmark.tags", JSON.stringify(["rag-v3"]));
      // Retrieval logic here
    });

    // Another child span
    await ctx.span({ name: "generation-step" }, async (spanCtx) => {
      const prompt = await client.loadTextPrompt("generate.prompt.mdx");
      const input = await prompt.format({
        props: { query: "What is AgentMark?" },
        telemetry: { isEnabled: true },
      });
      return await generateText(input);
    });
  }
);
In the AgentMark dashboard, this trace displays with all three tags: production, search-feature, and rag-v3.

Viewing tags in the dashboard

Tags appear as a column in the trace list and as chips in the trace detail view. You can filter traces by tag to quickly find traces in a specific environment, from a specific team, or part of a specific experiment. For details on filtering and the available operators, see the Tags platform documentation.

Best practices

Use consistent naming conventions

Adopt kebab-case for tag names across your codebase to keep tags predictable and easy to filter:
// Consistent kebab-case
tags: ["production", "team-alpha", "chat-v2"]

// Avoid mixing formats
tags: ["Production", "team_alpha", "chatV2"]  // Inconsistent

Define tags as constants

Avoid typos and inconsistencies by defining your tag values as constants:
const Tags = {
  ENV_PRODUCTION: "production",
  ENV_STAGING: "staging",
  TEAM_ALPHA: "team-alpha",
  TEAM_PLATFORM: "team-platform",
  FEATURE_CHAT: "chat-v2",
  FEATURE_SEARCH: "search-rerank",
} as const;

const { result } = await trace(
  {
    name: "user-request",
    tags: [Tags.ENV_PRODUCTION, Tags.TEAM_ALPHA, Tags.FEATURE_CHAT],
  },
  async (ctx) => {
    // Your logic here
  }
);

Keep the tag set small

Tags work best with a bounded set of known values. If a dimension has hundreds or thousands of unique values (like user IDs or request IDs), use metadata instead.

Next steps

Traces and logs

Learn about trace collection and span attributes

Sessions

Group related traces together

Tags in the dashboard

View and filter tags in the platform