Policies in policies/<name>.yaml set rules the factory cannot change on its own, and budgets in factory.yaml cap what each work item may spend.
A policy file
# policies/guard.yaml
description: Keep the factory from weakening its own checks
protectedPaths: [policies/**, gates/**, decisions/command-guard.yaml]
twoApprovalPaths: [agents/review/**]A factory can have several policy files. Kiln combines the lists from all of them.
| Key | Enforced today | What it does |
|---|---|---|
protectedPaths |
Yes | Self-improvement drops any proposed change to a matching path and lists it in the proposal. |
twoApprovalPaths |
Yes | A self-improvement proposal that changes a matching path needs approvals from two different people before Kiln applies it. |
deniedActions |
Not yet | Accepted by the schema. |
allowedTriggerers |
Not yet | Accepted by the schema. |
maxUsdPerWorkItem |
Yes | A spending cap per work item. See Budgets. |
description |
Not applicable |
Patterns are paths relative to the definition root. * matches within one directory level and ** matches across levels.
Self-improvement never changes files under policies/ or gates/, whether or not a policy lists them.
Rules that do not need a policy
Some limits are built into Kiln and cannot be turned off:
- A run token can push only
kiln/*branches of the factory's repositories, open pull requests, comment and add labels. It cannot approve or merge, and it expires after 60 minutes. - Kiln pushes the agent's branch itself. The agent is told not to push, open pull requests or merge.
- A work item can only become
completeafter a merge event or a person's confirmation. - Agents cannot approve self-improvement proposals.
Budgets
# factory.yaml
budgets:
perWorkItemUsd: 40
monthlyUsd: 6000| Key | Enforced today | What it does |
|---|---|---|
perWorkItemUsd |
Yes | The default budget of each new work item. |
monthlyUsd |
Yes | The most the factory may spend on runs in a calendar month. |
Before each agent run, Kiln checks two limits:
- Per work item. The cap is the lowest of the work item's budget and every policy's
maxUsdPerWorkItem. A work item's budget isperWorkItemUsd, unless the work item was created through the API with its own budget, which replaces it. When the item's spend has reached the cap, it stops asblockedwith the reason "budget of $40 reached ($41.20 spent)". - Per month. Kiln adds up the cost of all the factory's runs since the 1st of the month (UTC). When that has reached
monthlyUsd, the item stops asblockedwith the reason "monthly budget of $6000 for webapp reached ($6012.40 spent)".
A pipeline's budget.maxUsd is accepted but not enforced yet.
Cost comes from each run's harness. Claude Code and OpenCode report cost directly. Codex reports tokens, and Kiln estimates the cost from them.
Kiln also checks while a run goes. Each time the harness reports cost, Kiln saves it on the run and checks the same limits again, plus the team's spend limit. The work item check counts the item's finished runs and its runs still going. When a limit is reached, Kiln stops the agent and the run ends as failed with budget_exceeded. Cost the harness reported stays on the run, even when the run fails afterwards.
Codex and OpenCode report cost after each turn, so Kiln can stop them during a run. Claude Code reports cost when its session ends, so a Claude Code run can still take spend past a budget.
Who may decide
Who may approve a gate is set by the gate's approvers (see Pipelines and gates) and by the scopes on the person's token (see Admin, RBAC and audit).
Both must hold. A person needs the gate's decide:* scope on the factory, and must be one of the gate's assignees, on every surface: web, API, CLI, MCP, Slack, Discord and Teams. A gate without assignees can be decided by anyone with the scope. A token with admin on the factory may decide any of its gates. Anyone else gets HTTP 403, and a message from them in the task's thread joins the conversation instead of answering an open question.