Repository navigation
Add free-tier cloud models as a probed, liveness-gated subagent placement pool #79
Description
Proposal
Why
The fleet already has two placement pools: local llama-skein hosts (ctx-aware-subagent-placement,
role-placement-policy) and other live opencode-skein sessions (session-peer-awareness). llama-
skein hosts are frequently busy running their own opencode-skein sessions. The user's own
workaround, done manually today: open /models, search "free", pick a free-tier cloud provider,
send it a throwaway "hi" to check it actually responds, and if so use it as an extra subagent
target when the local fleet is saturated. This proposal makes that workflow a placement source
instead of a manual routine.
This must not repeat the exact failure class subagent-notification-reliability exists to fix or
ctx-aware-subagent-placement already hardened against for local hosts: a placement source that
looks available but silently isn't (rate-limited, cold, revoked) must never be selected, and the
parent must never block synchronously on an uncertain candidate. That is why this change depends
on subagent-notification-reliability landing first — a third, inherently less reliable
placement pool is a bad idea to add on top of a wake-up path that isn't already trustworthy.
What Changes
1. Discover free-tier cloud providers via existing /models search
Reuse whatever provider/model catalog /models already queries to filter for a "free" tag or
zero-cost pricing metadata, rather than a hardcoded list — provider free tiers change.
2. Liveness handshake before eligibility, not before every placement
A discovered free-tier candidate is not placement-eligible until it passes a strict, cheap
handshake: send a short deterministic prompt (e.g. "Are you available? If so, answer exactly
'yes'.") and require an exact-match response within a short timeout. This mirrors exactly the
manual test the user already does. Handshake results are cached with a short TTL (candidates are
re-probed periodically, not on every placement decision, to avoid spending free-tier quota on
liveness checks alone) and a candidate that fails the handshake is not offered again until its
next probe window.
3. Extend placement scoring, don't replace it
LocalPlacement.pick (placement.ts) gains a lower-priority pool: local llama-skein hosts and
live opencode peers are preferred (residency/warmth already scores them highly); a free-tier
cloud candidate is only offered when no local/peer target is eligible, consistent with the
existing "silently moving a cloud parent's subagents onto local weights is a quality surprise, the
opposite is not" framing from role-placement-policy. A free-tier target is always cloud, so none
of the residency/VRAM-fit machinery applies to it — it is either liveness-passed and eligible, or
not offered.
4. Never select an unverified candidate
Selection MUST require a passed handshake within the current TTL window. A candidate whose probe
failed, is stale, or was never run MUST NOT be selected — including as a last-resort fallback.
Falling through to "no eligible target, run it yourself" is always safe; silently placing on an
unverified candidate is not.
Non-Goals
- Not adding paid/metered cloud providers to placement — free-tier discovery only.
- Not building general cloud-provider health monitoring — the handshake is a placement gate, not
observability infrastructure. - Not the Claude-Code cross-session peer protocol (
claude-peer-protocol-spike) — that is a
different kind of peer entirely (another live agent session, not a model endpoint) and is
explicitly out of scope here.
Dependencies
- Depends on
subagent-notification-reliabilityshipping first (see Why). - Extends the scoring machinery from
ctx-aware-subagent-placementandrole-placement-policy;
does not modify their local-host logic.
Impact
- New: free-tier discovery + handshake probing, likely
packages/opencode/src/local/free-provider.ts
or alongside existing model catalog code (exact location TBD by whatever already backs/models
search — investigate before creating a new module if one fits). - Modified:
packages/opencode/src/local/placement.ts(pool extension, eligibility gate),
packages/opencode/src/tool/task.ts(candidate pool now includes free-tier when applicable).
Disposition (2026-09-18)
Archived — superseded/obsolete. Folded into skein-pool: an idle peer on a cloud model is a delegation target when every local host is full. No separate liveness-probed pool.
Tasks
Slice 1: Discovery
- 1.1 Locate the catalog/query
/modelsalready uses; investigate whether "free" is exposed
as a tag, zero pricing, or must be inferred from provider metadata.- Validation: manual — list at least the free-tier providers reachable in this environment
- 1.2 Add a discovery function returning candidate free-tier providers/models from that
catalog, with no hardcoded provider list.- File: TBD by 1.1 (existing model-catalog module preferred over a new one)
- Validation: unit test with a mocked catalog response
Slice 2: Liveness handshake
- 2.1 Implement the handshake: send a short deterministic prompt, require an exact-match
response within a bounded timeout, on a per-candidate basis.- File:
packages/opencode/src/local/free-provider.ts(new, or co-located per 1.1) - Validation: unit test — matching response passes, non-matching/timeout fails
- File:
- 2.2 Cache handshake results with a short TTL; re-probe on expiry, not on every placement
decision.- Validation: unit test — a cached pass is reused within TTL; expired entries are re-probed
Slice 3: Placement integration
- 3.1 Extend
LocalPlacement.pickwith a lower-priority free-tier pool, offered only when no
local/peer candidate is eligible.- File:
packages/opencode/src/local/placement.ts - Validation: unit test — a free-tier candidate is never selected while a local candidate is
eligible
- File:
- 3.2 Hard-gate selection on a currently-passed handshake (within TTL); no fallback selection
of an unverified or stale-probe candidate.- File:
packages/opencode/src/local/placement.ts - Validation: unit test — an unverified candidate is never selected, even as last resort
- File:
- 3.3 Wire the pool into
task.tscandidate resolution alongside existing local/peer sources.- File:
packages/opencode/src/tool/task.ts - Validation:
bun run typecheck
- File:
Slice 4: Verification
- 4.1
bun run typecheckandbun test test/local/ test/tool/green.- Validation:
bun run typecheck && bun test test/local/ test/tool/
- Validation:
- 4.2 Live check: with local fleet saturated (or simulated as such), a subagent placed on a
free-tier candidate completes and its result reaches the parent via the
subagent-notification-reliabilitywake-up path.
Unchecked items above: see Disposition in proposal.md (2026-09-18).
Activity
androidand commentedon Sep 17, 2026
Archived 2026-09-18 — see the change's Disposition section.