# Tags

Tags are how a call becomes "Acme's support bot" instead of "a gpt-5-mini call". Five have their own columns in the ledger, and every report, budget and export can use them:

| Tag | What to put in it | Used for |
|---|---|---|
| `customer` | The paying account: your org, workspace or tenant id | Cost and margin per customer, per-customer budgets |
| `feature` | The product surface: `support-bot`, `summaries`, `search` | Cost per feature, classification in the monthly close |
| `user` | The end user inside the customer | Cost per active user, per-user budgets on free plans |
| `project` | Whatever else you divide work by: a team, program, pipeline or cost center, such as `protein-design`, `eval-harness`, `claims-ops` | Cost per project, project budgets, classification in the close |
| `environment` | `production`, `staging`, `development` | Separating test spend; `development`, `dev`, `staging`, `test` and `research` are classified as R&D by default |

Anything else you pass (`plan="pro"`, `region="eu"`) is kept as a free-form tag on the call.

## Where to set them

Set tags once, at the edge of a request, not at every call:

```python [Python]
@app.middleware("http")
async def tag_requests(request, call_next):
    with veqen.tags(customer=request.state.org_id, user=request.state.user_id):
        return await call_next(request)
```

```ts [TypeScript]
app.use((req, res, next) => withTags({ customer: req.org.id, user: req.user.id }, next));
```

Then name the feature where the client is created, with `wrap(client, feature=...)`, or with a nested `tags()` block around a specific flow. Inner tags override outer ones.

## No customers? Tag projects

If AI is something your company uses rather than sells (research, data labeling, internal agents, evaluation runs), `customer` stays empty and `project` does the work. Give each team, program or pipeline a project, and the ledger answers what each one costs, a project budget caps it, and the close books it to the right account:

```python
gpu_free = veqen.wrap(OpenAI(base_url="https://api.together.xyz/v1"), project="protein-design")
with veqen.tags(project="eval-harness", environment="research"):
    run_evals()
```

## Rules

- Values are strings up to 128 characters (64 for `environment`). Free-form tags: up to 32 per call, values up to 256 characters.
- Don't put personal data in tags. Use your internal ids, not emails or names; Veqen stores tags as given.
- Use the same customer value everywhere: the Stripe connection matches revenue to the `customer` tag (see [Margin](/docs/margin)).
- Calls without a customer show as "(untagged)". The Customers page tells you how much spend that is. Group by project in Explore for the same view of internal spend.
