AgentLedger documentation
AgentLedger shows what your team's AI coding agents cost and what that spend produced, inside your Snowflake account. This guide covers installing the app, connecting your agents and tools, and how every number is calculated.
Requirements
- A Snowflake account with Cortex Code enabled. The app reads its telemetry from
SNOWFLAKE.LOCAL.AI_OBSERVABILITY_EVENTSandSNOWFLAKE.ACCOUNT_USAGE. - ACCOUNTADMIN, or a platform role that can grant the privileges the app requests, to install it.
- For the built-in GitHub, GitLab, Jira or Linear connections, an account that allows external access integrations. Snowflake trial accounts don't.
- For Claude Code, Cursor CLI and Gemini CLI, Python 3.10 or later on each developer's machine.
1. Install the app
Get AgentLedger from Snowflake Marketplace and install it as ACCOUNTADMIN, or a platform role that can grant the requested privileges. Approve them when Snowsight asks: read access to SNOWFLAKE.ACCOUNT_USAGE, serverless tasks, and an X-Small warehouse for the dashboard.
The installing role becomes an app admin. It owns the app, so it holds APP_ADMIN, and everyone with that role can read developers' prompts. Install with a narrow role such as ACCOUNTADMIN, never a broad one such as SYSADMIN or a shared team role.
The examples below assume the app is named AGENTLEDGER. Replace it with your app's name if you chose another.
2. Let the app read Cortex Code traces
Run as ACCOUNTADMIN:
GRANT APPLICATION ROLE SNOWFLAKE.AI_OBSERVABILITY_READER TO APPLICATION AGENTLEDGER;
Cortex Code sessions appear on the next refresh. Open the dashboard from the app's page in Snowsight. Its Setup view shows which steps are complete.
3. Give auditors the dashboard
The dashboard is an admin tool for auditing AI usage. It shows developers' prompts, replies and tool details, and it changes settings. Grant it through a dedicated role, so that access is named and reviewable and ACCOUNTADMIN stays out of daily use:
CREATE ROLE IF NOT EXISTS AI_USAGE_AUDITOR;
GRANT APPLICATION ROLE AGENTLEDGER.APP_ADMIN TO ROLE AI_USAGE_AUDITOR;
GRANT ROLE AI_USAGE_AUDITOR TO USER <auditor>;
-- Optional: the cost and session views in SQL, without prompts
GRANT APPLICATION ROLE AGENTLEDGER.APP_VIEWER TO ROLE <analyst_role>;
4. Connect developer machines
This step adds branch and pull request attribution for Cortex Code, and brings in Claude Code, Cursor CLI and Gemini CLI, whose sessions never reach Snowflake telemetry.
-
Publish the developer plugin. In the dashboard, open Setup, then Git integration, and turn on Publish the git hook plugin to this account. Or run:
CALL AGENTLEDGER.core.publish_plugin();This adds a Cortex Extension, already configured for your app, which the app keeps up to date on every upgrade.
core.unpublish_plugin()removes it. -
Give developers the reporter role:
GRANT APPLICATION ROLE AGENTLEDGER.APP_REPORTER TO ROLE <developer_role>; -
Each developer runs, once:
uv tool install agentledger # or: pipx install agentledger agentledger install # add --app <name> if your app isn't AGENTLEDGERagentledger installchecks that the developer's Snowflake connection can reach the app, installs the plugin for Cortex Code, and adds hooks for each of Claude Code, Cursor CLI and Gemini CLI it finds. After each turn, those sessions are queued and loaded into the app in the background.agentledger statuschecks the setup.
When the app is upgraded, cortex plugin check shows the update and cortex plugin update agentledger installs it.
5. Sync pull requests
Open the app in Snowsight, choose Configure, and bind the GitHub or GitLab references: API access, and a read-only token. For GitHub, create a fine-grained token under Settings → Developer settings → Fine-grained tokens, limited to the repositories you want, with Pull requests: Read-only.
Pull requests sync every 15 minutes. Accounts without external access can push pull requests from CI or a laptop with the provided script, which calls core.ingest_pull_requests.
6. Connect Jira or Linear
On the dashboard's Setup view, under Issue tracker, set your Jira site URL and account email, or keep Linear's default host api.linear.app, and save. Then, on the app's page in Snowsight, choose Configure and approve that tracker's API access and token. Approving again picks up a site or host you change later.
How cost is calculated
- Model cost per request comes from
SNOWFLAKE_COCO_USAGE_HISTORYwhen Snowflake has billed it. Otherwise it is estimated: uncached input, output, cache-write and cache-read tokens multiplied by the model's AI credits per million tokens, from Snowflake's published Cortex Code prices, then converted at your price per AI credit. Admins can edit model prices on the Setup view. - Claude Code, Cursor CLI and Gemini CLI sessions are estimated from their token counts and the same editable price list.
- Side requests, such as session-title generation, count toward the session they follow.
- Agent SQL is costed from
QUERY_ATTRIBUTION_HISTORYat your price per platform credit. - Per pull request: requests on the pull request's head branch, from when the previous pull request on that branch closed (or 30 days before this one opened) until this one is merged or closed. Each request is attributed to the branch in effect when it started, so switching branches mid-session is handled.
Models without a price are flagged on the Setup view and in the session list until an admin adds one.
Efficiency score
Each session gets a score from 0 to 100, and the session page shows how each part contributed:
| Part | Default weight | What it measures |
|---|---|---|
| Reliability | 35% | The share of model requests and agent SQL queries that succeeded |
| Cache reuse | 25% | The share of input read from the prompt cache; 90% or more scores full marks |
| Focus | 20% | Model requests per turn: two or fewer scores full marks, ten or more scores zero |
| Cost | 20% | Cost per turn against your account's median |
Admins can change the weights on the Setup view.
Work types
Each session is tagged with the kinds of work it did. Tags come from metadata only, never from prompts, answers or file contents:
- Branch names and pull request titles: for example
fix/…for bug fixes,feat/…for new features, and keywords for tests, documentation, dependencies, refactors and migrations. - SQL the agent ran: queries only means data analysis; DDL or DML means data changes.
- Tools the agent used: reading files without editing them means code review and exploration; no tools and no SQL means questions.
Data freshness
Data refreshes every 30 minutes, and pull requests sync every 15. Snowflake delivers traces on a best-effort basis and ACCOUNT_USAGE views can lag by a few hours, so recent Cortex Code activity can take a while to appear. Sessions from the developer CLI arrive within a few minutes. Admins can turn either schedule off under Data refresh on the Setup view.
Query it in SQL
Roles with APP_VIEWER can query the core views directly. Some starting points:
Agent cost per developer, last 30 days
SELECT user_name, agent, COUNT(*) AS sessions, SUM(turns) AS turns,
ROUND(SUM(cost_usd), 2) AS cost_usd
FROM AGENTLEDGER.CORE.SESSIONS
WHERE started_at >= DATEADD(day, -30, CURRENT_TIMESTAMP())
GROUP BY 1, 2
ORDER BY cost_usd DESC;
Agent cost behind each pull request
SELECT repo_slug, number, title, state, sessions, developers,
ROUND(cost_usd, 2) AS cost_usd
FROM AGENTLEDGER.CORE.PR_COSTS
WHERE sessions > 0
ORDER BY merged_at DESC NULLS FIRST;
Cost by branch
SELECT repo_slug, branch, sessions, turns, ROUND(cost_usd, 2) AS cost_usd, last_activity
FROM AGENTLEDGER.CORE.BRANCH_COSTS
ORDER BY last_activity DESC;
Other views: core.request_costs, core.daily_costs, core.session_work_types, core.session_prs, core.pr_activity and core.branch_activity.
Privacy and access
- Everything runs inside your Snowflake account. The app never sends data to us, and we have no access to your account.
- Costs, scores and work types use metadata only: token counts, timings, tool names and status.
- Prompts, replies and tool details are read only when someone with
APP_ADMINopens a session's trace. For Cortex Code they are read from Snowflake's trace events at that moment, and the app keeps no copy. - Git reports include the repository, branch and commit, never the remote URL or any file content.
- Reports are accepted only from the Snowflake user who ran the session, so nobody can attach a branch to, or replace, someone else's session.
Questions? Email [email protected] or see Support.