Admission — what the Control Plane does before a task reaches a daemon
ee/planner used to turn a task into a DAG of worker specs. It no longer does. What remains on the Control Plane is everything except planning: admission control, org limits, idempotency, fleet routing, model policy, and the Job/QueuedTask transaction. The component kept its name because it occupies the same seam in the code, but almost nothing is left of the job it used to do.
Why decomposition was removed
Decomposition existed to divide a task into file-sized pieces small enough for a single-turn Actor to rewrite whole — and it had to guess those files from a repository URL, since the Control Plane has never seen the file contents. That guess is what the session loop exists to stop relying on: an Implementer that can grep the actual repository needs no file list handed to it in advance.
Removing it also closes a real containment gap. Decomposition ran on the Control Plane, which meant a frontier-model call at submit time — and in BYOC, that call needed the org's decrypted provider key, so planning on the Control Plane meant Kiwi's own network making a provider call with a customer credential. In the current design the Architect is the planner, and it runs in the daemon, where the key already has to be. Removing decomposition removed that call and that read in the same change.
What admission still does
You submit a PlanRequest — a task description, a repo URL and ref, the model, and an optional test command. Service.SubmitPlan runs the checks that decide whether the task may run at all:
- Idempotency — a repeated
Idempotency-Keyheader dedupes retried submissions to the same job. - Org limits — concurrency, budget, and (Free tier) agent-minute caps, checked before anything is enqueued.
- Model policy and funding — the model id resolves to a provider through the same routing rule the daemon uses, and the Control Plane checks that a key exists for it without decrypting it — a presence check, not a read. This is skipped for a Kiwi-provided model, since demanding the org connect their own key would refuse the exact case that feature exists to serve.
- Fleet routing — which fleet (shared managed, dedicated managed, or BYOC) the task belongs to.
Once admitted, the task is written as a Job and exactly one QueuedTask in a single transaction — there is no DAG to construct, so there is nothing to roll back partially.
The one-worker plan
SessionPlanner.Plan produces a fixed, single-worker plan with no LLM call:
// ee/planner/session.go
worker := PlannedWorker{
ID: "session",
Task: req.Task,
Model: req.Model,
ArchitectModel: req.ArchitectModel,
}
File and Files are deliberately left empty even when the submitter supplied them. A hint the Control Plane cannot check against the real repository is exactly what the session loop exists to stop relying on — carrying one here would reintroduce the old guess under a different name, and a near-miss would send the Implementer to the wrong place with an air of authority it hasn't earned.
If your org has shared context enabled, prior-job learnings are still resolved here (the Control Plane owns the vector index) and ride along on the plan to reach the Architect — computed once at admission time rather than recomputed, and paid for, inside the daemon.
What a task carries to the daemon
| Field | Meaning |
|---|---|
id | <job_id>-session — the queued task id |
task | your task description |
model | the Implementer's model (runs on the customer's key) |
architect_model | the Architect's model, if you set one — defaults to the platform default |
test_cmd | the guard command — it must still pass after the change |
repo_url / ref | where to get the code |
job_id | links the task back to its job |
If no test command is given, the daemon infers one from the repository at execution time — submitting a prompt and nothing else is the product, so a missing test command is not a reason to refuse the work at admission.
mode is accepted and ignored
The API, the CLI (kiwi submit -mode), and the SDKs still accept a mode field, so nothing written against the old two-mode API breaks. It does nothing: session is the only execution loop, and there is no "simple mode" to opt into or out of.
Next: Agentic sessions — what the Architect and Implementer actually do with the task once a daemon leases it.