Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions docs/ai-coder/agents/platform-controls/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,13 @@ none, if the template does not define any).

### Spend management

Administrators can set spend limits to cap LLM usage per user within a rolling
time period, with per-user and per-group overrides. The cost tracking dashboard
provides visibility into per-user spending, token consumption, and per-model
breakdowns.
The Spend page provides usage-only reporting for Coder Agents chats. The native
usage-limit configuration UI has been removed from release 2.36, but values
configured before upgrading remain stored and enforced. Existing native values
are not migrated to AI Gateway budgets.

See [Spend Management](./usage-insights.md) for details.
Configure new AI Gateway budgets from group settings or through the generated
group budget API. See [Spend Management](./usage-insights.md) for details.

### Git providers

Expand Down
111 changes: 36 additions & 75 deletions docs/ai-coder/agents/platform-controls/usage-insights.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,51 @@
# Spend Management

Coder provides admin-only controls for monitoring and controlling agent
spend: usage limits and cost tracking.
Coder provides usage reporting for Coder Agents and two independent ways to
limit spend on release 2.36: existing native chat usage limits and AI Gateway
budgets.

## Usage limits
## Native chat usage limits

Navigate to **Agents** > **Settings** > **Manage Agents** > **Spend**.
The native usage-limit configuration UI has been removed from release 2.36.
Values configured before upgrading remain stored and enforced. Coder checks the
user's current spend before processing each chat message and returns a **409
Conflict** response when the applicable limit is reached.

Usage limits cap how much each user can spend on LLM usage within a rolling
time period. When enabled, the system checks the user's current spend before
processing each chat message.
Existing native values are not migrated to AI Gateway budgets. To change spend
controls after upgrading, configure new AI Gateway budgets. Native limits remain
in effect until they are changed through the existing experimental API or
removed in a later release.

### Configuration
## AI Gateway budgets

- **Enable/disable toggle** — master on/off for the entire limit system.
- **Period** — `day`, `week`, or `month`. Periods are UTC-aligned: midnight
UTC for daily, Monday start for weekly, first of the month for monthly.
- **Default limit** — deployment-wide default in dollars. Applies to all
users who do not have a more specific override. Leave unset for no limit.
- **Per-user overrides** — set a custom dollar limit for an individual user.
Takes highest priority.
- **Per-group overrides** — set a limit for a group. When a user belongs to
multiple groups, the lowest group limit applies.
AI Gateway budgets cap each user's AI Gateway spend, including Coder Agents
chats, over a monthly period.

### Priority hierarchy
- Set a group budget from the group's settings page.
- When a user belongs to several budgeted groups, the deployment budget policy
selects the applicable group. The default policy selects the highest budget.
- A per-user override takes priority over group budgets.

The system resolves a user's effective limit in this order:
Budget controls require a license that includes AI Gateway. Existing native
usage-limit values and recorded spend are not migrated when you configure a
budget.

1. Individual user override (highest priority)
1. Minimum group limit across all of the user's groups
1. Global default limit
1. No limit (if limits are disabled or no value is configured)
The API reference documents how to
[get](../../../reference/api/enterprise.md#get-group-ai-budget),
[upsert](../../../reference/api/enterprise.md#upsert-group-ai-budget), and
[delete](../../../reference/api/enterprise.md#delete-group-ai-budget) a group
budget.

### Enforcement
The Agents page shows the signed-in user's current AI Gateway spend and budget
when AI Gateway is available.

- Checked before each chat message is processed.
- When current spend meets or exceeds the limit, the chat returns a
**409 Conflict** response and the message is blocked.
- Fail-open: if the limit query itself fails, the message is allowed
through.
- Brief overage is possible when concurrent messages are in flight, because
cost is determined only after the LLM returns.
## Spend visibility

### User-facing status
Navigate to **Agents** > **Settings** > **Manage Agents** > **Spend** to view
usage-only reporting for deployment-wide Coder Agents chat costs.

Users can view their own spend status, including whether a limit is active,
their effective limit, current spend, and when the current period resets.
The top-level table includes total cost, message and chat counts, and token usage
for each user. It supports date range filtering, search, and pagination.

> [!NOTE]
> The admin configuration page shows the count of models without pricing
> data. Models missing pricing cannot be tracked accurately against limits.

## Cost tracking

Navigate to **Agents** > **Settings** > **Manage Agents** > **Spend**.

This view shows deployment-wide LLM chat costs with per-user drill-down.

### Top-level view

A per-user rollup table with the following columns:

| Column | Description |
|--------------------|-------------------------------------|
| Total cost | Aggregate dollar spend for the user |
| Messages | Number of chat messages sent |
| Chats | Number of distinct chat sessions |
| Input tokens | Total input tokens consumed |
| Output tokens | Total output tokens consumed |
| Cache read tokens | Tokens served from cache |
| Cache write tokens | Tokens written to cache |

The table supports date range filtering (default: last 30 days), search by
name or username, and pagination.

### Per-user detail view

Select a user to see:

- **Summary cards** — total cost, token breakdowns, and message counts.
- **Usage limit progress** — if a limit is active, a color-coded progress
bar shows current spend relative to the limit.
- **Per-model breakdown** — table of costs and token usage by model.
- **Per-chat breakdown** — table of costs and token usage by chat session.

> [!NOTE]
> Automatic title generation uses lightweight models, such as Claude Haiku or GPT-4o
> Mini. Its token usage is not counted towards usage limits or shown in usage
> summaries.
Select a user to view summary cards and per-model and per-chat breakdowns. The
Spend page does not configure native usage limits or AI Gateway budgets.
40 changes: 18 additions & 22 deletions docs/ai-coder/ai-gateway/cost-controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,35 +270,31 @@ see [Prometheus metrics](../../admin/integrations/prometheus.md).

## Migrate from Coder Agents Cost Control

In v2.36, AI Governance Cost Control replaces Coder Agents Cost Control. The
legacy Coder Agents Spend page remains available until v2.37.
In release 2.36, the native Coder Agents usage-limit configuration UI is no
longer available. Existing native values remain stored and enforced, and are not
migrated to AI Gateway budgets.

> [!WARNING]
> Spend limits configured under **Admin settings** > **AI** > **Spend** are no
> longer enforced by Coder Agents. To enforce spend, set an AI Governance budget.

To migrate existing limits:

1. Record the limits currently set under **Admin settings** > **AI** >
**Spend**, including the default limit and any group or user overrides.
1. Recreate group limits as [group budgets](#group-budget).
1. Recreate per-user limits as [user overrides](#user-override).
Configure new AI Gateway budgets from the group settings page or use the API to
[get](../../reference/api/enterprise.md#get-group-ai-budget),
[upsert](../../reference/api/enterprise.md#upsert-group-ai-budget), or
[delete](../../reference/api/enterprise.md#delete-group-ai-budget) a group
budget.

Expect the following differences:

- No deployment-wide default exists. Each group that needs a limit requires its
own budget.
- The UTC calendar month is the only period. Daily and weekly periods are not
currently supported.
- Users in several budgeted groups receive the highest budget. Coder Agents Cost
Control applied the lowest.
- Native limits and AI Gateway budgets are independent. A user can be subject to
both until native limits are removed in a later release.
- AI Gateway has no deployment-wide default budget. Each group that needs a
limit requires its own budget.
- The UTC calendar month is the only budget period. Daily and weekly periods are
not currently supported.
- Users in several budgeted groups receive the highest budget by default. Native
Coder Agents usage limits apply the lowest group limit.
- Budgets cover priced AI Gateway traffic. Chat, IDE extensions, and CLI agents
draw on the same budget when their provider and model are priced. See
[How spend is estimated](#how-spend-is-estimated).
- Recorded spend does not carry over. Every user starts the first period at
$0 USD.
- Coder Agents users who exceed their budget see a usage limit error in chat.
The error details include the AI Governance budget limit.
- Recorded spend and native limit values do not carry over to AI Gateway
budgets.

## Next steps

Expand Down
2 changes: 1 addition & 1 deletion docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@
},
{
"title": "Spend Management",
"description": "Set spend limits and track AI costs for Coder Agents with admin-only controls.",
"description": "Track Coder Agents usage and configure new spend controls with AI Gateway budgets.",
"path": "./ai-coder/agents/platform-controls/usage-insights.md",
"state": ["beta"]
},
Expand Down
65 changes: 0 additions & 65 deletions site/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3948,71 +3948,6 @@ class ExperimentalApiMethods {
const response = await this.axios.get<TypesGen.ChatCostUsersResponse>(url);
return response.data;
};

getChatUsageLimitConfig =
async (): Promise<TypesGen.ChatUsageLimitConfigResponse> => {
const response =
await this.axios.get<TypesGen.ChatUsageLimitConfigResponse>(
"/api/experimental/chats/usage-limits",
);
return response.data;
};

getChatUsageLimitStatus =
async (): Promise<TypesGen.ChatUsageLimitStatus> => {
const response = await this.axios.get<TypesGen.ChatUsageLimitStatus>(
"/api/experimental/chats/usage-limits/status",
);
return response.data;
};

updateChatUsageLimitConfig = async (
req: TypesGen.ChatUsageLimitConfig,
): Promise<TypesGen.ChatUsageLimitConfig> => {
const response = await this.axios.put<TypesGen.ChatUsageLimitConfig>(
"/api/experimental/chats/usage-limits",
req,
);
return response.data;
};

upsertChatUsageLimitOverride = async (
userID: string,
req: TypesGen.UpsertChatUsageLimitOverrideRequest,
): Promise<TypesGen.ChatUsageLimitOverride> => {
const response = await this.axios.put<TypesGen.ChatUsageLimitOverride>(
`/api/experimental/chats/usage-limits/overrides/${encodeURIComponent(userID)}`,
req,
);
return response.data;
};

deleteChatUsageLimitOverride = async (userID: string): Promise<void> => {
const response = await this.axios.delete(
`/api/experimental/chats/usage-limits/overrides/${encodeURIComponent(userID)}`,
);
return response.data;
};

upsertChatUsageLimitGroupOverride = async (
groupID: string,
req: TypesGen.UpsertChatUsageLimitGroupOverrideRequest,
): Promise<TypesGen.ChatUsageLimitGroupOverride> => {
const response = await this.axios.put<TypesGen.ChatUsageLimitGroupOverride>(
`/api/experimental/chats/usage-limits/group-overrides/${encodeURIComponent(groupID)}`,
req,
);
return response.data;
};

deleteChatUsageLimitGroupOverride = async (
groupID: string,
): Promise<void> => {
const response = await this.axios.delete(
`/api/experimental/chats/usage-limits/group-overrides/${encodeURIComponent(groupID)}`,
);
return response.data;
};
}

// This is a hard coded CSRF token/cookie pair for local development. In prod,
Expand Down
85 changes: 0 additions & 85 deletions site/src/api/queries/chats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1994,91 +1994,6 @@ export function paginatedChatCostUsers(
};
}

export const chatUsageLimitStatusKey = [
...chatsKey,
"usageLimitStatus",
] as const;

export const chatUsageLimitStatus = () => ({
queryKey: chatUsageLimitStatusKey,
queryFn: () => API.experimental.getChatUsageLimitStatus(),
refetchInterval: 60_000,
});

const chatUsageLimitConfigKey = [...chatsKey, "usageLimitConfig"] as const;

export const chatUsageLimitConfig = () => ({
queryKey: chatUsageLimitConfigKey,
queryFn: () => API.experimental.getChatUsageLimitConfig(),
});

export const updateChatUsageLimitConfig = (queryClient: QueryClient) => ({
mutationFn: (req: TypesGen.ChatUsageLimitConfig) =>
API.experimental.updateChatUsageLimitConfig(req),
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: chatUsageLimitConfigKey,
});
},
});

type UpsertChatUsageLimitOverrideMutationArgs = {
userID: string;
req: TypesGen.UpsertChatUsageLimitOverrideRequest;
};

export const upsertChatUsageLimitOverride = (queryClient: QueryClient) => ({
mutationFn: ({ userID, req }: UpsertChatUsageLimitOverrideMutationArgs) =>
API.experimental.upsertChatUsageLimitOverride(userID, req),
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: chatUsageLimitConfigKey,
});
},
});

export const deleteChatUsageLimitOverride = (queryClient: QueryClient) => ({
mutationFn: (userID: string) =>
API.experimental.deleteChatUsageLimitOverride(userID),
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: chatUsageLimitConfigKey,
});
},
});

type UpsertChatUsageLimitGroupOverrideMutationArgs = {
groupID: string;
req: TypesGen.UpsertChatUsageLimitGroupOverrideRequest;
};

export const upsertChatUsageLimitGroupOverride = (
queryClient: QueryClient,
) => ({
mutationFn: ({
groupID,
req,
}: UpsertChatUsageLimitGroupOverrideMutationArgs) =>
API.experimental.upsertChatUsageLimitGroupOverride(groupID, req),
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: chatUsageLimitConfigKey,
});
},
});

export const deleteChatUsageLimitGroupOverride = (
queryClient: QueryClient,
) => ({
mutationFn: (groupID: string) =>
API.experimental.deleteChatUsageLimitGroupOverride(groupID),
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: chatUsageLimitConfigKey,
});
},
});

// ── MCP Server Configs ───────────────────────────────────────

export const mcpServerConfigsKey = ["mcp-server-configs"] as const;
Expand Down
Loading
Loading