CrossBridge 业务集成实战指南:智能体嵌入场景
本文档专门针对 "独立应用 + 嵌入式交付" 的双重业务场景,提供具体的架构设计灵感和代码实现模式。
🎯 核心痛点与解决思路
现状分析
你的智能体应用 (Child) 需要支持:
- 独立运行模式: 直接访问 URL,拥有完整的默认功能。
- 嵌入运行模式: 被第三方系统 (Parent) 通过 iframe 嵌入,UI 文案和交互行为需要受控于父系统。
CrossBridge 的边界
- ✅ 能做的: 极其稳定地在父子之间传递 JSON 数据、指令、状态字符串。
- ❌ 不能做的: 直接传递 JavaScript
Function对象(序列化会丢失);直接操作对方的 DOM 节点(跨域限制)。
🔑 核心设计模式:数据驱动与控制反转
💡 场景一:子 App 控制父 App (跳转/功能联动)
需求: 子应用中点击按钮,要求主应用跳转页面或打开弹窗。
实现方案:Action Dispatcher 模式
子应用不应该关心"如何跳转",它只需要发出"请求跳转"的意图。
1. 子应用 (Agent Chat) 代码
在子应用中,封装一个统一的行为触发器:
typescript
// utils/action.ts
const handleAction = (actionType: string, payload: any) => {
// 判断环境:如果是独立运行,执行默认逻辑
if (bridge.role === 'standalone') {
if (actionType === 'navigate') {
window.location.href = payload.url;
}
return; // 结束
}
// 如果是嵌入环境,将意图"外包"给父页面
bridge.emit('child-request-action', {
type: actionType,
data: payload,
timestamp: Date.now()
});
};
// 业务组件中使用
<button onClick={() => handleAction('navigate', { url: '/user/profile' })}>
查看画像
</button>2. 父应用 (Container) 代码
父应用注册监听,接管所有请求:
typescript
bridge.on('child-request-action', (request) => {
switch (request.type) {
case 'navigate':
// 父应用使用自己的路由系统进行跳转
myAppRouter.push(request.data.url);
break;
case 'open-modal':
// 打开父应用的弹窗
Modal.show(request.data.title);
break;
case 'auth-expired':
// 处理子应用 Token 过期,父应用弹出登录框
showLoginDialog();
break;
}
});💡 场景二:父 App 修改子 App 的文案和点击事件
需求: 交付给客户A时按钮叫"提交",交互是提交表单;交付给客户B时按钮叫"咨询",交互是跳转客服。
难点: 无法跨域传递函数。
实现方案:UI Configuration + Event Hook 模式
此方案将子应用改造为"可配置组件"。
1. 子应用改造 (数据驱动 UI)
定义一份 UI 配置协议(Schema),并设置默认值。
typescript
// default-config.ts
const defaultConfig = {
submitBtn: {
text: '开始对话', // 默认文案
actionId: 'default-chat', // 默认行为标识
visible: true
},
theme: {
primaryColor: '#007AFF'
}
};
// 业务组件 (Vue/React)
const AgentButton = () => {
const [config, setConfig] = useState(defaultConfig);
// 监听父页面发来的配置覆盖
useEffect(() => {
bridge.on('update-ui-config', (newConfig) => {
// 深度合并配置
setConfig(prev => ({ ...prev, ...newConfig }));
});
}, []);
const handleClick = () => {
// 关键点:点击时,不硬编码逻辑,而是上报行为标识
const actionId = config.submitBtn.actionId;
// 1. 先尝试执行内部逻辑
if (actionId === 'default-chat') {
startChat();
return;
}
// 2. 如果是自定义行为,广播出去让父页面处理
bridge.emit('component-event', {
source: 'submit-btn',
actionId: actionId
});
};
if (!config.submitBtn.visible) return null;
return (
<button style={{ color: config.theme.primaryColor }}>
{config.submitBtn.text}
</button>
);
};2. 父应用配置 (客户交付代码)
交付给不同客户时,只需在父页面初始化时发送不同的配置。
typescript
// 客户 A 的父页面代码
await bridge.connect();
// 场景:想要修改文案,并未点击按钮绑定自定义逻辑
bridge.emit('update-ui-config', {
submitBtn: {
text: '联系人工客服', // 修改文案
actionId: 'customer-service-redirect' // 修改行为标识
},
theme: {
primaryColor: '#FF6600' // 修改皮肤
}
});
// 监听自定义行为
bridge.on('component-event', (event) => {
if (event.actionId === 'customer-service-redirect') {
// 这里写父页面特有的逻辑
window.open('https://kefu.baidu.com');
}
});🚀 总结:架构设计的灵感
为了实现高质量的独立+嵌入双模交付,建议遵循以下三个原则:
子应用"无状态"化 (UI 即函数): 不要在子应用的组件里写死 "点击按钮=发起POST请求"。而是写成 "点击按钮=执行当前配置的 ActionID"。
父应用是"大脑",子应用是"手脚": 在嵌入模式下,复杂的业务判断(如权限校验、页面跳转、全局弹窗)尽量上浮到父应用处理,子应用只负责展示和基础输入。
定义协议 (Protocol): 你需要维护一份 JSON 协议文档,告诉你的集成方:
- 发送什么 JSON 可以通过
update-ui-config改界面。 - 监听什么事件可以捕获
child-request-action。
- 发送什么 JSON 可以通过
使用 CrossBridge 插件,你已经拥有了最稳固的通信管道。现在只需要在其实封装这层简单的 JSON 协议,就能完美解决你面临的两个交付难题。