A small control plane around a fast worker
The model is not the system. The packet, state transitions, fallbacks, and evidence are.
01 / steer
review before executionplan + review + judgement
scope / risk / evidence
02 / execute
high-throughput workerbounded implementation
registry -> route -> runbook
03 / prove
state and evidencelease / checkpoint / resume
OTel -> Langfuse -> local
if quota: health-check OpenRouter, then fallback
if recovered: route back to Go, do not drift
always: checkpoint before the next action
The most useful change in my AI setup was not choosing a cleverer model. It was deciding that the model making the plan did not have to be the model doing every keystroke.
I now use Sol for the work that benefits from broad context: planning, reviewing the plan, judging whether the result is actually acceptable, and deciding when a risk deserves a human decision. OpenCode Go, with Luna as the high-execution worker, handles the bounded implementation loop. The queue, skill registry, checkpoints, and telemetry make the split observable instead of turning it into folklore.
That sounds like a model-routing story. In practice, the models were the easy bit. The hard part was making sure a half-finished task could be understood, resumed, measured, and safely rerouted without somebody reading an old transcript for twenty minutes.
The short version
This is an architecture note, not a promise that a particular subscription or provider is always cheaper. The measurements below come from different windows and different workloads. They are useful operational evidence, not a matched benchmark.
Why put Sol at the gate?
Sol is most valuable before and after execution. Before execution it can turn an ambiguous request into a packet: objective, paths, constraints, risk, tool budget, deadline, acceptance checks, and the exact next action. During review it can challenge the packet rather than rubber-stamp it. After execution it can judge the result against the acceptance checks and decide whether a retry, a human decision, or a new packet is needed.
The gate is mandatory for high-risk work. That is deliberate. A fast worker should not be able to widen its own scope, silently change the provider chain, or mark an incomplete result as complete just because a command returned zero.
The useful distinction is:
- Planning: What is the smallest safe packet that can produce the result?
- Review: Are the paths, permissions, provider assumptions, and acceptance checks credible?
- Judgement: Does the evidence support
complete, or does the work need a bounded next action?
Sol is not a permanent supervisor that watches every tool call. It is a decision point with a durable record. Once a packet passes the gate, Go gets enough context to execute without inheriting the whole planning transcript.
Go is the execution lane
OpenCode Go is useful here because it is the high-execution lane. Luna can spend its context on reading the relevant files, making the change, running the narrow check, and returning evidence. That is a better use of a worker than making it rediscover the entire system design from a long parent conversation.
The packet is intentionally boring:
task_id: publish-sol-go-architecture-20260824
owner: opencode-go-luna-article-builder
risk: HIGH
objective: publish one evidence-led architecture article
allowed_paths: /Users/rajeev/Code/rajeevg.com
done_when: article builds, route renders, evidence is reported
next_action: inspect existing MDX patterns and add the smallest publishable sliceThe task ID and packet digest are repeated at acknowledgement. This matters because a worker should not begin from a vaguely similar prompt. The packet is the contract; the transcript is an implementation detail.
Deterministic skills beat prompt luck
The skill registry is a small deterministic index, not a second model. Each entry names its purpose, allowed tools, expected evidence, and the runbook needed for the task. Routing starts from explicit hints such as architecture, frontend, or documentation, then selects the smallest healthy set that covers the packet.
The selected skill set in the current evidence window was four healthy skills. That is a health result for those selected entries, not a claim that every installed skill was audited.
The important rule is that routing is reproducible. A worker should be able to explain why a skill was selected, which version of its instructions it used, and what evidence it was expected to return. Vercel skills distribution is useful as a way to distribute versioned skill material and runbooks, but distribution is not validation. The local registry remains responsible for checking compatibility, required tools, and health before routing.
This separation also makes migrations safer. A skill can be published, indexed, health-checked, canaried, and then promoted. Replacing a skill in place without that sequence creates a hidden behavior change in every future packet.
The queue is the memory
The queue holds state that should survive a timeout, a process restart, or a model change. The state machine is monotonic for normal work:
queued -> leased -> acknowledged -> running -> verifying -> complete
| | | |
+----------+-------------+-------------+--> retryable / blockedThere are two safeguards I care about most.
- Lease ownership: only the current owner can advance or release its work. A replacement does not steal a live task just because it has a newer transcript.
- Checkpoint before continuation: the worker records what completed, the evidence that proves it, the current state, and one exact next action before doing more work.
The checkpoint is smaller than the conversation and more useful than the conversation. It lets a replacement worker resume from state instead of replaying every thought that led there.
The current queue snapshot contained 1 active task, 15 stale or expired tasks, and 59 complete tasks. That snapshot is a point-in-time operational view. It is not a throughput metric, and stale work is not evidence that the queue is healthy by itself. It is a prompt to review lease expiry, release behavior, and whether blocked tasks are being closed with a reason.
Quota is a circuit, not a surprise
The provider path has an explicit quota and reset circuit. The normal route is Go. If the Go quota is exhausted or a reset is in progress, the circuit does not immediately send work to a fallback. It first health-checks OpenRouter, verifies that the selected fallback model and credentials are usable, and records why the route changed.
The fallback is gated by health because a provider that is merely configured is not necessarily available. If OpenRouter fails its health check, the task becomes retryable or blocked with evidence. It does not churn through providers hoping one will work.
When the Go quota resets, the circuit returns to Go. The return is also explicit and observable; otherwise a temporary fallback quietly becomes a permanent provider migration.
if (goQuota.isAvailable()) {
return route("opencode-go", packet)
}
if (await openRouter.healthCheck() && openRouter.isAllowedFor(packet)) {
return route("openrouter", { ...packet, fallback: true })
}
return retryable("no healthy execution route", { taskId: packet.taskId })This is deliberately not a provider configuration change. It is a routing rule with a health gate, a reason code, and a return path.
Keep the rollback paths
I have preserved the CLIProxyAPI and OpenRouter rollback paths rather than deleting them because a migration is not safe if its escape route exists only in someone's memory. The normal Go lane can be tested and promoted while the previous adapters remain available for a bounded rollback.
That does not mean every provider should be active all the time. It means the system keeps a known seam:
- the packet contract stays provider-neutral;
- the Go adapter owns normal execution;
- the OpenRouter adapter can serve a health-gated fallback;
- the CLIProxyAPI path remains available for rollback and diagnosis;
- the evidence record identifies which adapter actually handled the packet.
Rollback should be a state transition with a reason and an expiry, not an emergency edit to a config file. Once the primary route is healthy again, new work returns to Go and the fallback is drained rather than left to accumulate hidden state.
The migration mistake that changed the rules
I learned this one by breaking the session that was doing the migration.
The active Codex process had started with model_provider = "cliproxyapi". I changed the config on disk and moved the old CLIProxyAPI LaunchAgent, assuming the running process would follow the new route. It did not. Running sessions keep the provider chain they inherited at startup, so I had removed a path that the parent session still needed. Recovery meant restoring the provider and restarting the old 8080 -> 18081/8319 chain.
It was avoidable, and the fix is now a hard migration sequence:
- Identify active consumers, including long-running sessions and child processes.
- Add the new path without removing the old one.
- Prove the new route with a fresh disposable session.
- Send new work to it while old sessions keep their inherited route.
- Let those sessions drain.
- Prove the old provider, daemon, port, or LaunchAgent is unused.
- Only then disable it, with a tested rollback path still available.
Changing ~/.codex/config.toml changes future sessions. It does not rewrite the assumptions inside a process that is already running. That sounds obvious written down. It was less obvious at one in the morning with several provider layers in motion.
The tool surfaces have different jobs
MCPs, CLIs, APIs, and AGENTS.md are not interchangeable copies of instructions. They are different control surfaces.
- MCPs expose structured capabilities such as browser control, documentation retrieval, and telemetry queries. Their schemas should be deterministic and their failures should name the invalid field.
- CLIs are good for lifecycle transitions, checkpoints, local builds, and evidence collection. They provide a narrow shell interface that can be audited in a runbook.
- APIs connect the queue, provider adapters, Langfuse, OpenTelemetry collectors, and distribution systems. They need timeouts, authentication, health checks, and explicit retry behavior.
AGENTS.mdshould contain the short always-loaded policy: ownership, safety boundaries, and how to discover the right runbook. It should not become a 2,000-line encyclopedia.- Runbooks hold the detailed procedures for browser recovery, provider rollback, queue release, MCP diagnosis, and migration. They are loaded when the packet needs them.
This division keeps the interface small enough to reason about. The implementation can be deep without forcing every worker to carry every procedure into every task.
Observability that can answer a question
I want the operator view to answer questions, not merely show a green dashboard.
Langfuse is the trace and generation view. OpenTelemetry is the portable event shape. The local operator dashboard is the practical surface for queue state, provider route, skill health, quota circuit, checkpoint age, and evidence links.
The useful trace dimensions are deliberately structural:
- task ID and packet digest;
- parent and child transcript lineage;
- role, provider, model, and route reason;
- input/output token fields where available;
- tool count, retry count, compaction, and completion state;
- checkpoint and queue transition timestamps.
Prompts, tool arguments, tool output, credentials, and private message bodies do not belong in a general operator index. A dashboard can be useful without becoming a second archive of the work.
The current evidence check found zero missing declared dashboard sources. That means every source declared by the dashboard contract was present for the check. It does not mean the sources are timeless, complete, or correct for every future route.
What the current numbers say
| Signal | Observed value | How to read it |
|---|---|---|
| OpenCode Go | 13,583,938 tokens / $0.5239769 | Recorded workload and cost in the Go evidence window, not a universal rate. |
| Live OpenRouter fallback | 1,180 tokens / $0.000121 | One observed fallback, not proof of a normal fallback cost. |
| Historical premium share | 97.78% | Historical share across a different window; it is not comparable to the live fallback row. |
| Queue snapshot | 1 active / 15 stale or expired / 59 complete | Point-in-time state, not throughput or success rate. |
| Selected skills | 4 healthy | Health of the selected set, not an audit of the whole registry. |
| Dashboard source check | 0 missing declared sources | The declared source contract resolved for this check. |
The evidence windows are not aligned. Go usage, the one live OpenRouter fallback, the historical premium share, and the queue snapshot answer different questions at different times. I am keeping them together because they describe the operating system, not because they form a controlled experiment.
A first directional reading from the build itself
We now have a little more than a static architecture snapshot. Three substantial slices of this build ran through the new Go queue: the operator dashboard, this article, and the final system-closure pass. All three completed, all three needed one retry, and all three passed native Sol review. The retained checks include a production content build, responsive browser proof, 78 focused dashboard tests, 95 focused closure checks, and a final unrestricted suite of 161 passing tests.
The telemetry is still annoyingly uneven. Only the dashboard slice retained a complete provider counter in its queue evidence: 5,166,631 Go tokens at a reported cost of $0.19260677. That makes 5.17 million tokens a lower bound for the three slices, not their total. The other two completion records prove what ran and what passed, but not how many worker tokens they consumed. Fixing that hole is now part of the system rather than a footnote I can ignore.
The cleanest comparison is a smaller matched canary. The same task and the same five tests were run once through native Sol and once through Go. Both arms passed 5/5. The Go arm moved 100% of that execution slice off ChatGPT subscription tokens, but it used 3.13 times as many provider tokens and took about 2.30 times as long. In other words, the routing worked economically, not magically: it exchanged cheap worker capacity and latency for scarce subscription capacity while preserving the observed result on one small task.
There is also a less flattering number. The final closure audit counted 620 parent tool calls across two turns, against a combined policy budget of 120, and marked that as a hard delegation breach. Tool calls are not tokens, so I will not pretend that this is a subscription-cost calculation. It is still the clearest sign of where premium usage is leaking: Go is doing large execution runs, but Sol is spending too long integrating, rechecking, and tidying their results.
So the direction is encouraging, but the verdict is not in. We have evidence that bounded worker execution can leave the subscription meter entirely untouched while passing the same checks. We also have evidence that an overactive parent can give much of that advantage back. A stronger worker model can wait. The next gains should come from tighter result packets, complete per-dispatch counters, fewer parent-side tool calls, and one review pass unless the evidence genuinely fails.
The deferred Phase 6 objective
The ambitious objective is a tenfold subscription reduction with indistinguishable quality. That is a deferred Phase 6 objective, not a proven result.
The current evidence supports narrower statements:
- planning, review, and judgement can be separated from high-execution implementation;
- a deterministic registry can make skill selection explainable;
- queue leases and checkpoints make interruption recoverable;
- a health-gated OpenRouter fallback has been observed, while the reset-aware controller implements and tests the return to Go;
- OTel, Langfuse, and a local dashboard can connect operational claims to records;
- provider and rollback seams can remain available during migration.
It does not support a tenfold savings claim, an indistinguishable-quality claim, or a universal token reduction claim. Those require a paired experiment with the same packet, acceptance checks, task class, evidence version, retries, and repeated runs across both arms.
Maintenance is part of the architecture
The system will drift. My minimum maintenance loop is:
- Revalidate skill health and registry versions before a promotion.
- Expire or release stale leases with a durable checkpoint and reason code.
- Check that dashboard source declarations still resolve and that telemetry fields have not silently changed.
- Run a canary packet through Go, the health-gated fallback, and the return-to-Go path when provider behavior changes.
- Preserve the previous adapter and rollback runbook until the new route has passed its evidence window.
- Migrate state with a versioned schema, a dry run, a backup or export, and a reversible cutover.
The safest migration is deliberately uneventful: add the new reader, dual-write only when necessary, compare records, cut over, observe, then remove the old path after a defined retention period. Changing the packet shape, provider route, queue state, and dashboard schema in one go is how I ended up repairing infrastructure instead of improving it.
What I would build next
I would build the paired measurement harness before trying to optimise further. It should freeze a packet digest, run direct and delegated arms, attach the same acceptance checks, record all retries and fallback calls, and refuse to produce a saving claim when the task fingerprints differ.
That harness is the missing bridge between a well-instrumented architecture and a defensible efficiency result. Until it exists, the right conclusion is modest: the system is more recoverable, more attributable, and easier to review. Whether it is ten times cheaper while preserving quality remains work for Phase 6.
Sources and operating notes
- OpenTelemetry generative AI semantic conventions
- Langfuse observability documentation
- OpenRouter generation metadata
- Vercel Skills
- OpenCode documentation
The article metrics come from the privacy-safe operator-snapshot/v1 artifact generated at 2026-08-24T00:47:34Z, fingerprint 4c12fbc025ad3fd6d1908e101d078676553962a94681a13194ef8445c68f0ac3. That snapshot records the Go and OpenRouter token/cost rows, queue state, selected-skill health, source health, and three fallback transition events. The live OpenRouter row is independently tied to generation gen-1787532425-zr6WGUwsCyBY6SqSNZMC, served by DeepInfra using deepseek/deepseek-v4-flash-0731.
These are operational artifacts, not provider invoices. The differing evidence windows should not be combined as if they were one benchmark run. The production capacity state was closed at publication time, but the article does not treat that point-in-time state as proof of a matched fallback-and-return experiment.