Microsoft Bot Framework主机器人与技能机器人上下文共享问题咨询
无法传递状态的核心原因
- 状态实例天然隔离:主机器人和技能机器人是独立运行的服务,各自的
TurnContext是每轮请求独立初始化的上下文对象,不存在跨机器人的自动传递机制,你在主侧存入TurnContext的属性不会自动出现在技能侧的上下文里。 - 存储默认隔离:哪怕你主侧已经调用
SaveChangesAsync持久化到存储,只要技能机器人没有配置和主机器人完全相同的存储实例,技能根本访问不到主侧存储的状态数据。 - 存储键规则不匹配:就算两边用了同一个存储,Bot Framework的
UserState/ConversationState默认生成的存储键会包含当前机器人的Bot ID作为前缀,主机器人和技能机器人的Bot ID不同,生成的存储键完全不一样,自然找不到同一份数据。 - 属性名不统一:你当前的属性名是用
typeof(RootBot<T>).FullName动态生成的,技能机器人的项目中不存在RootBot<T>类,两边的属性访问器的属性名不一样,就算读到同一份状态数据也匹配不到对应的属性。
可行的解决方案
方案1:通过技能调用的活动直接传值(最简单,适合少量数据共享)
不需要依赖状态存储,主机器人调用技能之前,直接把需要共享的状态存入待发送给技能的Activity的Value或者Properties字段:
// 主侧调用技能前插入 var skillActivity = (Activity)Activity.CreateMessageActivity(); skillActivity.Value = patientResponce; // 后续正常调用技能
技能侧直接从入参读取即可:
// 技能侧OnMessageActivityAsync中读取 var sharedContext = turnContext.Activity.Value as PatientResponce;
方案2:统一状态存储与配置(适合大量数据需要多端共享)
- 第一步:主、技能两个项目都使用完全相同的Blob存储连接字符串初始化
UserState,并将UserState实例注册为单例。 - 第二步:把状态属性名提取为公共常量,不要绑定各自的Bot类名:
// 公共类库中定义常量,两边都引用 public static class SharedStateConstants { public const string UserContextPropertyName = "Shared.UserContext.PatientResponce"; }
- 第三步:自定义状态的键生成逻辑,去掉Bot ID前缀的影响,保证两边对同一个用户生成相同的存储键:
// 两边都注册自定义的存储键生成器 public class SharedUserStateKeyGenerator : IStorageKeyGenerator { public string GetKey(ITurnContext turnContext, string propertyName) { var userId = turnContext.Activity.From.AadObjectId ?? turnContext.Activity.From.Id; return $"UserState.{userId}.{propertyName}"; } }
内容的提问来源于stack exchange,提问作者Andriy Zakharko
相关产品推荐
相关产品推荐

