Skip to main content
Agent governance builds on Stigg Governance, which is in public beta.

What it is

Agents act on their own. One misconfigured loop can burn through a customer’s entire credit pool overnight, and a single shared budget gives nobody a way to tell which agent did it. Agent governance makes each agent a first-class, budgeted entity in Stigg:
  • Each agent has an identity. An agent is a Governance entity of an agent entity type, owned by your customer.
  • Each agent can have its own budget. A monthly cap in credits or in a metered feature, set by you or by your customer’s admin.
  • Agents live in a tree. Place agents under teams, departments or orgs. A call is allowed only if every level above the agent still has budget.
  • Every call is attributed. Usage lands on the agent and rolls up through the tree automatically, from a single report.
  • You know why access was denied. When a call is denied, the decision says which limit was reached: the agent’s own budget, its team’s budget, or the customer’s credit balance. You can then respond the right way, for example by asking an admin to raise a budget or offering the customer more credits.

Why use it

Contain runaway agents

A per-agent cap stops one agent without stopping the others. Siblings keep working when one exhausts its own budget.

Let your customers govern their AI

Enterprise buyers want to allocate AI spend by team and by agent. Governance gives their admins the controls, and gives you the data to show them.

Answer 'which agent spent this?'

Usage is attributed to the agent that made the call and to every level above it, so cost reporting per agent, team and org comes for free.

Turn denials into revenue

An agent out of budget is an upgrade or top-up moment. The decision tells you which one.

Example use cases

The problem: a customer runs a support agent, a research agent and a coding agent from one credit balance. When the research agent loops on a bad prompt, it drains the shared balance and the other two stop working too.With Stigg: each agent gets its own monthly budget. The research agent is stopped when it reaches its own budget, and the other two keep serving users.
The problem: an enterprise customer wants to split its AI credits between departments, 60% to engineering and 40% to support, and let its own admin manage that split.With Stigg: agents are placed under their department, and each department has a budget. When a department reaches it, its agents stop, and the admin raises the budget from an interface you build on the governance query API.
The problem: the customer’s finance team wants to know which agents drive their AI spend, before deciding on any limits.With Stigg: agents are registered without a limit, so nothing is blocked, and every call is attributed to its agent and team. The customer sees usage per agent and per team without any extra reporting code.
The problem: agents also call paid tools, such as a web-search API, a data provider or a code sandbox. Each call costs you money, and an agent stuck in a loop can run thousands of them.With Stigg: tool calls are metered as their own feature, for example web searches, and checked before each call against the same agent and team budgets as its model calls. You can cap them, and charge the customer for them.

How it works

A call made as reviewer is checked against the reviewer’s own limit, the research team’s limit and the customer’s credit pool. It is allowed only if all three allow it, and its usage counts against all three. If the drafter spends its 3 credits, its access is denied with deniedBy: 'drafter', and the reviewer keeps working. If the team’s 30 credits run out first, both are denied with deniedBy: 'team-research', even though the reviewer has budget of its own left. The SDK maps this onto three steps:

1. Register the agent

stigg.register() creates the agent in Stigg: its entity, its budget, and its place in the tree. This registers the drafter from the example above, with its limit of 3 credits a month under the research team:
  • Call it once, when the agent is created in your product. It saves the agent to Stigg in two parts, matching the two groups in the example: (1) it creates the agent’s entity, or updates it if it already exists, and (2) if you pass a budget, it sets the agent’s budget and place in the tree for that entitlement (a Governance assignment). Do not call it on every model call. Wrapped clients only need the agent’s ID.
  • It is safe to call again. Each process remembers which agents it has registered. A call with only part 1 (no budget) is skipped the second time, so you can call it on every startup. A call that includes a budget is always saved, because a budget or parent change is deliberate.
  • The parent is set per budget. An agent’s place in the tree belongs to each budget, not to the agent, so it can roll up to a different parent for each credit currency or feature. For example, the drafter’s credits count against the research team’s budget, while its web searches count against a company-wide search budget managed by IT. Register it once per entitlement, each time with the matching budget.parentId.
  • Let admins own the limit, if they change it in the Stigg app. By default, budget.limit is saved on every call, so a limit changed in the Stigg app is overwritten the next time your code registers the agent. Pass apply: 'on-create' to set the limit only when the agent has no budget yet.
  • Registering is optional. If you do not register an agent, calls made with its agent ID still work, but Stigg has no entity for that agent. Its usage does not count toward any agent or team budget, and its calls are checked against the customer’s limits only.
For every field of register(), see the SDK reference.

2. Make calls as the agent

Each model call the agent makes goes through a wrapped client, which checks access before the call and reports usage after it. You do not report usage separately. Wrap the client once, and name the customer and the agent on each call, together with the attribution key of the agent’s entity type:
One wrapped client can serve every agent and every customer this way. In a real server, the customer and agent IDs come from the request being handled. attributionKey must be the attribution key declared on the agent’s entity type. The agent ID travels on every check and report under that key, which is how Governance finds the entity and its chain. The SDK rejects an agentId without an attributionKey, because a guessed key would silently attribute the spend to the customer instead. Naming an agent in a context attributes calls to it. It does not create it: that is what register() is for.
Governance counts agent and team usage in whole units. When a call is attributed to an agent and its usage draws a credit currency, the SDK rounds the amount up to the next whole credit and logs that it did. Define the credit currency in small enough units, such as thousandths of a dollar, that rounding a single call up costs little. Calls with no agent are reported with their exact fractional amount.

One client per agent

You can also wrap a separate client for each agent, with the agent as that client’s default:
Each call still passes its customerId. Do this when you want separate usage totals per agent in your own code: each wrapped client’s stigg.summary(), for example drafter.stigg.summary(), returns what that client has done so far, including how many checks and reports it made and the usage totals per metric. See the SDK reference.

Fine-grained attribution with dimensions

An agent usually works on behalf of someone, and may use more than one model. To track or limit usage by those as well, attribute each call to them too. For example, in the research team:
  • Per person: Alice can spend at most 5 credits a month through any of the team’s agents.
  • Per model: calls to an expensive model have a tighter budget than the team’s overall one.
Pass them in stiggContext.dimensions, next to the agent:
The call is then checked against Alice’s budget and the model’s budget as well, and its usage counts toward both. For this to work, users and models must be set up in Governance as entity types, and each key in dimensions must be that type’s attribution key, here userId and modelId. A key that matches no entity type is ignored. A per-model budget is a scoped budget. Dimensions set on a call are added to the ones set on the client.

When access is denied

If the agent, its team or the customer has no budget left, access is denied and the call is not sent to the provider. The wrapped call throws an AccessDeniedError, and stigg.denial(err) returns the decision, with hasAccess: false, just like an entitlement check. To find out before a call instead, use stigg.check(), which returns the decision without throwing. Use the decision to respond the right way:
For every field, see The decision object.

3. Deregister the agent (optional)

When an agent is no longer needed, archive its entity:
For long-lived agents this is optional. For ephemeral agents, created for a single task or session, deregister each one when it finishes, so finished agents do not pile up in the customer’s tree.

Observe-only rollout

Governance is opt-in: an agent with no budget is never denied access by Governance. To introduce agent budgets safely:
  1. Register agents with budget: { entitlement, limit: null }. Usage per agent and per team is tracked and visible in the Stigg app, and nothing is blocked.
  2. Review the numbers with your customers.
  3. Set real limits, per agent or per team, from your code or in the Stigg app.

Without Governance

Agent-level governance requires Governance to be enabled in your account. See Setting up governance. If it is not enabled, the SDK keeps working, but without agents or teams:
  • Calls are checked against the customer only. There are no agent or team budgets, so each call is checked against the customer’s own credits or usage limit, as with any wrapped client. When access is denied, deniedBy is the customer.
  • Usage is still metered for the customer, but not attributed to an agent.
  • register() with only the agent part logs a warning and does nothing.
  • register() with a budget throws GovernanceNotEnabledError, because there are no agent budgets to save them to.

Tool calls and workflow steps

To put an agent’s tool calls or workflow steps under the same budgets as its model calls, check and report them directly. See Gating actions that are not model calls.