What happens
bridgeCellModel builds a child's wire model from the child's own AgentProfile. When that profile names a model without a provider, the seam's provider is not inherited — the harness name is prefixed directly and the child is routed to the harness's own default provider.
dist/supervise-*.js (0.128.0, unchanged since at least 0.120.0):
const model = hasBackendModel ? concreteModelId(backendModel) : qualifyProviderModel(profile.model);
...
if (model) return model.startsWith(`${harness}/`) ? model : `${harness}/${model}`;
qualifyProviderModel({ default: 'glm-5.2' }) returns 'glm-5.2', so the wire id becomes pi/glm-5.2 — no provider segment. pi then resolves glm-5.2 against its default provider.
Why it matters
The seam was configured with pi/tangle-router/glm-5.2. The child asked for the same model by name and silently got a different provider, then died before its first turn:
bridgeExecutor: bridge stream error: pi exit 1:
No API key found for amazon-bedrock.
Three children in one supervised run settled down with spent.tokens = 0. The run reported no-winner/aborted with no indication that the cause was a dropped provider segment. From the operator's side this looks like a credential problem, and the natural fix (add a bedrock key) is exactly wrong.
The failure is quiet in the way that matters: a provider-less model is a valid wire id, so nothing rejects it. It routes somewhere real, just not where the seam pointed.
Why the obvious workarounds don't apply
- Seam
agentProfile overlay — correctly refused: supervise: backend agentProfile overlays are not allowed because they run after spawn authorization. A child could be authorized as one profile and executed as another, so this is not a gap to reopen.
allowedModels — assertProfileModelsAllowed checks profile.model?.default, .small, subagent and mode models. All of those are bare names (glm-5.2); none carries the provider. The allow-list cannot distinguish the correct route from the broken one.
- Instructing the supervisor to always write the provider — tried; a run still lost three children to it. Prompt compliance is not a sound guard for a wire-level default.
Proposed fix
When the profile's model has no provider, and the seam model resolves to the same harness, inherit the seam's provider segment rather than emitting a provider-less wire id:
// seam: pi/tangle-router/glm-5.2 ; profile: { default: 'glm-5.2' }
// currently -> pi/glm-5.2 (harness default provider; wrong)
// proposed -> pi/tangle-router/glm-5.2
If inheriting is considered too implicit, the safe alternative is to reject a provider-less profile model when the seam carries a provider, so the failure names its own cause at spawn authorization instead of surfacing as a missing credential for a provider nobody configured.
Either way the invariant worth stating is: a child that names the seam's model must not be routed to a different provider than the seam.
Reproduce
Supervise with a bridge backend on pi/<provider>/<model>, and have the supervisor spawn a child whose profile is { harness: 'pi', model: { default: '<model>' } } — provider omitted. The child settles down, spent.tokens = 0, with a credential error naming the harness's default provider.
Observed with runtime 0.128.0, cli-bridge provider 0.3.5, pi (earendil) 0.83.0.
What happens
bridgeCellModelbuilds a child's wire model from the child's ownAgentProfile. When that profile names a model without a provider, the seam's provider is not inherited — the harness name is prefixed directly and the child is routed to the harness's own default provider.dist/supervise-*.js(0.128.0, unchanged since at least 0.120.0):qualifyProviderModel({ default: 'glm-5.2' })returns'glm-5.2', so the wire id becomespi/glm-5.2— no provider segment. pi then resolvesglm-5.2against its default provider.Why it matters
The seam was configured with
pi/tangle-router/glm-5.2. The child asked for the same model by name and silently got a different provider, then died before its first turn:Three children in one supervised run settled
downwithspent.tokens = 0. The run reportedno-winner/abortedwith no indication that the cause was a dropped provider segment. From the operator's side this looks like a credential problem, and the natural fix (add a bedrock key) is exactly wrong.The failure is quiet in the way that matters: a provider-less model is a valid wire id, so nothing rejects it. It routes somewhere real, just not where the seam pointed.
Why the obvious workarounds don't apply
agentProfileoverlay — correctly refused:supervise: backend agentProfile overlays are not allowed because they run after spawn authorization. A child could be authorized as one profile and executed as another, so this is not a gap to reopen.allowedModels—assertProfileModelsAllowedchecksprofile.model?.default,.small, subagent and mode models. All of those are bare names (glm-5.2); none carries the provider. The allow-list cannot distinguish the correct route from the broken one.Proposed fix
When the profile's model has no provider, and the seam model resolves to the same harness, inherit the seam's provider segment rather than emitting a provider-less wire id:
If inheriting is considered too implicit, the safe alternative is to reject a provider-less profile model when the seam carries a provider, so the failure names its own cause at spawn authorization instead of surfacing as a missing credential for a provider nobody configured.
Either way the invariant worth stating is: a child that names the seam's model must not be routed to a different provider than the seam.
Reproduce
Supervise with a bridge backend on
pi/<provider>/<model>, and have the supervisor spawn a child whose profile is{ harness: 'pi', model: { default: '<model>' } }— provider omitted. The child settlesdown,spent.tokens = 0, with a credential error naming the harness's default provider.Observed with runtime 0.128.0, cli-bridge provider 0.3.5, pi (earendil) 0.83.0.