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 customer tag (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.