File Formats
A policy is data. This page describes its shape, the overlay that restricts tools, the flows that sequence a task, and the .kabap bundle that carries all three between machines.
.kabap
Section titled “.kabap”A .kabap file is a ZIP archive, stored uncompressed, containing a single entry: policy.kabap.json. The current format version is 1. Readers reject a compressed manifest or a newer version.
{ "kabap_version": 1, "exported_at": "2026-08-07T19:14:22.031Z", "policy": { "title": "…", "description": "", "ai": { /* policy settings, without machine placement */ } }, "resources": { // optional "extraction_rules": ["amazon.com"], // keys; the importer re-fetches "playbooks": ["proton.me"], // keys "flows": [ { "id": "…", "phases": [ /* … */ ] } ] // content }, "assets": { "container": { "reference": "docker.io/library/rust:1-bookworm" }, "base_model": { "kind": "stock", "variant": "e4b" }, "client_model": { "kind": "imported", "name": "my-model" }, "adapters": [ { "name": "my-lora", "source": { "url": "…" } } ] }}kind is stock, imported or default.
What travels and what does not
Section titled “What travels and what does not”The rule: what the policy permits or does travels; what names a machine does not.
| In the bundle | |
|---|---|
| Policy settings | Yes. Imported as a new policy. |
| Tool overlay: disabled tools, surfaces, descriptions, chains, step limit | Yes, inside the settings. |
| Flows | Yes, as content. |
| Inference target, client target, tool peer, sandbox peer | No. Stripped on export; the import wizard asks where to run. |
| Container image | Reference and pull hints only. The image must be pullable on the target. |
| Base model, adapters | Name, variant and source URL only. They must be installed or fetchable. |
| Playbooks, extraction rules | Keys only. |
So a bundle carries what the policy permits, how it thinks and the sequence it follows. The importer supplies where it runs.
Export from Settings → Policies; import with Import policy.
Policy
Section titled “Policy”A policy is { id, title, description, ai }. Everything of substance is in ai.
| Field | Meaning |
|---|---|
useKabaTarget, clientTarget | Where inference runs: a peer ID, or null for this device. |
toolPeer, sandboxPeer | Where commands and containers run. |
baseModel, clientBaseModel | "e2b", "e4b" or "model:<imported name>". |
lora, remoteLora, clientLora, clientRemoteLora | Adapter names. |
temperature, maxTokens, maxContext, turbo, repetitionPenalty | Generation. maxContext: 0 means automatic. |
container | Image reference. Empty means the default. |
execAllowed | false denies execution tools outright. |
deniedTools, clientDeniedTools, maxToolSteps | Ceilings. Deny wins. |
toolOverlay | See below. |
flows | Inline flows. See below. |
steerControl | Recovery settings for the coding loop. |
How the tool set is resolved
Section titled “How the tool set is resolved”- Start from the full catalog.
- Apply overlays in ascending authority; later wins per key.
- Apply the policy ceiling last. Nothing below can re-enable what it removes, and
maxToolStepsclamps any overlay’s step limit.
For each absent tool the result records why, such as policy: denied.
Tool overlay
Section titled “Tool overlay”ai.toolOverlay is the only place overlays live. Toolbench edits it.
{ "disabled": ["run_host_command"], // removed everywhere "surfaces": { "toast": ["simulate"] }, // removed on one surface "descriptions": { "collect": "Record a product you can SEE…" }, "maxSteps": 32, // clamped by ai.maxToolSteps "dropRules": [ { "when": "no-attachments", "drop": ["read_file"] } ], "chains": [ { "tool": "collect", "after": ["extract_products", "inspect_page"] } ]}| Key | Effect |
|---|---|
disabled | Tools removed on every surface. |
surfaces | Tools removed on one surface: projects, toast, menu or client. |
descriptions | Replace the text the model sees for a tool. |
maxSteps | Step limit, never above the policy’s. |
dropRules | Remove tools when a condition holds. |
chains | Order: tool may run only after one of after has run in the same run. The tool stays visible; running it early returns a correction. |
An overlay cannot add a tool. The catalog is code. Overlays only subtract, re-describe, scope and order.
Flows and phases
Section titled “Flows and phases”A flow is a list of phases. A phase is a goal: the tools on the menu, a condition for being done, a hint, and a step ceiling.
{ "id": "shop", "title": "Shop, compare, add to cart", "match": { // both must hold to engage "task_matches": "\\b(shop|buy|cheapest)\\b", "requires_tools": ["extract_products", "rank_candidates"] }, "phases": [{ "id": "open", "goal": "Land on the retailer's search-results page", "tools": ["open_pane", "navigate", "search_web"], "hint": "Land on the retailer's SEARCH RESULTS URL.", "done_when": { "any": [ { "url_matches": "[?&](k|q|query)=" }, { "url_has": "/search" } ] }, "max_steps": 5, "stuck_hint": "Go straight to the retailer's search URL." }]}done_when
Section titled “done_when”| Predicate | True when |
|---|---|
{ "any": [ … ] }, { "all": [ … ] } | One child, or every child, is true. |
{ "url_has": "/cart" } | The address contains the text, ignoring case. |
{ "url_matches": "regex" } | The address matches. |
{ "text_has": "added to" } | The page text contains it. |
{ "candidates_at_least": 3 } | At least that many candidates were collected. |
{ "ranked": true } | A ranking has been produced. |
{ "tool_ran": "collect" } | That tool ran in this flow. |
Predicates have three values: true, false, and not yet knowable, for example text_has before any page has loaded. Not-yet-knowable neither unlocks nor fails a phase.
Two safeguards: an empty or missing done_when counts as satisfied, so a phase can never trap a run; and exceeding max_steps swaps hint for stuck_hint once, rather than halting.
Writing a good flow
Section titled “Writing a good flow”- Name tools in
requires_toolsthat must really exist. The flow stays inert under a policy that disabled them. - Make
done_whencheckable from the address, page text or tool history. Never from what the model says. - Keep each phase’s
toolslist short.
Where flows come from
Section titled “Where flows come from”| Source | Authority | In a .kabap |
|---|---|---|
| Bundled with the app | lowest | No |
On disk, per policy: <user data>/kaba-resources/flows/<policy>.<id>.json | middle | Yes |
Inline in ai.flows | highest | Yes |
Flows merge by id: a policy’s flow named shop replaces the bundled shop. An inline flow makes a policy self-contained. A malformed inline flow is ignored, not fatal.
Steer control
Section titled “Steer control”ai.steerControl tunes recovery in the coding loop. Everything is on by default. false turns a feature off; an object tunes it. Unknown keys are ignored and numbers are clamped, so a malformed policy cannot disable steering by accident.
| Key | Default |
|---|---|
candidateBuffer | on |
bestOfN | on; k: 4, temperature: 0.7, maxBytes: 8192 |
tabu | on |
stateView | on; historyWindow: 12, freshWindow: 2 |
stuckPolicy | on; ladder: ["resample", "fresh", "best-of-n", "halt"] |
impact | on; maxLines: 8 |
fixMemory | on; maxEntries: 200 |
plainTextCode | on |
derivedSeeds | on |
localize | on |
What each does is described under projects & tool loop.
Adapters
Section titled “Adapters”A trained adapter is two files in <storage>/kaba-engine/loras/: <name>.mpk (weights) and <name>.json (manifest). Imported adapters are converted on import, and the original download is kept beside them.
Shell integration
Section titled “Shell integration”~/.config/kaba/shell-integration.sh is sourced from your shell’s rc file when shell integration is on. It emits standard command marks (OSC 133) so the terminal knows where commands begin and end.