Skip to content

Usage Limits ​

A conversation on @cognipeer/agent-server 0.3.0 or later can have a usage limit (a budget): a cap on what its turns cost. When the limit is used up the turn stops, and the conversation waits for a higher limit or ends. Chat shows where the conversation stands, closes the composer when nothing more can be sent, and - where the host allows it - lets a person raise the limit and carry on.

New in 0.4.0

The usage meter, the "limit reached" notice, raise-and-continue, and the useChat members that drive them. The server side (prices, how a limit is set and enforced) is in Usage & Budgets.

Nothing changes for a conversation that has no limit.

When to use it ​

Give a conversation a limit when people with open-ended access (a public portal, a trial, an intranet assistant) could run up a bill, and let Chat show where they stand. Show the meter to operators and to people who budget their own usage; hide it (showBudgetMeter={false}) where amounts should stay private. The notice still shows when the limit is used up.

What the page shows ​

The server sends conversation.budget ({ maxCostUsd, onReach }), conversation.spentUsd and conversation.runtime.status. Chat draws a thin meter while there is room and a notice once the limit is used up:

Conversation usage                    $1.25 of $5.00 used
[██████░░░░░░░░░░░░░░░░░░░░░░░░░░]
onReachWhen the limit is used up
pauseThe conversation is paused and carries on from where it stopped once the limit is raised. runtime.status is budget_paused, and a turn the limit stopped midway stays that way after the raise until it is continued (or a new message abandons it).
stopThe conversation has ended. Raising the limit reopens it, but nothing is carried on. The notice does not promise to.

In both cases the composer is closed (composerState is budget_paused) and the last answer carries the "usage limit" notice. A send the server refuses with budget_reached (402) makes the page fetch the conversation again, which shows the notice.

tsx
<Chat
  showBudgetMeter={false}          // hide the meter (default true); the notice still shows
/>

The usage meter above the composer: Conversation usage, $0.0024 of $0.05 used

The meter shows amounts in USD (formatUsd: two decimals, four for amounts under one cent so they do not read as zero, in the page's locale). The server only sends a limit for conversations that have one. Turn the meter off where people should not see amounts.

Who may do what about it ​

What a person can do once the limit is used up is the host's call, because the server may refuse a change (budget_forbidden, unless the host set authorizeBudget).

Prop (or capabilities.budget.* of the agent)The banner offers
nothing (default)"Ask an administrator to raise the limit."
allowBudgetContinue / allowContinueContinue, for a paused conversation whose limit was raised somewhere else. While the limit is still used up the server answers 402 budget_reached, and that is shown.
allowBudgetEdit / allowEditA field for a new limit with Increase and continue (paused) or Increase limit (ended), and Remove limit. The new limit has to be above what was spent.
tsx
<Chat allowBudgetEdit />                       // for operators

An agent can say it for itself: a host that lists its agents puts capabilities: { budget: { allowContinue: true } } in the agent's info (GET /agents). It overrides the props, in both directions, so a portal can allow it for one agent only.

From code ​

tsx
const chat = useChat({ baseUrl, agentId });

chat.budget;            // { maxCostUsd, onReach } | null
chat.spentUsd;
chat.budgetExhausted;   // used up
chat.composerState;     // "budget_paused" when it is

await chat.updateBudget({ maxCostUsd: 20, onReach: "pause" }, { continue: true });
await chat.updateBudget(null);                     // remove the limit
await chat.continueConversation();                 // carry on a paused turn

updateBudget resolves false when the server refused the change and error says why. With continue: true the turn the limit stopped carries on afterwards, as a new assistant message - but only when the server's answer to the change says it can: continuable: true. A turn the limit stopped midway stays budget_paused after the raise and is continuable; a turn that had already finished its answer before the limit is not (the raise only reopens the conversation), and no continue request is made. A server that does not send continuable is read by the runtime its answer reports (still budget_paused means carry on), and one that reports neither keeps what the page knew. continuable is on the answer to the change and on a loaded conversation (Conversation.continuable). When a continuation ends the conversation is fetched again, so what it has cost (spentUsd) and the meter are the server's figures even where the end of the turn does not carry them. A "nothing to continue" answer (someone else already did, or the agent cannot be continued) is not an error. It resolves true once the limit is changed, whatever the continuation then does. canUpdateBudget and canContinue say whether the transport can do it at all.

A paused conversation whose limit has room again (raised in another window, or here when the continuation failed) shows Continue beside the field for a new limit, so a person who can edit the limit does not have to raise it a second time just to carry on.

onBudgetReached({ conversationId, budget, spentUsd }) is called when a turn ends on the limit.

BudgetBanner is the component, and renderBudgetBanner replaces it:

tsx
<Chat renderBudgetBanner={(props) => <MyBanner {...props} />} />

Transport ​

ts
interface ChatTransport {
  updateBudget?(conversationId: string, budget: ConversationBudget | null): Promise<Conversation>;   // PATCH /conversations/:id
  continueConversation?(conversationId: string, options?: ContinueOptions): Promise<SendMessageResponse | undefined>;   // POST /conversations/:id/continue
}

AgentServerClient implements both. A refusal arrives as an error with the server's code (budget_forbidden, invalid_budget, budget_reached, nothing_to_continue) and details (spentUsd, maxCostUsd, onReach).

Troubleshooting ​

SymptomCause and fix
No meter showsThe conversation has no budget (the server only sends one for conversations that have a limit), spentUsd is missing, or showBudgetMeter is false.
The composer is closed and says the conversation reached its usage limitcomposerState is budget_paused. Raise the limit (the banner offers it only where allowBudgetEdit or the agent's capabilities.budget.allowEdit is on) or ask an administrator.
"You can not change the usage limit of this conversation"The server refused with budget_forbidden. What a person may do is decided on the server as well as by the props.
"Enter an amount above $x"The new limit has to be above what was spent.
Continue answers "usage limit" againThe limit is still used up: the server answers 402 budget_reached until it has room.
Raising the limit only reopens the conversationThe turn had already finished its answer before the limit (continuable: false) or the budget is onReach: "stop": there is nothing to carry on.

Next steps ​

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub