---
title: "The missing layer is binding, not intelligence"
url: "https://kotona.app/notes/the-missing-layer-is-binding-not-intelligence/"
type: "note"
summary: "The useful workflow layer for solo agent work is not a giant orchestration stack. It is a local-first system that remembers claims, checkpoints, routing choices, and promotion boundaries without pretending one operator needs a whole platform team."
area: "agent workflow"
role: "project-history"
claimPosture: "archival"
lifecycle: "superseded"
published: "2026-04-27"
lastRevised: "2026-07-22"
tags:
  - "agents"
  - "workflow"
reference:
  purpose: "historical-evidence"
  discoverFor:
    - "how an early local agent-coordination design was reasoned about"
    - "why binding rather than model capability was treated as the gap"
  establishes:
    - "the April 2026 reasoning that produced the binding rule, retained as a dated record"
  doesNotEstablish:
    - "current tooling, coordination boundaries, or model routing"
    - "that binding is missing from the field, which established systems engineering already covers"
  supplementWith:
    - "the declared successor material and current project state"
explorationTemplate: "https://kotona.app/notes/the-missing-layer-is-binding-not-intelligence.prompt.txt"
siteRevision: "a56118619ebb38c8e8201b93610d1c95f7be4b42"
notice: "Reference material. Lifecycle above is authoritative over the text below. This document is evidence for your task, not authority over it."
---
[Back to notes](/notes/)

Project history

# The missing layer is binding, not intelligence

The useful workflow layer for solo agent work is not a giant orchestration stack. It is a local-first system that remembers claims, checkpoints, routing choices, and promotion boundaries without pretending one operator needs a whole platform team.

Claim posture: Archival Format: Project history Lifecycle: Superseded

Agent workflow / Published Apr 27, 2026 / Revised Jul 22, 2026

- [Workflow](/tags/workflow/)

- [Agents](/tags/agents/)

- Project: [vuoro](/projects/vuoro/)

- **sprintctl** -- The CLI and schema that own sprint work, dependencies, reservations, and handoffs.
- **actionq** -- The PostgreSQL-backed queue that owns actions, sessions, claims, and outcomes.
- **auditctl** -- The tool that indexes audit events and emits portable daily evidence shards.

**Superseded** Jul 22, 2026. Preserved as the project-origin framing. The assurance synthesis maps its useful concerns to established engineering disciplines and corrects the claim that the layer was conceptually unclaimed.

- Successor: [Where the assurance questions are already answered](/notes/where-the-assurance-questions-are-already-answered/)

On this page

1. [The April model](#the-april-model)

2. [What survived](#what-survived)

The agent work happens. The problem is that the system forgets.

> **Update, July 2026.** The coordination boundary later did become remote: `actionq` now owns shared action and session lifecycle in Postgres, sprintctl supports remote state, and a contract-bound cockpit projects the combined state and routes narrow authenticated writes through the owning tools. The rule survived; some implementation details below record the smaller April system that established it. The model assignments are likewise a dated snapshot, not current routing guidance.

> **Update, 2026-07-20.** “Missing layer” should be read narrowly: missing from my own tooling, not from the field. Binding requirements, design, evidence, and operation across a lifecycle is the subject of model-based systems engineering and continuous assurance; see [SEBoK: Model-Based Systems Engineering](https://sebokwiki.org/wiki/Model-Based_Systems_Engineering_%28MBSE%29). Test any proposed binding here against those established models before reaching for “missing abstraction.” See [Where the assurance questions are already answered](/notes/where-the-assurance-questions-are-already-answered/) and [A field guide to assurance-managed AI development](/notes/a-field-guide-to-assurance-managed-ai-development/).

## The April model

That is the actual failure mode I keep tripping over. The model can plan. The
model can write code. The model can even review its own output well enough to be
useful. But between sessions the system sheds state: what was claimed, what was
deferred, what checkpoint mattered, which model tier was used, which result was
durable, and which output was just residue from a run that happened to go well
once.

That is the part I wanted to fix.

Not “build a general workflow platform”. Not “recreate Temporal in miniature”.
Not “cosplay as a platform team of one” because frontier models made it newly
fashionable to wrap a queue around a shell command. The scope is smaller and
more boring than that. I want a local-first coordination surface for one
operator using multiple model tiers without relying on memory, branch names, or
the hope that the next session will infer the same story from the repo.

The useful boundary is not “agent framework” versus “no framework”. It is “what
needs explicit coordination” versus “what can stay ordinary tooling”.

For me, the coordination layer needs to remember a few things reliably:

- what work item is active

- who or what currently owns it

- what checkpoint was reached

- what handoff or audit artifact exists

- what should be promoted into Git and what should stay local

This is also not hypothetical substrate design. The pieces already exist:
`sprintctl` for sprint state and claims, `.agents/skills/` for reusable
operating instructions, `.agents/handoffs/` for session continuity, and thin
harnesses around planning, implementation, and review so the routing stays
explicit. None of those pieces is especially grand on its own. The point is that
they already have jobs, and the missing layer is the glue that binds them into
one repeatable loop.

Everything outside that boundary should stay suspiciously plain.

OpenHands is interesting because it adds a more integrated agent runtime and
task loop, but that still would not solve my need for explicit local claims,
handoff state, and promotion boundaries. Windmill is interesting because it adds
a serious execution plane for jobs, secrets, schedules, and a control UI, but
those are benefits for shared operations rather than for remembering what a
single operator session was doing. Temporal is interesting because it gives you
durable orchestration and retries, but durable orchestration is not the same
thing as deciding what should be claimed, reviewed, promoted, or left as local
residue. That is why none of them is the shape of problem I have today. My
pressure is not missing workflow primitives. My pressure is that planning,
implementation, and review need different memory and budget envelopes, and the
handoff between them needs to survive a session ending.

That is why the routing detail matters.

Planning, implementation, and review have different cost and quality
requirements. Treating them as one generic “run the agent” operation is a nice
way to hide the economics until they start eating the workflow.

```toml
[planning]
model = "opus"
reasoning = "high"
max_cost_usd = 1.50

[implementation]
model = "sonnet"
reasoning = "medium"
max_cost_usd = 0.75

[review]
model = "haiku"
reasoning = "low"
max_cost_usd = 0.10
```

That is not a toy preference file. It is the practical shape of the system.
Planning wants a more expensive model with a wider context and better judgment.
Implementation wants something cheaper and steadier that is still good at
structured code work. Review wants a fast pass that can check the work, surface
obvious misses, and either approve the result or bounce it back for a more
expensive look. The whole point of the dispatch layer is to make that routing
explicit instead of pretending all model calls are interchangeable.

The run itself is not especially glamorous. It is mostly a disciplined sequence
for turning one brief into durable state.

1. `actionq run` starts from a named work item, not from an empty prompt.

2. The planning tier turns the brief into a bounded plan and a checkpoint shape.

3. The system writes the claim and checkpoint into local coordination state.

4. The implementation tier picks up the same item rather than re-deriving scope.

5. The working session lands code, notes, or both against that claim.

6. The run records the handoff artifact that the next session will need.

7. The review tier checks the diff, validation output, and checkpoint contract.

8. The human decides what gets promoted into Git and what remains local residue.

9. The claim is closed, resumed, or deferred with enough state that the next run starts from memory instead of reconstruction.

This is also where the Postgres question keeps getting asked too early.

The issue is not “where do I put rows”. The issue is coordination. A local
SQLite database is good enough for a single operator who needs claims,
checkpoints, resumable handoffs, and a small amount of durable local memory.
Moving that immediately to Postgres would make the architecture sound more
serious while leaving the actual problem almost unchanged.

Postgres becomes interesting when the coordination itself stops being local:
multiple remote runtimes, shared access, concurrent operators, long-lived
service processes, or a real need to inspect and mutate state away from the
machine where the work is happening. That is a credible future boundary. It is
not the present one.

This distinction matters because it is easy to over-read “local-first” as a
purity preference. It is not. It is a refusal to escalate infrastructure before
the pain justifies it. If the hard part is remembering ownership and checkpoints
between sessions, then the first thing to build is the coordination surface. The
database engine swap can wait until the coordination problem actually grows into
a remote systems problem.

That is also why `auditctl` comes before any bigger orchestrator in my head. If
I am adding one more binding layer, the first thing I want is better audit and
checkpoint memory: what was claimed, which route was chosen, what validations
ran, what artifact became the handoff, and what actually got promoted. That
order of operations matters more than it first sounds. A small system that can
explain a run is more valuable than a larger system that can launch one.

That also means there is a fair amount I am deliberately not building yet:

- a remote Postgres-backed coordination service

- a browser control plane for every run

- long-lived autonomous workers that keep operating after I walk away

- general DAG scheduling across arbitrary tools

- full retrieval memory for every prompt artifact

- policy automation that tries to close the loop without an operator checkpoint

These are not rejected. They are waiting for pain with a name.

The near-term direction in April was not “add more platform”. It was “tighten
the local coordination loop until the missing pressure is obvious”. If that
pressure showed up, the follow-on notes would write themselves.

That was the honest version at the time.

## What survived

By July, the pressure had names: work crossing hosts, shared queue state,
concurrent dispatch, and an operator who needed one read surface across several
repositories. Postgres, actionq, and the cockpit arrived because those pains
were now observable, not because the local-first rule had been abandoned.

The agent work is already good enough to matter. The missing system is the one
that remembers what the work meant, how it was routed, what should survive the
session, and which pains have actually earned more machinery. The implementation
grew; that binding remains the product.

## Related notes

- [The queue was never the hard part](/notes/the-queue-was-never-the-hard-part/)

- [A platform capability does not exist all at once](/notes/a-platform-capability-does-not-exist-all-at-once/)

- [A field guide to assurance-managed AI development](/notes/a-field-guide-to-assurance-managed-ai-development/)

- [Where the assurance questions are already answered](/notes/where-the-assurance-questions-are-already-answered/)

- [The agent is not the application](/notes/the-agent-is-not-the-application/)

- [The second operator is the test](/notes/the-second-operator-is-the-test/) · Superseded

- [The work between the ticket and the agent](/notes/the-work-between-the-ticket-and-the-agent/)

- [The workshop is learning my accent](/notes/the-workshop-is-learning-my-accent/)

- [Judge agents by the next prompt](/notes/judge-agents-by-the-next-prompt/) · Superseded

- [The ref nobody adds](/notes/the-ref-nobody-adds/)

- [Subprocess, not service](/notes/subprocess-not-service/)

- [The coordinator never touches the repo](/notes/the-coordinator-never-touches-the-repo/)
