Policy settings

Every setting of a team policy with type, default and allowed values, the five presets, and the authority table.

Every team has exactly one policy. It decides which repositories and paths kanman may touch, which executor and models it uses, how much it may spend, when a human must approve, and how much work runs in parallel. For the ideas behind it, read Policies, presets and authority levels.

You edit the policy in the app under Teams, your team, Settings. Team settings have twelve pages in four groups; the policy keys live on these:

Group Page Path Settings
How kanman works Autonomy /<workspace>/teams/<team>/settings/autonomy preset_id (the trust dial), the steps intake_scope, autonomy, plan_approval, plan_approval_min_size, rework_attempts, merge_policy, auto_merge_max_lines, the boundaries (autonomy.boundaries), under Small housekeeping authority_overrides, and the Responsible person (responsible_user_id)
How kanman works Limits and budgets .../settings/limits max_concurrency (Stories at the same time), budget_run_cents, budget_day_cents, budget_month_cents, or with the runner environment budget_run_minutes, budget_day_runs, budget_month_runs, under What I may change denied_paths, max_changed_files, max_changed_lines, secret_names, under Improve over time improve_over_time, and under Advanced gate_failure_budget and cadence.loopDoctorMinutes
How kanman works Hours and rhythm .../settings/hours working_hours, reachability, cadence.deliveryReview, cadence.retroWeekday
How kanman works Agent and models .../settings/agent routing, spec_author_model, executor, fallback_executor, billing_mode, ai_config_id, assistant_billing_mode, assistant_ai_config_id
Where work comes from Repositories and tracker .../settings/work allowed_repos
Quality and operations Checks and delivery .../settings/checks acceptance_spec_for, require_acceptance_spec, spec_notes, the team environment and the default check files
Quality and operations Maintenance and CI .../settings/maintenance maintenance, cadence.scannerDays

is_paused has no page: the pause button next to the team’s status line in the team header sets it (see is_paused). The other pages hold settings outside the policy: Chat and mentions (where kanman talks and what it posts there), Knowledge (sources kanman reads and the conventions it learned), Code review, Services and on-call and Team (name, key, look). Old links to the pages that were merged (Policy, Budgets, Executor, Claude Code, Approvals) still work and land on the new page and card. Every change saves at once, with a Saved tick and Undo.

billing_mode and ai_config_id are chosen when you set up the team. The keys on this page are the names kanman uses in the audit log and in the policy snapshot of every run.

Who can change it

Only workspace admins can change a policy; other members see the settings read-only. Every change increases the policy version by one and writes a policy_changed entry to the audit log with the changed values and the old and new version. Each run stores the policy it started with, so you can always see which rules applied to a run.

Scope

What kanman may touch.

allowed_repos

Type: array
Default: []
Allowed: {"provider": "github" or "gitlab", "repoFullName": "org/repo", "branches": ["main"]}

Repositories and base branches kanman may work on. Branch entries are globs; a repository without a branch list allows any base branch. An empty list allows no repository at all. Work in a repository that is not listed stops with a policy_exception decision.

The names of the branches kanman pushes are set next to the repositories, under Branch names (see Branch names).

denied_paths

Type: array of globs
Default: from the preset
Allowed: Glob patterns, for example infra/**

Paths the executor must not change. kanman checks them while the executor works (through check_policy) and again on the final diff. A change to a denied path stops the run with a policy_exception decision. .kanman/acceptance/** is always denied in addition and cannot be removed or allowed once.

max_changed_files

Type: integer
Default: 30
Allowed: 1 or more

Maximum number of files one change may touch. Larger changes fail the policy_diff gate.

max_changed_lines

Type: integer
Default: 800
Allowed: 1 or more

Maximum added plus deleted lines of one change.

secret_names

Type: array of strings
Default: []
Allowed: Variable names

Names of the workspace’s secrets for runs this team’s runs may use. Edited under Settings > Limits and budgets, What I may change, as chips; the app suggests the names of the workspace’s secrets. A run gets the listed secrets that exist in the workspace as environment variables of the executor and of the local verify command; names the workspace does not have are listed in the run. Names kanman uses itself, such as model provider keys or PATH, are refused.

spec_notes

Type: text or null Default: null Allowed: Up to 4000 characters

The team’s notes for the acceptance specs kanman writes. Edited under Settings > Checks and delivery as Notes for acceptance specs. kanman follows them in every spec it writes or rewrites for this team, for example: “never reload the page after picking the tenant; wait for ‘Select a tenant to continue’; the app is ready when the ‘Open search and commands’ button shows”. Clearing the text removes the notes. Changes apply to the next spec kanman writes; specs that are already approved stay as they are until they are written again.

acceptance_spec_for

Type: string Default: routine_and_complex Allowed: all, routine_and_complex, complex_only

Which stories get an acceptance spec. Edited under Settings > Checks and delivery as Which stories get an acceptance spec. Quick stories without one are proven by your build and tests, CI, kanman’s review of every criterion and before/after screenshots (light and dark mode); for the others the coding agent writes the acceptance test with the fix.

  • all (Every story): every story gets an acceptance spec, quick ones too.
  • routine_and_complex (Routine and complex stories): quick stories are proven without a new spec.
  • complex_only (Complex stories only): only complex stories get one.

Existing teams use the default. Changes apply to the next story that moves to Ready; a story with an approved spec keeps it. Every change is recorded in the audit log.

spec_author_model

Type: string Default: assistant Allowed: assistant, coding

Who writes the team’s acceptance specs. Edited under Settings > Agent and models, in the spec writer fold of Which model works on what.

  • assistant: kanman’s assistant model, the same model access as drafting stories, the conversation and the reviewer (see Budgets). Cheaper and quicker, but it knows your test setup less well and may guess how to find elements on a page.
  • coding: the model access of the team’s coding agent, with the team’s mid tier model (for Claude Code: Sonnet, unless you set another model for the mid tier under Settings > Agent and models). With a self-hosted runner this is the runner’s coding access. It knows test frameworks better, so its specs fail less often for the wrong reason; each spec costs a call to that model.

Changes apply to the next spec kanman writes or rewrites. Specs you provide yourself are never written by a model. Teams on a self-hosted runner need a current runner version for coding; older runners keep using the assistant model.

Executor and routing

Which coding agent and models do the work.

executor

Type: string
Default: claude-code
Allowed: claude-code, codex

The coding agent that implements stories. Shown as Claude Code or Codex under Settings > Agent and models, Coding agent.

fallback_executor

Type: string or null
Default: null
Allowed: claude-code, codex

The executor that takes over when the main executor itself fails. If an attempt ends because the coding agent crashed or its model provider returned an error (not because a check failed, a budget or turn limit was reached, or a policy stopped it), kanman retries that attempt once with the fallback executor and its model for the story. The switch is noted in the run and recorded in the audit log as a policy decision. It happens only when the fallback can use the team’s model access: with your own key, Claude Code needs an Anthropic or Amazon Bedrock key and Codex an OpenAI or Azure OpenAI key.

routing

Type: object
Default: see below

Model tier, turn budget and ceremony per complexity class, plus the reviewer settings.

Default value:

{
  "trivial":  { "modelTier": "small",    "turnBudget": 100, "ceremony": "none" },
  "routine":  { "modelTier": "mid",      "turnBudget": 120, "ceremony": "plan_self_review" },
  "complex":  { "modelTier": "flagship", "turnBudget": 200, "ceremony": "approaches_then_plan" },
  "reviewer": { "vendor": "different_from_executor", "modelTier": "mid" },
  "modelOverrides": {}
}
Ceremony What happens before code is written
none The executor starts directly.
plan_self_review A short plan, then a self-review of the change before submitting.
approaches_then_plan Several scored approaches, then a plan based on the best one.

Default models per tier:

Tier Claude Code Codex
small haiku gpt-5-mini
mid sonnet gpt-5
flagship opus gpt-5

The Claude Code names always point to the current model of that family. modelOverrides pins a model by complexity class (for example "routine"), by tier (for example "mid") or for the "reviewer"; a class entry wins over a tier entry. With "vendor": "different_from_executor" the reviewer uses the other vendor’s model of its tier, so code written by Claude Code is reviewed by a Codex model and the other way round.

In the app you change the model and the effort limit (1 to 1000 steps) per story size under Settings > Agent and models, Which model works on what. Changes apply to the next attempt, including retries and the automatic rework of stories that are already running. Teams created before 3 October 2026 keep the trivial budget of 60 steps they started with; raise it here if quick stories run out of steps.

billing_mode

Type: string
Default: pass_through
Allowed: byok, pass_through, runner_env

How the executor reaches its model and who pays the provider: your own contract through a key saved in kanman (byok), kanman, billed at cost plus 15 percent (pass_through), or the model access of your self-hosted runner (runner_env, shown as Model access from the runner environment). With runner_env, kanman passes no model credentials to the run at all; it is offered only for workspaces whose runs execute on their own runners. kanman cannot see model cost in this mode, so the run and team budgets count minutes and runs instead of euros. Chosen in the team setup and under Settings > Agent and models.

ai_config_id

Type: reference or null
Default: null
Allowed: The key saved under Workspace settings > Model access

The provider key used with byok. Claude Code works with an Anthropic or Amazon Bedrock key, Codex with an OpenAI or Azure OpenAI key. With an AI gateway key, Claude Code needs the gateway’s Anthropic-compatible endpoint and Codex its OpenAI Responses API. A run with a missing, inactive or unsuitable key fails with a clear error instead of falling back to pass-through.

assistant_billing_mode

Type: string or null Default: null (same as billing_mode) Allowed: null, byok, pass_through, runner_env

How kanman’s assistant steps reach their model: drafting stories, replies in the conversation, the reviewer and the spec author. null (shown as Same as the coding agent) uses the coding agent’s billing_mode and key. Another value gives them their own model access, for example your company’s AI gateway key while the coding agent uses the runner environment. runner_env is offered only for workspaces whose runs execute on their own runners. Set under Settings > Agent and models as the assistant’s model access.

assistant_ai_config_id

Type: reference or null Default: null Allowed: The key saved under Workspace settings > Model access

The provider key of the assistant steps when assistant_billing_mode is byok. Cleared automatically for every other value.

Budgets

All amounts are in euro cents. Budgets are hard stops. Set under Settings > Limits and budgets, where meters show what was spent this month and today (or, with the runner environment, the runner’s limits in minutes and runs). Work with the class of service expedite and incident work is never stopped by budgets.

budget_run_cents

Type: integer
Default: 200 (2.00 EUR)
Allowed: 1 or more

Maximum cost of one run, across all attempts. When it is reached the run stops with Stopped: budget reached, no pull request is created, and a budget_stop decision offers to double the run budget.

budget_day_cents

Type: integer or null
Default: null (no limit)
Allowed: 1 or more

Maximum spend of the team per day, in the time zone of working_hours (UTC if none). When it is used up, no new run starts until the next day.

budget_month_cents

Type: integer or null
Default: null (no limit)
Allowed: 1 or more

Maximum spend of the team per calendar month, in the same time zone. When it is used up, no new run starts until the next month.

improve_over_time

Type: object {"enabled": boolean, "share": number, "capCents": integer or null}
Default: {} (on, 5 % of the model spend of the last 30 days)
Allowed: share 0.01 to 0.25, capCents 0 or more (a fixed monthly limit instead of the share)

Improve over time: kanman re-runs the team’s merged stories on the team’s own model access to find changes that make it better at the team’s work. "enabled": false switches it off. The cost counts toward the team’s spend; re-runs never use the last tenth of budget_month_cents.

budget_run_minutes

Type: integer Default: 60 Allowed: 1 to 1440

Only with billing_mode runner_env: maximum time of one attempt in minutes. When it is reached the run stops with Stopped: the run used its 60 minutes (with your value), and no pull request is created. Euro budgets do not apply in this mode.

budget_day_runs

Type: integer or null Default: null (no limit) Allowed: 1 or more

Only with runner_env: number of runs the team may start per day, in the time zone of working_hours. When it is reached, no new run starts until the next day. Expedite and incident work still starts.

budget_month_runs

Type: integer or null Default: null (no limit) Allowed: 1 or more

Only with runner_env: number of runs the team may start per calendar month.

Approvals

When a human has to say yes. Edited in the Plan and Merge steps of Settings > Autonomy (old links to Approvals lead there).

plan_approval

Type: string
Default: always
Allowed: always, by_size, never

When a human must approve the plan before code is written. The run plans read-only first, and the plan arrives as a plan_approval decision.

plan_approval_min_size

Type: string or null
Default: null
Allowed: S, M, L

With by_size: stories of this size or larger need approval. Without a value, or for a story without a size, every plan needs approval.

merge_policy

Type: string
Default: human
Allowed: human, auto_if_small

Who merges. With human the story stays in Review with a mergeable pull request until a person merges it. auto_if_small merges automatically when every gate passed and the change is no larger than auto_merge_max_lines; larger changes raise a merge_approval decision. While your main branch is red, kanman holds automatic merges.

In autonomous mode kanman also merges work that passed every gate itself, whatever this setting says, unless it crosses one of the team’s boundaries; see autonomy. This includes high-risk changes (migrations, security, payment, infrastructure and CI files) whose kind of work the team does not keep as a boundary; a change to a CI file merges only after kanman checked that no job, test or rule was removed or weakened.

auto_merge_max_lines

Type: integer or null
Default: null
Allowed: 1 or more

With auto_if_small: the largest change, in lines, that may be merged automatically.

autonomy

Type: object or null Default: null (follows the preset: on for Autonomous, off for every other preset) Allowed: {"selfApprove": true|false, "mergeLowRisk": true|false}

What kanman does on its own, edited in the Intake, Plan and Merge steps and under Always comes to you of Settings > Autonomy. selfApprove: kanman approves its own low-risk stories into Ready up to the free run slots and the runners’ capacity, and starts them without a plan approval. selfReview (absent: follows selfApprove): kanman reviews every other plan itself and approves it when its confidence reaches minConfidence (0.5 to 0.99, absent: 0.8), has it rewritten at most twice otherwise, and asks a person one specific question when it needs input; it also retries failed checks and acceptance specs with its own guidance (twice per run) and continues rollouts. mergeLowRisk: kanman merges low-risk work when CI is green and every gate passed, and with selfReview every story that passed every gate, plus the green merge requests of rollouts. boundaries: the kinds of work that always come to a person (data_migrations, payments, deletions, security, infrastructure, dependencies_major; absent: the first four). Low risk means a maintenance update with a repeatable fix, or an assessed story of size S or M without concerns, risk notes or overlaps. See Autonomous mode and the team heartbeat.

authority_overrides

Type: object
Default: {}
Allowed: {"<kind>": "NOTIFY"} or "ESCALATE"

Raises the authority level of individual decision kinds. See the authority table. In the app this is Small housekeeping under Settings > Autonomy, with the levels On my own, Tell me and Ask me first.

responsible_user_id

Type: user id or null
Default: the person who set up the team’s policy (teams set up before October 2026: nobody)
Allowed: a member of the workspace who has joined, or null

The person who answers for how much kanman does on its own in this team. In the app this is Responsible person at the end of Settings > Autonomy; workspace admins choose it, everyone else sees the name. Every change of the team’s policy is recorded in the audit log together with the person who made it and the person responsible at that moment, so the question “who allowed this to run without approval?” is answered by one entry.

Working hours and concurrency

When and how much kanman works.

working_hours

Type: object or null
Default: null (always)
Allowed: {"tz", "days", "start", "end"}

When new runs may start, for example {"tz": "Europe/Berlin", "days": [1,2,3,4,5], "start": "08:00", "end": "19:00"}. Days are 1 (Monday) to 7 (Sunday). Runs in progress finish. Expedite stories and incidents start outside working hours too.

max_concurrency

Type: integer
Default: 1
Allowed: 1 to 20

How many runs of this team may be active at the same time, set as Stories at the same time under Settings > Limits and budgets; its meter shows which cap applies (team, plan or workspace). The effective value is capped by the team’s plan: Starter 2, Team 5 (also during the 14-day trial), Enterprise up to 20. On Local, no runs start in the cloud. Stories wait in Ready until a slot is free.

is_paused

Type: boolean
Default: false
Allowed: true, false

A paused team starts no new runs; runs in progress finish. Pause and resume with the pause button next to the team’s status line in the team header (Paused ยท Resume while paused); it takes effect at once and offers Undo. You can also ask kanman in the conversation, for example “pause Sandbox Team”, and confirm the change. While the team is paused, Settings > Hours and rhythm says since when.

reachability

Type: object or null
Default: null (the defaults below)
Allowed: {"responseHours": {"mentions", "reviews"}, "outsideHours", "dailyUpdate": {"enabled", "at", "where"}}

How reachable kanman is for the team, set under Reachability in Settings > Hours and rhythm:

Key Default Meaning
responseHours.mentions 4 First answer to a mention, in working hours (1 to 72)
responseHours.reviews 8 First review of a requested pull or merge request, in working hours (1 to 72)
outsideHours "hold" hold: outside working_hours, pull and merge requests open as drafts and are marked ready when the hours start; reviews and Slack posts wait for the hours; no unprompted messages in Slack or Teams. anytime: no holding. Expedite stories and incidents are never held.
dailyUpdate.enabled false A short daily update on working days, only when there is something to say
dailyUpdate.at "09:00" Local time in the time zone of working_hours (UTC if none)
dailyUpdate.where "chat" chat (the team chat) or slack (the team’s Slack channel)

See Working hours and reachability.

Gates

How strict the outcome gate is. The gate itself, the diff guard and the clean-room run cannot be switched off.

require_acceptance_spec

Type: boolean
Default: true
Allowed: true; false only with the Trial preset

Whether a story needs a red acceptance spec before it can reach Ready. With false, kanman falls back to CI, the test plan and the reviewer run, and the evidence pack says that no outcome proof exists. Setting false with any other preset is rejected with Only the Trial preset can work without acceptance specs. In the app this is the Off choice of Which stories get an acceptance spec under Settings > Checks and delivery, offered only on the Trial preset.

rework_attempts

Type: integer
Default: 1
Allowed: 0, 1

Automatic rework attempts after a failed verification, with the gate output and the reviewer’s findings as input. With 0, a failed verification goes straight to the decision inbox.

gate_failure_budget

Type: integer
Default: 3
Allowed: 1 to 10

How many failures of the same gate a story may collect, across all its runs and attempts, before kanman parks the run and asks with a Repeated gate failure decision. Failures of the test environment itself do not count. Set under Settings > Limits and budgets, Advanced.

Personality knobs

These are the settings presets change, together with max_concurrency and the default denied_paths.

preset_id

Type: string
Default: trial
Allowed: trial, focused, balanced, autonomous, hardening

The preset the policy is based on. See Presets. The team setup suggests Balanced.

is_custom

Type: boolean
Default: false
Allowed: read only

true once a preset knob differs from the preset. The app then shows “Balanced, adjusted” on the trust dial. Maintenance and the cadence keys deliveryReview, retroWeekday and scannerDays never count.

intake_scope

Type: string
Default: humans_and_kanman
Allowed: humans_only, humans_and_kanman

Who may file the stories kanman works on.

  • humans_only: kanman only works on stories people filed. kanman never files a story itself: with maintenance on, every finding waits as a proposal in Decisions, and only a person accepting it files the story.
  • humans_and_kanman: kanman may also file stories itself. With maintenance on, findings of the allowed kinds (allowedKinds) are filed as maintenance stories without asking; all other findings still wait as proposals.

Stories from intake are always approved by a person before they are written to the tracker, whatever this setting says.

maintenance

Type: object
Default: {"enabled": false, "dripPerDay": 0, "maxPerRun": 1, "allowedKinds": []}

Maintenance mode: on or off, how many maintenance stories and proposals may be filed and started per day, how many routine findings one scan may file at most (maxPerRun), how many new stories and proposals one scan may create in total, security included (newStoriesPerScan, 5 when not set), which kinds become stories without asking, and optionally the shared template repository (templateRepo) that group stories name. Edit it under Settings > Maintenance and CI: Pace (Gentle, Steady, Fast) sets dripPerDay, maxPerRun, newStoriesPerScan and cadence.scannerDays together, Filed without asking sets allowedKinds, and Advanced holds your own numbers and templateRepo. Presets keep it as it is; only Hardening switches it on, with its defaults, for a team that has it off.

cadence

Type: object
Default: {"reportWeekday": 1, "loopDoctorMinutes": 15, "scannerDays": 7}

Weekday of the team report (1 = Monday), how often the health check looks at the team’s runs, and how often maintenance scanners run for the team, plus the team’s rituals: the delivery review after the weekly report (deliveryReview) and the day of the retrospective prompt (retroWeekday, 0 = off). The health check currently runs every 15 minutes for every team. A preset keeps deliveryReview, retroWeekday and scannerDays.

Presets

Presets only change the personality knobs and the default denied paths. Safety settings (sandbox, diff guard, clean-room run, always-denied paths) are the same for every preset.

Preset max_concurrency intake_scope Maintenance require_acceptance_spec Default denied_paths
Trial 1 humans_only kept false infra/**, **/*.tf, .github/workflows/**
Focused 1 humans_only kept true infra/**, **/*.tf, .github/workflows/**
Balanced 2 humans_and_kanman kept true infra/**, **/*.tf, .github/workflows/**
Autonomous 4 humans_and_kanman kept true .github/workflows/**
Hardening 2 humans_and_kanman on (2 per day, at most 1 per scan) when it was off true infra/**, **/*.tf, .github/workflows/**

Autonomous also sets autonomy so kanman approves low-risk work, reviews its own plans and decisions and merges what passed every gate, within the default boundaries; every other preset switches it off. Hardening allows the maintenance kinds cve, outdated_dep, unused_dep, lockfile_drift and broken_doc_link. All presets set cadence.reportWeekday to 1 and cadence.loopDoctorMinutes to 15 and keep the team’s other cadence keys.

Pick a preset with the trust dial under Settings > Autonomy. The dial first shows what changes; Apply stores it and Undo brings the old values back. Budgets, plan approval, merging, rework, working hours, rituals, routing, maintenance and authority overrides are not part of a preset and stay as they are.

Authority table

Every decision kanman takes has a kind, and the kind has a base authority level. The table is fixed code, not a prompt.

Level Meaning Decision kinds
AUTO Act silently, visible in the audit log write_ac, set_priority_in_band, link_duplicate, resequence, nudge_run
NOTIFY Act and record a notice close_duplicate, split_story, pause_thrashing_run
ESCALATE Stop and ask in the decision inbox, with a recommendation and 2 to 4 options expand_scope, change_security_posture, touch_production_data, overspend, contradict_operator, touch_denied_path, plan_approval, merge

Rules:

  • Unknown kinds default to NOTIFY.
  • Risk only raises the level: an irreversible action, a high blast radius or a cost of 20.00 EUR or more makes it ESCALATE; a medium blast radius or a cost of 5.00 EUR or more makes it at least NOTIFY.
  • authority_overrides can only raise a kind, never lower it.
  • touch_production_data, change_security_posture and overspend are always ESCALATE (safety floor).
  • plan_approval and merge take their base level from the approval settings (plan_approval, merge_policy); an override can only make them stricter.

Example: always ask before kanman links duplicates:

{
  "authority_overrides": {
    "link_duplicate": "ESCALATE"
  }
}

An override that would lower a level (for example "merge": "NOTIFY" while a person merges) has no effect: the stricter level always wins. Values other than NOTIFY and ESCALATE are ignored.

Full example

{
  "preset_id": "balanced",
  "is_custom": true,
  "version": 7,
  "allowed_repos": [
    { "provider": "github", "repoFullName": "acme/billing", "branches": ["main"] }
  ],
  "denied_paths": ["infra/**", "**/*.tf", ".github/workflows/**", "migrations/**"],
  "max_changed_files": 30,
  "max_changed_lines": 800,
  "executor": "claude-code",
  "fallback_executor": null,
  "billing_mode": "pass_through",
  "ai_config_id": null,
  "budget_run_cents": 300,
  "budget_day_cents": 3000,
  "budget_month_cents": 40000,
  "budget_run_minutes": 60,
  "budget_day_runs": null,
  "budget_month_runs": null,
  "plan_approval": "by_size",
  "plan_approval_min_size": "M",
  "merge_policy": "human",
  "auto_merge_max_lines": null,
  "authority_overrides": {},
  "working_hours": { "tz": "Europe/Berlin", "days": [1, 2, 3, 4, 5], "start": "08:00", "end": "19:00" },
  "max_concurrency": 2,
  "secret_names": [],
  "require_acceptance_spec": true,
  "rework_attempts": 1,
  "gate_failure_budget": 3,
  "intake_scope": "humans_and_kanman",
  "maintenance": { "enabled": false, "dripPerDay": 0, "maxPerRun": 1, "allowedKinds": [] },
  "cadence": { "reportWeekday": 1, "loopDoctorMinutes": 15, "scannerDays": 7 },
  "is_paused": false
}

Last updated: January 1, 0001

Open kanman