Appearance
Why Agents Need a Control Plane
An agent that provisions infrastructure by emitting shell commands is operating open-loop: every docker run, helm install, or aws cli call is a one-way bet that something else will notice if it goes wrong. Three failure modes dominate:
- Non-reproducibility. Two runs of the "same" instruction produce different states depending on what already exists on the machine.
- No drift semantics. When reality diverges from intent, there is no definition of intent to diverge from — so recovery is guesswork.
- Blast radius. A hallucinated flag or a mis-scoped credential acts directly on the substrate, with nothing between the model output and production.
Nanokit's premise is different: the agent decides what to do; Nanokit guarantees that what the agent decides gets done — deterministically, securely, and reproducibly.
The division of labor
| Concern | Owner | Mechanism |
|---|---|---|
| Intent | Agent (or human) | Edits nanokit.yml |
| Planning | Nanokit | Diff desired vs. current state → typed plan |
| Execution | Nanokit | Ordered, dependency-aware apply with health gates |
| Verification | Both | Machine-readable state after every operation |
The agent's surface area shrinks to two verbs: declare (write the contract) and observe (read structured state). Everything in between — locking, ordering, secret resolution, rollback, drift repair — is Nanokit's job and does not depend on the agent getting it right.
What this buys you
- Idempotence as a property, not a discipline. Applying the same config twice converges to the same state; the second run is a no-op by drift-hash comparison.
- Reviewable changes. Because intent lives in YAML, every agent decision is a diff a human can read before it happens, not a log line after it happened.
- Constrained authority. Every change goes through the config contract and the reconcile pipeline; there is no path that skips planning, locking, or drift detection.
Config write access implies command execution
The contract itself does express commands — services.*.start, .command, .hooks.*, provisioning.install, cron.*.command, and deploy.*.prepare (which runs on the remote host) are free-form shell strings. So an actor able to write nanokit.yml and apply it can execute commands on the host and on every deploy target. The schema narrows what can be declared; it does not by itself bound authority.
Bounding it is the job of the agent tool layer, not the config. The MCP server does exactly that: it exposes a closed allow-list of writable fields and refuses to write any command-bearing field until a human approves that exact request with nkapp mcp approve.
Where to go next
- The Declarative Contract: how
nanokit.ymlmaps to deterministic reconcile. - Machine-Readable State: what an agent can observe, and through which channels.
- The MCP Server: connect an agent host to Nanokit's typed tools.
Shipped: the MCP server
nkapp mcp exposes Nanokit to agent hosts as 28 typed tools. They cover reads such as get_environment and get_plan, intent writes such as create_environment and set_secret, and plan-gated applies such as deploy, rollback and backup. Destructive operations (destroy, restore) stay human-only commands. See The MCP Server.