Skip to content

Analytics and AI usage

Accessed via client.analytics, client.usage and client.ai_rates.

The server enforces scope: you only see your own teams, a led organisation, or (administrators) everything. Costs are reported per currency and never summed across currencies.

from datetime import datetime, timedelta, timezone
from pyawe import AweClient, UsageEvent

client = AweClient("https://awe.example.com")
client.login("me@example.com", "secret")

now = datetime.now(timezone.utc)
ai = client.analytics.ai(from_=now - timedelta(days=30), to=now)
print(ai.totals.input_tokens, [(c.currency, c.cost_micros / 1_000_000) for c in ai.totals.costs])

client.usage.record(UsageEvent("anthropic", "claude-sonnet-5-5", source="script",
                               input_tokens=1200, output_tokens=300, external_id="run-42"))

pyawe.client.AnalyticsClient

AnalyticsClient(http: _HttpSession)

Aggregated activity, time, team/organisation comparison and AI usage (/analytics/*).

The server enforces scope: you see your own teams, a led organisation, or (admin) everything. The arguments only narrow that scope. organization_id may be the nil UUID (00000000-0000-0000-0000-000000000000) to select rows with no organisation (admin only).

overview

overview(*, from_: datetime | None = None, to: datetime | None = None, granularity: str | None = None, tz: str | None = None, organization_id: UUID | str | None = None, team_id: UUID | str | None = None, mine: bool | None = None) -> AnalyticsOverview

Totals, workflows by status and a time series.

Parameters:

Name Type Description Default
from_ datetime | None

Start of the period (default: server picks the last 30 days).

None
to datetime | None

End of the period.

None
granularity str | None

"day" (default), "week" or "month".

None
tz str | None

IANA time zone used to bucket the series, e.g. "Europe/Dublin".

None
organization_id UUID | str | None

Narrow to one organisation.

None
team_id UUID | str | None

Narrow to one team.

None
mine bool | None

True resolves an administrator as an ordinary member (their own teams).

None

jobs

jobs(*, from_: datetime | None = None, to: datetime | None = None, granularity: str | None = None, tz: str | None = None, organization_id: UUID | str | None = None, team_id: UUID | str | None = None, mine: bool | None = None) -> AnalyticsJobs

Per-job activity, busiest first (same arguments as :meth:overview).

time

time(*, from_: datetime | None = None, to: datetime | None = None, granularity: str | None = None, tz: str | None = None, organization_id: UUID | str | None = None, team_id: UUID | str | None = None, mine: bool | None = None) -> AnalyticsTime

Time in status by period, job, person and step, plus lead time.

teams

teams(*, from_: datetime | None = None, to: datetime | None = None, granularity: str | None = None, tz: str | None = None, organization_id: UUID | str | None = None, team_id: UUID | str | None = None, mine: bool | None = None) -> AnalyticsGroups

Compare the teams in scope.

organizations

organizations(*, from_: datetime | None = None, to: datetime | None = None, granularity: str | None = None, tz: str | None = None, organization_id: UUID | str | None = None, team_id: UUID | str | None = None, mine: bool | None = None) -> AnalyticsGroups

Compare organisations, including the "no organisation" group.

Raises:

Type Description
AweAuthError

If the caller is not an administrator.

ai

ai(*, from_: datetime | None = None, to: datetime | None = None, granularity: str | None = None, tz: str | None = None, organization_id: UUID | str | None = None, team_id: UUID | str | None = None, mine: bool | None = None) -> AnalyticsAi

Recorded AI usage: tokens, cost per currency, by model and source, triage quality.

pyawe.client.UsageClient

UsageClient(http: _HttpSession)

Report AI usage to the ledger behind /analytics/ai (POST /usage-events).

record

record(*events: UsageEvent) -> UsageRecorded

Record one or more AI calls. Retrying with the same external_id is safe.

Raises:

Type Description
AweValidationError

If an event is invalid (e.g. cost without currency).

pyawe.client.AiRatesClient

AiRatesClient(http: _HttpSession)

Per-organisation AI price list used to price usage (/admin/ai-rates, admin only).

list

list(organization_id: UUID | str | None = None) -> builtins.list[AiRate]

List rates, optionally for one organisation.

set

set(organization_id: UUID | str, provider: str, model: str, *, currency: str, input_micros_per_mtok: int, output_micros_per_mtok: int, cache_read_micros_per_mtok: int = 0, cache_creation_micros_per_mtok: int = 0, effective_from: datetime | None = None) -> AiRate

Add or replace a rate. Prices are millionths of currency per million tokens (e.g. 0.75 per million tokens is 750_000). model must match what is reported.

delete

delete(rate_id: UUID | str) -> None

Delete a rate.