Hand off the unfinished delegation release

40098c70b45a · Devin AI · · parent 26a7e605e9c3

Hand off the unfinished delegation release

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

pushed
by user · WAL seq 285 · 2026-08-24T07:06:03.334353Z

Changed files

  • added docs/2026-08-24-delegation-release-handoff.md

Diff

1 file changed, +120 -0

docs/2026-08-24-delegation-release-handoff.md added +120

@@ -0,0 +1,120 @@

1
# Delegation release handoff, 2026-08-24
2
3
This document hands off unfinished work on model-driven delegation. The CLI side
4
is published. The server side is committed and pushed to forge `main`, but
5
production still runs the previous release, so the new behavior is not live yet.
6
7
## What is live
8
9
- Production runs openagents.com `adc413e98c701e1aa23db5d82eac525e5cca23e2`,
10
  image digest
11
  `sha256:28e7bafa803f8125cb60f139d38df7fbe6f5ef313b261ecbc14249f9211683c0`,
12
  on `sarah-fleet-1`, `sarah-fleet-2`, and `sarah-fleet-3`. Forge target
13
  `0c4f5374-d693-4b6a-a2a4-3b679887e2d1` is `live`.
14
- `POST /api/v3/threads` answers `201`, so `openagents coder` opens a thread.
15
- `@openagentsinc/cli@0.3.5` is the published latest release. `0.3.3` is
16
  deprecated because it shipped unresolved `catalog:` dependencies.
17
- In `0.3.5` the model calls a `delegate` tool during a conversation. There is
18
  no slash command, no `--child-model` flag, and no client-side provider
19
  credential. Children are real `opencode` processes that spend a grant the CLI
20
  obtains from the server.
21
22
## What is committed but not deployed
23
24
Forge `main` for openagents.com is
25
`26a7e605e9c3462a79ecd2aa185abe293cc0d9c7`, "Give a signed-in account credit, a
26
chat scope, and a second model". It carries three behavior changes, each with
27
tests, and the full suite passes locally (`3 doctests, 4141 tests, 0 failures`):
28
29
1. **A chat scope on ordinary login.** `openagents auth login` now mints
30
   `["chat:account", "forge:write"]`. `OpenAgents.ApiTokens.default_scopes/0` is
31
   the single source, and the device authorization schema, service, and
32
   controller all defer to it. Before this change, a plain login produced a
33
   token that `POST /api/v3/threads` refused, which is the failure Christopher
34
   hit.
35
2. **Account-level credit.** A signed-in account draws against
36
   `account_credit_microusd`, `100_000_000` microUSD, for the life of the
37
   account rather than per thread. An anonymous visitor keeps
38
   `visitor_credit_microusd`, `2_000_000` microUSD.
39
   `OpenAgents.Inference.Credit.spent/1` sums usage across every grant the
40
   visitor owns, including revoked and expired ones, and
41
   `OpenAgents.Threads.ceilings/1` mints each new grant for the remainder. An
42
   exhausted account is refused with `credit_exhausted` and an actionable
43
   sentence.
44
3. **A second model, routed to OpenRouter.** `OpenAgents.Inference.Models` is
45
   the registry that separates the public ID, the provider module, and the
46
   provider's own model string. `ox-alpha` resolves to
47
   `OpenAgents.Providers.OpenRouter` with provider model `stealth/ox-alpha`;
48
   `gpt-5.6-luna` stays on `OpenAgents.Providers.OpenAI`.
49
   `POST /api/v3/threads` accepts `{"model": "ox-alpha"}`, validates it through
50
   the registry, and mints the grant against it. The inference proxy resolves
51
   the provider from the grant, never from the request body.
52
53
On the CLI side, `0.3.5` opens a **separate** child thread on `ox-alpha` for
54
delegated children, so the parent conversation stays on Luna. A refusal to open
55
that thread is reported, never absorbed: the session says which refusal stopped
56
it rather than quietly running children on the parent's Luna grant.
57
58
## Remaining work, in order
59
60
1. **Deploy `26a7e60` to production.** Follow
61
   `docs/operations/production-deploy-runbook.md`: release gate, image build and
62
   push, promote, migration job, rolling replacement, settle, verify.
63
2. **Verify the routing end to end against production**, with the published
64
   CLI. Do not report success from configuration alone. The claims to prove are:
65
   plain `openagents auth login` opens a thread; the parent grant reports
66
   `gpt-5.6-luna`; the child thread request carries `"model": "ox-alpha"` and its
67
   grant reports `ox-alpha`; the proxy calls
68
   `OpenAgents.Providers.OpenRouter` with `stealth/ox-alpha`; no client-side
69
   OpenRouter key is involved; a child-thread failure surfaces its real code and
70
   message; both grants are revoked on exit.
71
3. **Review credit minting under concurrency.** `Threads.ceilings/1` reads
72
   remaining credit and then mints. Two simultaneous thread opens can each read
73
   the same remainder, so an account can oversubscribe by one grant's ceiling.
74
   Decide whether to serialize on the visitor row or accept the overshoot, and
75
   record the decision.
76
4. **Consider registry uniqueness.** If `openai_model` is ever configured as
77
   `ox-alpha`, `Models.all/0` returns two entries with the same ID. Deduplicate,
78
   or assert uniqueness in a test.
79
5. **Rotate the npm token** pasted in the working session. It published `0.3.4`
80
   and `0.3.5` and is now in a transcript.
81
82
## Deploy notes for this box
83
84
The release gate ran repeatedly here and stalled on environment flakes rather
85
than on the candidate:
86
87
- The gate needs Node 24. Node 20 fails
88
  `assets/test/sidebar_section_test.mjs`. Use
89
  `export PATH="$HOME/.nvm/versions/node/v24.19.0/bin:$PATH"`.
90
- The gate's `version_chain` and later stages connect over TCP, where
91
  `pg_hba.conf` requires `scram-sha-256`. The local `ubuntu` role needs a
92
  password, and the smoke URL must carry it:
93
  `OPENAGENTS_RELEASE_SMOKE_DATABASE_URL='ecto://ubuntu:PASSWORD@127.0.0.1/openagents_release_smoke'`.
94
- `mix precommit` failed once per run on a different load-sensitive test each
95
  time, and every one of them passed in isolation on the same commit:
96
  `OpenAgents.SCV.RunTest`, `OpenAgents.SCV.OpenCodeExecutorTest`, and
97
  `OpenAgents.Machines.IndexReachTest`. The first two spawn real processes and
98
  the third asserts a planner index choice. On an 8-core box under load they are
99
  unreliable. Treat a single failure of one of these as a flake, confirm it in
100
  isolation, and rerun rather than changing the candidate. Making them robust is
101
  worth its own issue.
102
- Two checkouts exist on this box. `~/repos/openagents.com` has the forge as
103
  `origin`; `~/repos/openagents-com` has the GitHub mirror proxy and holds the
104
  warm `_build`, `deps`, and the gate receipts under
105
  `.git/openagents/release-gate-receipts/`. The gate keys a receipt to the exact
106
  SHA, so it must run in the checkout that will build the image.
107
- Promotion needs `deployments:promote` and live operator standing. Saved tokens
108
  expire within 7 days, so mint one through the device authorization flow, or on
109
  a fleet node, at deploy time.
110
111
## Reference material
112
113
- `docs/2026-08-23-nested-thread-delegation-audit.md`, the delegation audit this
114
  work follows.
115
- In the openagents monorepo,
116
  `docs/teardowns/2026-08-23-cc-tool-and-agent-fleet-rendering-reproduction.md`
117
  and `docs/teardowns/2026-08-23-openagents-coder-tui-agent-fleet-port-plan.md`
118
  hold the tool contract, task registry, and fleet rendering specification the
119
  Coder TUI is being ported against.
120
- `INVARIANTS.md` records the credit and scope statements this change updated.

This page updates live while a promote is in flight · changelog