Last updated

/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".

Billing tab -- This Agent
Billing tab -- This Agent

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.

Billing tab -- Per User
Billing tab -- Per User

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.

Billing tab -- New User Limit
Billing tab -- New User Limit

Row actions -- Edit and Delete per user.

Billing tab -- row actions
Billing tab -- row actions

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

Billing tab -- Delete Spend Limit
Billing tab -- Delete Spend Limit

Common setup (brand, conventions, env files, verification): see docs/skill-setup.md.

Prerequisites

  • Auth set up (/iblai-vibe-auth, or vibe-starter).
  • AgentSettingsProvider wraps the route (/iblai-vibe-agent Β§1).
  • @iblai/iblai-js@^2.62.1 (resolves @iblai/web-containers 1.62.1). Check with pnpm 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.

PropTypeRequiredDescription
labelsDeepPartial<SpendCapsTabLabels>NoOverride user-visible strings
tenantKeystringNoOrganization key; defaults to AgentSettingsProvider
mentorIdstringNoAgent UUID; defaults to AgentSettingsProvider
headerClassNamestringNoExtra classes on the tab header (e.g. wider padding in a wide dialog)
bodyClassNamestringNoExtra classes on the scrollable body

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}/.

ActionRequest
Load This AgentGET agents/{uuid}/spend-cap/ (404 means no limit yet)
Save This AgentPUT agents/{uuid}/spend-cap/ -- an upsert: 201 the first time, 200 after
Delete LimitDELETE agents/{uuid}/spend-cap/
Load Per UserGET agents/{uuid}/spend-caps/users/
Save / status switch for a userPUT agents/{uuid}/spend-caps/users/{username}/ (the switch re-sends the limit with enabled flipped)
Delete a user limitDELETE 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

HookPurpose
useGetAgentSpendCapQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutationThis Agent
useListAgentUserSpendCapsQuery, useGetUserSpendCapQuery, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutationPer User
useGetSpendCapStatusQueryUser-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:

  1. pnpm build -- must pass with zero errors.
  2. pnpm test -- vitest must pass.
  3. Touch test /agents/<uuid>/billing in the browser as /iblai-vibe-ops-test says, 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 AgentSettingsProvider once at the layout level (/iblai-vibe-agent Β§1); do not wrap each tab.
  • Peer deps: sonner and @iblai/iblai-web-mentor (pnpm add sonner @iblai/iblai-web-mentor).
  • Brand guidelines: BRAND.md

Copyright Β© ibl.ai | support@iblai.zendesk.com