Skip to content

Old chats fail on their previous provider instead of switching to the bot's engine #433

Description

@linear-code

Problem

An old chat can keep a provider session that no longer matches its bot's engine, for example after the user switches the bot to another account or provider. The next turn then validates the old provider instance before switching. If that old account is broken or misconfigured (one repro: "This Custom API instance needs a base URL."), the turn fails against the old provider instead of moving to the bot's selected instance. Engine resolution also switches the old runtime across the instance boundary before the replacement path runs.

Goal

The next message in any chat uses the bot's saved model and provider account, even if earlier messages used another account, and the user never has to fix the old account first. An instance change goes through the existing session replacement path, which keeps conversation continuation and restart recovery. A model change on the same instance still switches in place.

Acceptance criteria

  • On an instance change, the session is replaced without switching or validating the old runtime
  • A model change on the same instance switches in place
  • Moving a Mastra session to standard OpenCode on the legacy bridge works
  • Turn-command and restart-recovery paths both take the replacement path
  • A regression test fails before the fix and passes after it
  • docs/internals/providers.md and docs/user/bots.md describe the behavior, and a patch changeset is included
  • An integrated client check passes: switch a bot's account, send in an old chat on web, and see the reply come from the new account

How to verify

vp test run apps/server/src/orchestration/Layers/ProviderCommandReactor.providerSwitch.test.ts apps/server/src/provider/Layers/AgentController.sessionSwitch.test.ts apps/server/src/provider/Layers/AgentController.reasoning.test.ts

Then, in an isolated dev environment, start a chat on one account, break that account (for example, clear a Custom API base URL), switch the bot to another account, and send a message from the old chat.

Status

Implemented locally on branch cos/session-provider-switch, which is not pushed and has no PR:

  • 092703115, test(server): reproduce stale provider session switching failures, adds turn-command, recovery, same-instance model, and legacy OpenCode regressions
  • 5770e2abd, fix(server): switch stale chat sessions to the requested provider, reads the old driver from the session binding and reuses the replacement path. It changes provider-command/Session.ts and agentController/EngineRouting.ts, plus docs and a changeset.

Verification recorded on 2026-10-06:

  • PASS: the regression failed before the fix and passes after it
  • PASS: provider and orchestration sweep, with 340 files and 2,347 tests passing and 2 files and 6 tests skipped
  • PASS: server typecheck and targeted lint
  • PASS: independent GPT-6.1 Sol review, with no findings
  • NOT CHECKED: live client verification. This stays with the coordinating agent, because the implementation worker was not allowed to start servers.

Context

The session decision lives in provider-command/Session.ts (instanceChanged, providerChanged, and the restart path), called from ProviderCommandReactor.

Created with Claude Opus 5.5 in Claude Code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions