Skip to content

Activity and costs

Lens keeps a ledger of what happens to each resource and what it cost: every request that changes something, every call it makes out (a language model, embeddings, the decision model, text to speech, a webhook, a web tool), and every job or routine run that ends. It is on by default and needs nothing set up.

What a row holds

Each row names every resource it counts for, as table:id:

Resource Example
A routine and one of its runs routine:3, routine_run:12
An automation and one of its runs automation:4, automation_run:51
A job, its asset, namespace and pipeline job:40, recording:7, space:1, pipeline:2
A workflow workflow:4
A chat chat:9
A note (its refinement and filing, and the requests that changed it) note_page:5
The person who asked account:1

A model call inside a workflow step of a job that a routine queued counts for the workflow, the job, the asset, its namespace, its pipeline and the routine. A request counts for the resources in its path (PATCH /api/v1/routines/3 is routine:3), for what a POST made (from the id in its reply), and for who sent it.

Besides the resources, a row has its kind (in, out or run), what it was (POST /api/v1/routines/{rid}, model.chat, model.describe (a picture Florence-2 or Moondream described on this server), embeddings, decision, notify.webhook, tool.http, workflow.http, web.search, web.read, google.token, gmail.list, job.succeeded, routine.done), the model, tokens in and out, the estimated cost in USD, how long it took, and how it ended (an error's type or HTTP status, never its message). It never holds prompt, reply, asset text or file content.

Costs

Each model is costed the way you set it under Settings › Telemetry › prices (telemetry.prices), or, for the assistant's model, Settings › AI assistant:

Unit Setting For
Tokens {"input": 3.0, "output": 15.0} (USD per million tokens) cloud models that bill by tokens
Time {"unit": "time", "per_hour": 0.6} (USD per hour a call takes) a local model on your own machine
Audio {"unit": "minute", "per_minute": 0.006} (USD per minute of audio heard) speech to text providers
Characters {"unit": "characters", "per_million": 15} (USD per million characters read aloud) text to speech providers
Off {"unit": "off"}, or leave the model out the default: no money counted, only tokens and time

Speech providers are named the way their ledger rows name them, the provider then the model: deepgram:nova-3, openai:whisper-1 or assemblyai:universal for a transcription (speech.transcribe, costed by the recording's length, detail.seconds), and elevenlabs:eleven_multilingual_v2 or openai:tts-1 for an answer read aloud (model.speech, costed by detail.chars). In Settings › Telemetry › prices that's one line each, like deepgram:nova-3 0.0043 per minute or openai:tts-1 15 per million characters; check the provider's own price list, since Lens ships none.

So local models aren't costed unless you give them a price. decisions.price_per_call gives the decision model's price per decision.

A figure that should have a cost but doesn't (a model priced by tokens whose server didn't report how many it used) marks the row unpriced, and every total that includes it says estimate: true: the cost shown is a floor, and the web app shows it with ≈.

A run row (a job or a routine run ending) repeats what its calls cost in all, and the job or run keeps it too (cost_usd, tokens). Totals don't count run rows twice.

Reading it

A resource's history merges its ledger rows with its audit log entries and its changes to the entity graph (both kind change; a graph change's action is graph.<op>, with its version, how it was made and why in detail; see graph-history.md), newest first:

GET /api/v1/activity?resource=routine:3&limit=100
GET /api/v1/activity?resource=routine:3&kind=out&before=2026-10-04T09:00:00.000+00:00

What it cost this day, week (from Monday) or month (UTC), or all time:

GET /api/v1/activity/totals?resource=pipeline:2&period=month
GET /api/v1/activity/totals?period=day            # everything (admins)
GET /api/v1/activity/top?table=routine&period=week  # what cost most (admins)

Admins see every resource. Everyone else sees their own account's activity, their own chats', and the assets and namespaces they can read.

Settings

Setting Default
activity.enabled true Off stops new rows (the audit log carries on).
activity.reads false Log API reads (GET) too. The web app reads often, so this grows the ledger fast.
activity.keep_days 365 Rows older than this are dropped, hourly, by the routines scheduler.

Sign-in requests (/api/v1/auth/, /api/v1/passkeys/) aren't logged here; the audit log records sign-ins.

Refine later

Compute time as a cost for local models (CPU seconds at a rate), per-person totals in the web app, and calls the ledger doesn't see yet (Fedora sync, Matterbridge messages).