> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentmark.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Tags

> Attach string labels to traces for categorization and filtering

Tags are string labels you attach to traces for categorization, filtering, and organization. Use tags to slice trace data by environment, team, feature, experiment, or any other dimension.

## Setting tags

Attach tags to a span by setting the `agentmark.tags` span attribute. The gateway accepts a JSON array string, a comma-separated string, or a native array.

Set the attribute inside a `span()` callback using `ctx.setAttribute()`. The Dashboard aggregates the tag list onto the parent trace.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { span } from "@agentmark-ai/sdk";
    import { client } from "./agentmark.client";
    import { openai } from "@ai-sdk/openai";
    import { generateText } from "ai";

    const { result, traceId } = await span(
      {
        name: "user-request",
        metadata: { user_id: "user-123" },
      },
      async (ctx) => {
        ctx.setAttribute(
          "agentmark.tags",
          JSON.stringify(["production", "chat-v2", "team-alpha"])
        );

        const prompt = await client.loadTextPrompt("handler.prompt.mdx");
        const { messages, text_config } = await prompt.format({
          props: { query: "Hello" },
        });
        return await generateText({
          model: openai(text_config.model_name.replace(/^openai\//, "")),
          messages,
          experimental_telemetry: { isEnabled: true },
        });
      }
    );
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import json
    from agentmark_sdk import span_context, SpanOptions
    from agentmark_client import client

    async with span_context(SpanOptions(
        name="user-request",
        metadata={"user_id": "user-123"},
    )) as ctx:
        ctx.set_attribute(
            "agentmark.tags",
            json.dumps(["production", "chat-v2", "team-alpha"]),
        )

        prompt = await client.load_text_prompt("handler.prompt.mdx")
        formatted = await prompt.format(props={"query": "Hello"})
        result = await call_your_model(formatted)
    ```
  </Tab>
</Tabs>

## Tags on child spans

You can set tags on any span. The gateway aggregates tags across a trace's spans into the trace-level tag list shown in the Dashboard.

```typescript theme={null}
const { result } = await span(
  { name: "multi-step-workflow" },
  async (ctx) => {
    ctx.setAttribute(
      "agentmark.tags",
      JSON.stringify(["production", "search-feature"])
    );

    await ctx.span({ name: "retrieval-step" }, async (spanCtx) => {
      spanCtx.setAttribute("agentmark.tags", JSON.stringify(["rag-v3"]));
    });
  }
);
// Dashboard shows three tags on the trace: production, search-feature, rag-v3
```

## Filtering by tags

Tags appear as a column in the trace list. Filter by navigating to **Traces**, clicking **Filters**, selecting **Tags**, and choosing an operator and value.

## Tags vs metadata

|              | Tags                                            | Metadata                                   |
| ------------ | ----------------------------------------------- | ------------------------------------------ |
| **Format**   | Array of strings                                | Key-value pairs (string → string)          |
| **Best for** | Categorical labels (environment, team, feature) | Unique identifiers (user IDs, request IDs) |
| **Set size** | Small, known set of values                      | Unlimited unique values                    |

<Tip>If you would use it as a label or category, make it a tag. If you would use it as a lookup key, make it metadata.</Tip>

## Limits

* Up to **20 tags** per span (the gateway drops extra tags).
* The gateway trims each tag, which must be **1–100 characters**. It drops longer tags.
* The gateway ignores empty strings.

## Best practices

* **Use kebab-case**: `production`, `team-alpha`, `chat-v2` (not `Production`, `team_alpha`)
* **Define tags as constants** to avoid typos
* **Keep the tag set small.** Tags with hundreds of unique values belong in metadata
* **Recommended patterns**: environment (`production`, `staging`), team (`team-alpha`), feature (`chat-v2`), experiment (`exp-new-prompt`), release (`v2.1.0`)

<CardGroup cols={2}>
  <Card title="Metadata" icon="tag" href="/observe/metadata">
    Key-value pairs for context and debugging
  </Card>

  <Card title="Filtering and search" icon="filter" href="/observe/filtering-and-search">
    Combine tags with other filters
  </Card>
</CardGroup>

<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>
