Tags
Attribute every AI call to a customer, feature, user, project and environment, so cost per customer, feature, team or project comes for free.
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:
@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)
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:
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
customertag (see 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.