How grouping works
Every request gets asession_id, one of two ways:
- Explicit — send an
X-Wardin-Session-Idheader and it is trusted as-is. Use this when your client knows its own task boundary (a CI job ID, a ticket number, an agent run ID). - Automatic — without the header, the gateway buckets consecutive requests from the same virtual key using an idle-timeout window (30 minutes, sliding). Each request extends the window; a gap longer than the window starts a new session.
Wardin deliberately ignores agentic clients’ own per-spawn attribution headers —
those are ephemeral process IDs, not identity. Attribution always comes from the
virtual key; sessions only group that key’s requests in time.
What a session gives you
- Cost per task — total spend across every request in the session, with the split token accounting (input / output / cache-creation / cache-read) intact
- Request count and duration — how much traffic one task actually generated
- Model mix — which models the task used
Where sessions appear
- MY LANE — each developer’s own sessions with per-session cost
- Analytics API —
GET /v1/developer/sessionsfor programmatic access, scoped to the calling key
Sessions and pricing
Because one task can be one request (a chat message) or a thousand (an agent), Wardin treats the session as the honest unit of work. If you’re comparing costs across tools or teams, compare cost per session — raw request counts punish exactly the agentic workflows that deliver the most value.Sessions as a quality signal (GitHub PR outcomes)
A session id is also how Wardin connects spend to a real business outcome. If a pull request’s body carries aWardin-Session-Id: footer matching the session id sent with its requests, a merged, closed, or reverted PR grades that session automatically:
pull_request webhook payload carries the PR body directly, so this requires no GitHub API access — just the same session id you already send via X-Wardin-Session-Id, written once more into the PR description. This is opt-in per team (the repo needs a Wardin GitHub connection) and per PR (the footer has to be present) — a PR without either produces no signal, never a guessed one. See the Claude Code guide for a copy-paste CLAUDE.md snippet.