Skip to main content
Tool permissions says which tools a role holds. This page covers the two controls that act on each call of a tool already held: asking a person, and refusing past a limit.

How an approval works

A gated tool call parks and shows the person a card with three things: the tool’s name, one plain sentence saying what will change (intent), and the literal operation (detail) so the sentence can be checked against what will run. For a spend, the engine writes the sentence from its own cost estimate; the model does not get to describe the price. Only a person can approve. Every other way a request settles is a denial, so “nobody answered” is safe by construction. The timeout is five minutes by default (APPROVAL_TIMEOUT_MS; 0 denies at once). A pending request is written to the transcript, so a dropped connection loses the view, not the decision. Turning approvals off. REQUIRE_WRITE_APPROVAL set to false, 0 or no removes the approval channel from person chat. The effect differs by tool and is listed below; most gated writes then refuse rather than run. Unattended runs (coworkers, the goal agent, the reviewer, and since 2026-10-11 an inbound email turn) have no approval channel at all, whatever the setting. Source: src/engine/approval.ts (ApprovalBroker, approvalRequired, approvalTimeoutFromEnv)

Which calls ask a person

Not gated by an approval: memory notes, project files, AgentMail drafts, content writer drafts, browser logins, and Contentsquare tools. A card with more than one yes puts the narrowest one where Approve usually is, so a quick approval grants the least. “Allow once” lasts until the conversation’s sandbox ends; “Allow for this store” is saved for the brand and can be removed under Settings → Account and security. Source: src/engine/session.ts (where each server is given or denied the approval channel), src/engine/sandbox-egress-tools.ts, src/engine/memory.ts, src/engine/shopify.ts, src/engine/dataforseo.ts, src/engine/firecrawl.ts, src/engine/sheets.ts, src/engine/github.ts, src/engine/agentmail.ts, src/engine/cloudflare.ts, src/engine/railway.ts

Model spend

A limit in agent.config.json that is zero, negative or not finite stops the server from loading the config. A monthly ledger that cannot be read stops the session before it starts, rather than reading as nothing spent. The session checks the monthly figure before starting and after every turn. On a gateway model the per-turn cost is the CLI’s estimate, not the provider’s bill. The cap still fires on the estimate. Source: src/engine/config.ts (loadConfig), src/engine/session.ts (monthly cap), src/engine/harness/registry.ts (harnessSessionLimits), src/server/registry.ts (worker overrides)

Goals

A daily figure of zero or below is refused. If today’s review spend cannot be read, no review runs. Source: src/engine/goal-reviewer.ts, src/engine/goal-store.ts, src/engine/goal-agent.ts

Connector spend

The connector’s own ledger is separate from the model ledger, so buying data never consumes the budget that keeps the session alive. The counter follows the credential: brands sharing one account’s key share one monthly counter.
For both connectors, 0 is the strictest setting, never “no limit”. A threshold of 0 asks on every call, a per-call ceiling of 0 refuses every billed call, and a monthly budget of 0 refuses every billed call for the month. Free calls, such as the account check, still run. Before PR #139 a monthly budget of 0 switched the monthly check off; that was a bug and is fixed.

Coworker allowances

A specialist that holds DataForSEO or Firecrawl must carry an allowance: The per-run figure is checked inside the connector’s gate on every call, counting what is spent plus what is held for calls still in flight. The per-day figure is checked before a run starts. Both sit under the deployment’s per-call ceiling and monthly budget, never above them. Measured once on 2026-09-23 for Firecrawl: a scrape was charged 1 credit, then a crawl that would have taken the run past a 3-credit allowance was refused with nothing spent (ALLOWANCE_CAPTURED). The DataForSEO allowance and the per-day refusal have not been exercised (ALLOWANCE_UNVERIFIED). Source: src/engine/dataforseo.ts, src/engine/firecrawl.ts, src/engine/allowance.ts, src/engine/coworkers.ts (specialistProblem)

Other caps

Source: src/engine/googleads.ts, src/engine/microsoftads.ts, src/engine/agentmail.ts, src/engine/agentmail-inbound.ts, src/engine/browser-config.ts, src/engine/coworkers.ts