/iblai-vibe-agent-billing
Mirrored from
iblai/vibeΒ·skills/agents/iblai-vibe-agent-billing/SKILL.md. This page is generated β edit it in the repository, not here.
Add the agent Billing tab (AgentSpendCapsTab) -- LLM spend limits for
this agent and for specific users of it, with how much has been used.
Scope: per agent. Two sub-tabs match the agent-level scopes: This
Agent (one limit for everything spent on the agent) and Per User
(a limit per user on this agent). The organization-wide limit lives in
organization settings (/iblai-vibe-billing). The tightest limit that
applies wins. This is one tab in the agent-settings family indexed by
/iblai-vibe-agent; it shares the AgentSettingsProvider wrapper with every
other tab.
This Agent -- the switch (on means the limit counts and is enforced),
a usage strip once a limit is saved (Spent, % of limit used, Remaining; the
bar turns amber at 80% and red when exceeded), and the form: Spend Limit
(USD), Resets Every (Day / Week / Month / Year), When the Limit Is
Reached (Block Requests or Alert Only), Alert At (% of Limit)
(comma-separated, default 80, 95), Delete Limit and Save. Before the
first save it says "No spend limit configured yet".

Per User -- one row per user (email, limit and period, a status switch that saves at once, Exceeded / Alert Only badges) and Add User Limit.

New User Limit -- pick the user by searching the organization's users (at least 2 characters; emails only, no free-text usernames), then the same form. Edit opens it without the picker.

Row actions -- Edit and Delete per user.

Delete Spend Limit -- asks for confirmation; spending is no longer limited or tracked against that limit. Delete Limit on This Agent asks the same.

Common setup (brand, conventions, env files, verification): see docs/skill-setup.md.
Prerequisites
- Auth set up (
/iblai-vibe-auth, or vibe-starter). AgentSettingsProviderwraps the route (/iblai-vibe-agentΒ§1).@iblai/iblai-js@^2.62.1(resolves@iblai/web-containers1.62.1). Check withpnpm why @iblai/web-containers.- A real agent UUID. Ask the user; never invent one.
- Org admin rights: the spend-cap endpoints are admin-only. A user without them sees a "no access" panel, except on This Agent before a limit exists: that GET answers 404 first, so they see the empty form and Save fails with a toast.
Step 1: Check Environment
Look for iblai.env in the project root with PLATFORM, DOMAIN, and
TOKEN. If it is missing, tell the user:
"You need an iblai.env with your platform configuration. Download the
template and fill in your values:
curl -o iblai.env https://raw.githubusercontent.com/iblai/vibe/refs/heads/main/iblai.env"
Step 2: Mount AgentSpendCapsTab
// app/(app)/agents/[mentorId]/billing/page.tsx
"use client";
import { AgentSpendCapsTab } from "@iblai/iblai-js/web-containers/next";
export default function AgentBillingPage() {
return (
<div className="flex h-full flex-col bg-white">
<AgentSpendCapsTab />
</div>
);
}
The tab reads tenantKey and mentorId from AgentSettingsProvider (each
can be passed as a prop instead) and does its own fetching and saving. No
grants need loading: the server answers 403 for non-admins, and the tab
shows its no-access panel (This Agent with no limit yet answers 404 first).
Show users how close they are (optional)
SpendCapUsage is the user-safe companion for chat screens: zones and
percentages only, never dollars, a warning near a limit and a banner once a
blocking limit is hit. It renders nothing while everything is fine unless
showWhenOk is set:
import { SpendCapUsage } from "@iblai/iblai-js/web-containers/next";
export function ChatSpendNotice(props: { org: string; username: string; agentId: string }) {
return <SpendCapUsage tenantKey={props.org} userId={props.username} mentorId={props.agentId} />;
}
Step 3: Customize Labels (Optional)
The tab renders with the default agent-facing copy
(AGENT_SPEND_CAPS_TAB_LABELS, localized through the SDK's i18n). Pass a
partial labels object to change any string:
import { AgentSpendCapsTab } from "@iblai/iblai-js/web-containers/next";
<AgentSpendCapsTab
labels={{
header: { title: "Spend limits" },
subTabs: { agent: "Agent limit", users: "User limits" },
}}
/>;
Label groups (SpendCapsTabLabels): header (title, description),
capability (the switch), subTabs (agent, users), tenantSections
(used by the organization Billing surface), form (field labels, interval
and enforcement options and help, noCapHint, buttons), usage (the usage
strip and badges), users (the Per User table, addButton, the user
picker), denied (the no-access panel), deleteModal, and toasts.
Step 4: Use MCP Tools for Customization
get_component_info("AgentSpendCapsTab")
get_component_info("SpendCapUsage")
get_component_info("AgentSettingsProvider")
<AgentSpendCapsTab> Props
Import from @iblai/iblai-js/web-containers/next.
| Prop | Type | Required | Description |
|---|---|---|---|
labels | DeepPartial<SpendCapsTabLabels> | No | Override user-visible strings |
tenantKey | string | No | Organization key; defaults to AgentSettingsProvider |
mentorId | string | No | Agent UUID; defaults to AgentSettingsProvider |
headerClassName | string | No | Extra classes on the tab header (e.g. wider padding in a wide dialog) |
bodyClassName | string | No | Extra classes on the scrollable body |
Related Exports
From @iblai/iblai-js/web-containers/next:
AGENT_SPEND_CAPS_TAB_LABELS-- the default label bundle.SPEND_CAPS_SUB_TABS-- the sub-tab keys (agent,users).SpendCapUsage(SpendCapUsageProps) -- the user-safe usage notice (Step 2).AgentSpendCapsTabProps,SpendCapsTabLabels-- types.
How it saves
Paths are under /api/ai-mentor/orgs/{org}/.
| Action | Request |
|---|---|
| Load This Agent | GET agents/{uuid}/spend-cap/ (404 means no limit yet) |
| Save This Agent | PUT agents/{uuid}/spend-cap/ -- an upsert: 201 the first time, 200 after |
| Delete Limit | DELETE agents/{uuid}/spend-cap/ |
| Load Per User | GET agents/{uuid}/spend-caps/users/ |
| Save / status switch for a user | PUT agents/{uuid}/spend-caps/users/{username}/ (the switch re-sends the limit with enabled flipped) |
| Delete a user limit | DELETE agents/{uuid}/spend-caps/users/{username}/ |
Every save sends interval_type (day | week | month | year),
max_cost_usd (a 2-decimal string), enforcement (block |
alert_only), alert_thresholds (fractions in (0, 1]: the form turns
80, 95 into [0.8, 0.95] and omits the field when empty) and enabled. Spent, remaining
and exceeded are computed by the server and only displayed. Per-user limits
are keyed by username; the tab shows emails.
Platform data
| Hook | Purpose |
|---|---|
useGetAgentSpendCapQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation | This Agent |
useListAgentUserSpendCapsQuery, useGetUserSpendCapQuery, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation | Per User |
useGetSpendCapStatusQuery | User-safe status (used by SpendCapUsage) |
All from @iblai/iblai-js/data-layer, with the SpendCap,
SpendCapUpsertRequest, SpendCapIntervalType, SpendCapEnforcement and
SpendCapExceededErrorBody types and SPEND_CAP_EXCEEDED_ERROR_CODE. The
organization scope has its own hooks (useGetTenantSpendCapQuery, β¦), used
by /iblai-vibe-billing. REST twin:
/iblai-api-spend-caps.
Step 5: Verify
Run /iblai-vibe-ops-test before telling the user the work is ready, and give
every page, control and state this skill added its own checkpoint β one Playwright
test titled <ID> Β· β¦ in e2e/journeys/, listed in e2e/coverage.json;
pnpm e2e:coverage must pass:
pnpm build-- must pass with zero errors.pnpm test-- vitest must pass.- Touch test
/agents/<uuid>/billingin the browser as/iblai-vibe-ops-testsays, signed in as an org admin: This Agent shows the form; save an Alert Only limit -- the usage strip appears; delete it again; read the console; check the phone width.
Important Notes
- Block means blocked: with Block Requests, an exceeded limit makes
chat and training requests fail with HTTP 429 (or a WebSocket error
frame) carrying
error_code: "spend_cap_exceeded". Match on that code, not the status: a provider rate limit is also 429. Use Alert Only while testing. - Usage is shared: everything anyone spends on the agent counts toward This Agent; a user's own spend on it counts toward their Per User limit.
- Shared provider: mount
AgentSettingsProvideronce at the layout level (/iblai-vibe-agentΒ§1); do not wrap each tab. - Peer deps:
sonnerand@iblai/iblai-web-mentor(pnpm add sonner @iblai/iblai-web-mentor). - Brand guidelines: BRAND.md