Skip to content

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.

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.

The rule: what the policy permits or does travels; what names a machine does not.

In the bundle
Policy settingsYes. Imported as a new policy.
Tool overlay: disabled tools, surfaces, descriptions, chains, step limitYes, inside the settings.
FlowsYes, as content.
Inference target, client target, tool peer, sandbox peerNo. Stripped on export; the import wizard asks where to run.
Container imageReference and pull hints only. The image must be pullable on the target.
Base model, adaptersName, variant and source URL only. They must be installed or fetchable.
Playbooks, extraction rulesKeys 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.

A policy is { id, title, description, ai }. Everything of substance is in ai.

FieldMeaning
useKabaTarget, clientTargetWhere inference runs: a peer ID, or null for this device.
toolPeer, sandboxPeerWhere commands and containers run.
baseModel, clientBaseModel"e2b", "e4b" or "model:<imported name>".
lora, remoteLora, clientLora, clientRemoteLoraAdapter names.
temperature, maxTokens, maxContext, turbo, repetitionPenaltyGeneration. maxContext: 0 means automatic.
containerImage reference. Empty means the default.
execAllowedfalse denies execution tools outright.
deniedTools, clientDeniedTools, maxToolStepsCeilings. Deny wins.
toolOverlaySee below.
flowsInline flows. See below.
steerControlRecovery settings for the coding loop.
  1. Start from the full catalog.
  2. Apply overlays in ascending authority; later wins per key.
  3. Apply the policy ceiling last. Nothing below can re-enable what it removes, and maxToolSteps clamps any overlay’s step limit.

For each absent tool the result records why, such as policy: denied.

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"] } ]
}
KeyEffect
disabledTools removed on every surface.
surfacesTools removed on one surface: projects, toast, menu or client.
descriptionsReplace the text the model sees for a tool.
maxStepsStep limit, never above the policy’s.
dropRulesRemove tools when a condition holds.
chainsOrder: 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.

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."
}]
}
PredicateTrue 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.

  • Name tools in requires_tools that must really exist. The flow stays inert under a policy that disabled them.
  • Make done_when checkable from the address, page text or tool history. Never from what the model says.
  • Keep each phase’s tools list short.
SourceAuthorityIn a .kabap
Bundled with the applowestNo
On disk, per policy: <user data>/kaba-resources/flows/<policy>.<id>.jsonmiddleYes
Inline in ai.flowshighestYes

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.

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.

KeyDefault
candidateBufferon
bestOfNon; k: 4, temperature: 0.7, maxBytes: 8192
tabuon
stateViewon; historyWindow: 12, freshWindow: 2
stuckPolicyon; ladder: ["resample", "fresh", "best-of-n", "halt"]
impacton; maxLines: 8
fixMemoryon; maxEntries: 200
plainTextCodeon
derivedSeedson
localizeon

What each does is described under projects & tool loop.

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.

~/.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.