Skip to content

switchAgentProvider 在同一 type 切换不同 config 时会复用旧实例 #29

@panda-xinyi

Description

@panda-xinyi

hello, 在查看 provider 切换逻辑时发现一个潜在问题:

问题描述

switchAgentProvider(type, config) 的流程是:

  1. activeProviders 取出当前 provider
  2. 调用 shutdown()
  3. 通过 AgentRegistry.getInstance(type, config) 获取新的 provider

AgentRegistry.getInstance 仅按 type 做缓存
type 相同、config 不同时,会直接返回缓存里的旧实例,导致新配置被忽略。

复现场景

// 初始
registry.instances = {
  'claude': ClaudeAgent({ apiKey: 'A' })
};

// 运行期切换配置
switchAgentProvider('claude', { apiKey: 'B' });

实际结果:

  • 当前 ClaudeAgent(apiKey: 'A') 被 shutdown
  • getInstance('claude', { apiKey: 'B' }) 返回的仍是旧实例
  • 看起来切换成功,实际上仍在使用旧配置

根因

目前存在两层缓存:

  • ProviderManager.activeProviders:当前使用中的 provider
  • AgentRegistry.instances:按 type 缓存的实例

switchAgentProvider 的语义是 切换 provider(可能带新配置)
getInstance 的语义是 同一 type 复用实例,两者在「config 是否参与 identity」上不一致。

影响

该问题在以下场景中容易出现:

  • 同一 provider type(如 claude
  • 运行期支持修改配置(apiKey / baseURL / model 等)
  • 使用 switchAgentProvider 做热切换

会导致 配置已切换但实际未生效~

方案

针对这个问题,想到两种处理方式:

方案一:在 switchAgentProvider 时,同步清理 AgentRegistry 中该 type 的缓存实例,确保配置变化时一定会创建新 provider。

await current.shutdown();
registry.clearInstance(type);
const provider = await registry.getInstance(type, config);

方案二:将 switch 明确视为一次新的生命周期切换,直接创建新的 provider 实例;而 getInstance 仅用于复用同一配置下的 provider。

await current.shutdown();
const provider = registry.create(type, config);

欢迎指正 🙏

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