Skip to content

案例2 在应用网站中接入织信全局智能体 ​

适用对象:织信应用开发者、网站模块开发者和负责集成的技术人员。

目标是在某个应用的网站模块中提供智能体会话,完整沿用工作台的会话、模型、技能、专家、知识库、附件、流式输出和历史记录调用方式。网站负责自己的页面布局,服务端仍使用工作台相同的智能体会话服务。

本文介绍如何在应用网站中复用工作台智能体的完整调用链,包括接入协议、开发步骤、代码示例和验收要求。示例中的页面和适配器需要结合实际部署完成开发、构建与联调。

应用效果 ​

下面以已完成的“智能问数”应用为例,展示在应用网站中使用织信全局智能体的效果。用户可以在网站内选择模型和应用查询范围,通过自然语言提问,并从最近提问中继续已有会话。

智能问数首页 ​

首页提供常用问题入口、最近提问和连接状态,用户无需切换到工作台即可开始对话。

智能问数首页,包含最近提问、常用问题和聊天输入框

选择应用范围并输入问题 ​

发送前选择本次查询的应用范围,输入具体业务问题。图中展示的是选择范围和填写问题的状态。

选择工程变更与质量整改闭环应用,并填写客户数量与占比问题

在同一会话中继续追问 ​

已有会话展示了基于上一轮结果继续计算客户占比的过程,回答同时列出计算方式、数据来源和统计时间。截图中的数字仅用于展示该会话的回答效果,不代表当前实时统计。

智能问数多轮对话,回答正式客户数量、占比与数据来源

1. 接入结论 ​

工作台“智能体会话”的核心调用链是:

text
网站页面获取当前登录态和应用上下文
  → 用户选择模型、权限、技能、专家、知识库
  → 首次发送时 POST /informatclaw/session,取得 sessionId
  → GET /informatclaw/session/{sessionId}/stream 建立 SSE
  → POST /informatclaw/session/{sessionId}/input 发送消息
  → 转换原始 SSE 事件并更新会话界面
  → 后续消息沿用同一个 sessionId
  → 重新进入时读取历史消息、状态,并恢复 SSE

网站模块应复用这条调用链。不要把 informat.aiagent.completions、chatCompletions 或 /aiagent/chat 当作工作台会话接口。它们不能直接替代本文描述的工作台会话协议。

目前网站 RPC 中有 systemService.getToken()、systemService.getApp() 等基础方法,没有已核实的 informat.agent.createSession() 一类现成网站 SDK。下文使用现有 RPC 获取上下文,再直接调用工作台 HTTP 接口;如需封装 SDK,应保留相同协议和行为。

2. 用户如何配置自己的应用智能体 ​

以“应用内知识问答与业务助手”为例:

  1. 在目标应用中新建或选择网站模块,设置聊天首页,并上传 HTML、CSS、JavaScript 资源。已有网站可增加“智能助手”页面或侧栏。
  2. 在团队中配置可用模型,并向目标用户授予相应 AI 使用权限。仅能进入应用,不代表一定可以使用工作台会话引擎;创建会话还会检查团队授权等条件。
  3. 准备允许使用的技能、专家、知识库,并确认这些资源已向目标用户开放。
  4. 网站页面通过 RPC 读取当前应用,把该应用作为会话的关联应用。需要应用内专用助手时,页面固定应用入口,不提供任意切换应用的操作。
  5. 用户首次发送问题时创建 type=default 的会话,并传当前应用 appId、所选权限和模型。
  6. 每次发送问题都按工作台格式提交本轮选择的技能、专家、知识库及附件。
  7. 发布网站所属应用,使用普通业务账号验证聊天、历史恢复和权限边界。

提示词示例:

你是本应用的业务助手。用户提到“当前应用”时,以当前关联应用为准。回答业务问题时优先使用本次选定的知识库;需要查询业务数据时使用当前用户有权访问的数据。资料不足时说明缺少什么。执行数据修改前清楚说明修改对象和内容。

这类文字用于定义助手职责。实际访问权限由服务端校验,不能只靠提示词控制。

3. 网站页面如何取得登录态 ​

3.1 从应用内部打开网站 ​

从织信应用内部打开网站模块时,可以通过平台提供的 RPC 脚本使用 systemService 和 appService,获取当前登录态和应用信息。

加载与当前部署版本匹配的 postmessage-rpc.js、rpc.js,等待 rpc-ready,再读取上下文。不要直接访问父页面 Vue 实例,也不要猜测 localStorage 中 token 的键名。

html
<!-- 以下路径适用于平台静态资源暴露在站点根目录的部署;
     使用子路径部署时,应配置为该部署实际的资源地址。 -->
<script src="/js/postmessage-rpc.js"></script>
<script src="/js/rpc.js"></script>
<script src="./main.js"></script>
javascript
/**
 * 等待平台父页面完成网站 RPC 初始化。
 * 仅适用于在织信应用内部以网站模块方式打开的页面。
 */
function waitForPlatformRpc() {
    return new Promise(resolve => eventService.onceEvent('rpc-ready', resolve));
}

/**
 * 读取当前用户登录凭据、应用和平台服务地址。
 * token 只保存在运行时内存中,禁止写入控制台、静态文件或聊天正文。
 */
async function loadAgentContext() {
    await waitForPlatformRpc();
    const [token, app, serverUrl] = await Promise.all([
        systemService.getToken(),
        systemService.getApp(),
        systemService.getServerUrl()
    ]);
    if (!token || !app || !app.id) {
        throw new Error('请从已登录的织信应用内打开智能助手页面');
    }
    return { token, app, serverUrl };
}

网站资源的典型地址为 /web{dbIndex}/website/{appId}/{websiteId}/。从页面路径可以识别当前网站的数据库路由前缀;不要把所有环境固定成 web0。

serverUrl 是平台服务根地址。存在网关前缀、独立资源域或反向代理的环境,应显式配置并核实会话服务根地址,不能仅使用 iframe 所在域名推断。

3.2 直接打开网站 URL 或嵌入外部系统 ​

独立打开网站地址时,不一定有父页面 RPC,也不一定具有有效登录态。本文的 RPC 初始化代码不能原样用于这种入口。

如需外部系统使用,必须另外完成登录集成、服务地址和跨域配置,再以合法的当前用户 token 调用同一套会话接口。不能把管理员 token、模型 API Key 或 X-INFORMAT-AGENT-TOKEN 放进网站资源。

工作台 HTTP 接口使用的是用户登录 token;X-INFORMAT-AGENT-TOKEN 属于智能体内部工具回调凭据,两者用途不同。

4. 服务地址和会话接口 ​

会话接口的基础路径为 /web{dbIndex}/informatclaw,其中 {dbIndex} 使用当前部署的数据库路由编号。存在网关前缀时,应使用管理员提供的实际访问地址。

下文用 BASE 表示已确认的完整服务地址,例如 https://informat.example.com/web0/informatclaw。

所有下列请求均带 ?token=<当前用户登录token>;已有查询参数时使用 &token=...,token 必须经过 URL 编码。

功能方法BASE 后的路径请求或说明
创建会话POST/session?type=default&aiModelKey=<模型key>JSON 创建参数;返回 {sessionId}
我的会话GET/sessions?typeList=default&appId=<应用ID>&pageIndex=1&pageSize=20返回 {list,count,pageIndex,pageSize}
历史消息GET/session/{id}/messages?pageIndex=1&pageSize=50返回分页消息及总数
实时输出GET/session/{id}/streamtext/event-stream,使用 EventSource
发送消息POST/session/{id}/inputJSON 消息体;接受成功返回 {ok:true}
会话状态GET/session/{id}/status用于恢复运行状态和用量等信息;按当前返回结构解析
停止生成POST/session/{id}/stop停止当前执行,保留会话
删除会话POST/session/{id}/delete关闭并删除会话,用户明确操作后调用
置顶POST/session/{id}/pin更新列表顺序
取消置顶POST/session/{id}/unpin更新列表顺序
重命名POST/session/{id}/updateThreadName{ "name": "售后问题分析" }
切换权限POST/session/{id}/permissionMode{ "permissionMode": "readonly" }
切换关联应用POST/session/{id}/app{ "appId": "<应用ID>" }
删除指定消息POST/messages/delete消息数字 ID 数组,如 [101,102]

普通会话使用 owner 接口。/shared/session/{id}/messages、stream、status 用于经授权的管理只读场景,不可用来绕过会话归属限制。

4.1 首次创建参数 ​

http
POST BASE/session?type=default&aiModelKey=<模型key>&token=<用户token>
Content-Type: application/json
json
{
  "appId": "<当前应用ID>",
  "permissionMode": "readonly"
}

可选创建参数包括 appName、appDefineId、expertId、expertTeamId、skillList、kbFolderList、appKbList,资源字段应使用与本轮输入相同的序列化约定。按实际功能传入,不要把示例占位符发送到服务端。

网站普通聊天沿用工作台的 type=default。codestudio、createApp 等是其他业务场景,不能因为聊天界面位于网站模块就使用 codestudio。

模型通过查询参数 aiModelKey 指定,传模型的 key,不是模型记录 id。工作台首次发送后锁定本会话模型;用户需要切换模型时新建会话。

“新建会话”按钮先创建前端空白状态,用户真正发送第一条消息时才调用创建接口,避免留下大量空会话。

4.2 每轮输入参数 ​

json
{
  "message": "请根据本次选择的知识库回答报销规则",
  "skillList": "<技能key1>,<技能key2>",
  "expertId": "<专家ID>",
  "kbFolderList": "[\"<团队知识库ID>\"]"
}
字段格式含义
message字符串正文,含工作台格式的应用上下文和附件引用
skillList逗号分隔的字符串多个技能使用 key,不能传技能对象数组
expertId字符串所选专家 ID
expertTeamId字符串所选专家团队 ID;需该部署启用功能
kbFolderListJSON 数组的字符串团队知识库 ID 列表,例如 JSON.stringify(ids)
appKbList字符串化资源列表应用知识库选择;当前后端按关联应用解析,集成时复用现有应用知识库处理逻辑
insertTestData字符串特定业务入口使用的选项;普通网站聊天不需要传

输入字段按字符串格式提交,因此不要直接传 kbFolderList: ["id"]。技能、知识库可以多选;专家与专家团队应按页面支持的选择规则提交,避免同时传相互冲突的选择。

清空专家与“不改变专家”不是同一语义。工作台清空选择时会使用 expertId: "";没有该字段可能继续沿用已有状态。知识库的未传、空列表和专家默认知识库也有不同处理,必须复用选择状态的构造逻辑,并验证清空后的实际范围。

技能、专家和知识库必须通过上述结构化字段提交,不能只把显示名称拼进提示词来模拟选择。

4.3 首轮应用上下文 ​

工作台不仅设置会话 appId,还会在新会话第一条消息前注入以下上下文。要模仿工作台,网站也应保留这一行为:

text
【当前关联应用上下文】
用户已在创建会话前选择关联应用:<应用名称>
appId: <当前应用ID>
appDefineId: <应用定义ID,存在时填写>
当用户说“当前系统”“这个系统”“当前应用”“有哪些表/页面/字段”等未明确指定范围的问题时,默认只针对上述关联应用处理;不要先遍历全公司或所有应用,除非用户明确要求查看所有应用。
【用户原始问题】
<用户输入>

后续轮次不用重复加入这段首轮上下文。聊天气泡可以只展示用户原始问题,读取历史时将上下文说明与用户正文分开展示。

appId 是关联上下文,不应被理解为“服务端保证只能访问此应用”的独立安全沙箱。网站隐藏应用切换入口也不能替代服务端权限控制;若业务要求严格禁止跨应用访问,需要另行核实或增强服务端范围约束。

5. SSE 输出必须按工作台协议处理 ​

创建成功后订阅:

javascript
const source = new EventSource(
    `${BASE}/session/${encodeURIComponent(sessionId)}/stream?token=${encodeURIComponent(token)}`
);

工作台服务在创建成功后建立连接,随后提交 /input。网站可以等待连接 open 再发送,以减少首轮连接建立期间的展示空窗;恢复时仍需读取历史和状态。

5.1 原始事件与界面事件是两层协议 ​

SSE 的 message 通道承载原始 JSON,其中常见类型是:

原始类型网站需要执行的操作
system / init展示初始化、模型和能力等状态
stream_event处理消息开始和文本增量,例如 event.delta.type=text_delta
assistant解析 message.content 中的文本、工具调用等内容块
user 中的 tool_result回填对应工具调用结果,展示成功或失败
result处理执行结果、耗时、用量和错误标记
replay_start、replay_end处理当前轮事件回放,与历史消息协调,避免重复
done一轮结束,恢复输入状态
error展示业务错误并解除等待状态
expert_team_runtime专家团队运行进度,部署启用时处理

此外还要监听 SSE 命名事件 done 和 error。同一轮可能同时出现 message 中的 type=done 和命名 done,结束处理必须幂等。

不要把原始 assistant 当成可直接追加的纯文本。文本增量和最终快照可能表示同一段输出,如果两者都直接追加,会出现答案重复。

5.2 将事件呈现为聊天内容 ​

网站需要根据事件类型呈现文本、执行状态、工具调用及结果、文件链接和用户交互卡片。文本增量用于更新当前回答,完整消息用于校准最终内容,结束事件用于恢复输入状态。

对于需要用户回答的交互,将用户答案作为后续消息提交。不要自行假设存在新的“工具确认 HTTP 接口”。文件和链接应单独展示,错误应显示为明确的失败状态。

下面示例中的 onRawEvent 是网站自行处理事件的位置,需要根据第 5.1 节实现解析、去重和页面更新。

6. 网站侧最小协议适配示例 ​

下面的类演示创建、SSE、输入和停止的调用方式。要达到完整工作台体验,还需按第 5、8、9 节实现事件解析、历史恢复、能力选择及附件上传。它不是已经发布的官方 SDK。

javascript
/**
 * 网站页面中的工作台会话协议适配器。
 * 每个实例管理一个 sessionId 和一条 SSE 连接。
 * baseUrl 由宿主提供,已包含正确的 web{dbIndex} 路由前缀。
 */
class WorkbenchAgentClient {
    /**
     * @param {Object} options 接入配置。
     * @param {string} options.baseUrl 会话服务根地址。
     * @param {string} options.token 当前登录用户 token,只保存在内存。
     * @param {Function} options.onRawEvent 原始 JSON 事件回调,由网站解析并更新页面。
     * @param {Function} options.onError 业务及连接错误回调。
     * @param {Function} options.onDone 本轮结束回调,宿主应幂等恢复输入状态。
     */
    constructor({ baseUrl, token, onRawEvent, onError, onDone }) {
        this.baseUrl = baseUrl.replace(/\/$/, '');
        this.token = token;
        this.onRawEvent = onRawEvent;
        this.onError = onError;
        this.onDone = onDone;
        this.sessionId = null;
        this.source = null;
    }

    /** 为同一服务下的请求加上当前用户 token,保留已有查询参数。 */
    url(path, query = {}) {
        const url = new URL(this.baseUrl + path);
        Object.entries(query).forEach(([key, value]) => {
            if (value != null && value !== '') url.searchParams.set(key, String(value));
        });
        url.searchParams.set('token', this.token);
        return url.toString();
    }

    /**
     * 执行 JSON 请求,同时检查 HTTP 错误和 HTTP 200 下的业务失败。
     * 不记录完整 URL,以免把查询参数中的 token 写入日志。
     */
    async request(path, { method = 'GET', query = {}, body } = {}) {
        const response = await fetch(this.url(path, query), {
            method,
            headers: body === undefined ? {} : { 'Content-Type': 'application/json' },
            body: body === undefined ? undefined : JSON.stringify(body)
        });
        if (!response.ok) throw new Error(`会话请求失败,HTTP ${response.status}`);
        const data = await response.json();
        if (data && data.ok === false) throw new Error(data.message || '会话请求被拒绝');
        return data;
    }

    /**
     * 首条消息发送前创建会话;后续调用返回已有 ID。
     * 外层页面需要禁用重复提交,避免并发创建两个会话。
     */
    async create({ appId, aiModelKey, permissionMode = 'readonly', ...capabilities }) {
        if (this.sessionId) return this.sessionId;
        const result = await this.request('/session', {
            method: 'POST',
            query: { type: 'default', aiModelKey },
            body: { appId, permissionMode, ...capabilities }
        });
        if (!result.sessionId) throw new Error('创建会话未返回 sessionId');
        this.sessionId = result.sessionId;
        console.info('[website-agent] session-created', { sessionId: this.sessionId, appId });
        return this.sessionId;
    }

    /**
     * 建立 SSE 并等待连接就绪。连接中断时由 EventSource 自动重连。
     * 正式实现还需接入工作台的状态同步、重连上限和历史去重策略。
     */
    connect() {
        if (!this.sessionId) return Promise.reject(new Error('请先创建或恢复会话'));
        this.detach();
        return new Promise((resolve, reject) => {
            let opened = false;
            const source = new EventSource(this.url(`/session/${this.sessionId}/stream`));
            this.source = source;
            const timer = setTimeout(() => {
                if (!opened) {
                    source.close();
                    if (this.source === source) this.source = null;
                    reject(new Error('会话连接超时,请重试'));
                }
            }, 15000);
            source.onopen = () => {
                opened = true;
                clearTimeout(timer);
                resolve();
            };
            source.onmessage = event => {
                let raw;
                try { raw = JSON.parse(event.data); }
                catch (error) {
                    this.onError?.(new Error('会话事件格式异常'));
                    return;
                }
                this.onRawEvent?.(raw);
                if (raw.type === 'done') this.onDone?.();
                if (raw.type === 'error') this.onError?.(new Error(raw.message || '智能体执行失败'));
            };
            source.addEventListener('done', () => this.onDone?.());
            source.addEventListener('error', event => {
                if (event.data) {
                    this.onError?.(new Error(event.data));
                } else if (opened) {
                    this.onError?.(new Error('实时连接中断,正在尝试重连'));
                }
            });
        });
    }

    /**
     * 提交本轮正文和能力参数。返回只表示输入被接受,最终回答通过 SSE 接收。
     * 正文中的首轮应用上下文、附件引用由上层按工作台规则生成。
     */
    async send(message, capabilities = {}) {
        if (!this.sessionId) throw new Error('请先创建或恢复会话');
        return this.request(`/session/${this.sessionId}/input`, {
            method: 'POST', body: { ...capabilities, message }
        });
    }

    /** 停止当前生成,保留会话和已经保存的历史。 */
    async stop() {
        if (!this.sessionId) return;
        return this.request(`/session/${this.sessionId}/stop`, { method: 'POST' });
    }

    /** 页面退出或切换会话时仅断开连接,不向服务端删除会话。 */
    detach() {
        this.source?.close();
        this.source = null;
    }
}

调用顺序示例:

javascript
// BASE 必须由当前部署和网站运行上下文正确解析。
// handleRawEvent 根据事件类型更新聊天内容,不能把原始 JSON 当作最终答案。
const client = new WorkbenchAgentClient({
    baseUrl: BASE,
    token: context.token,
    onRawEvent: handleRawEvent,
    onDone: finishCurrentRound,
    onError: showAgentError
});

await client.create({
    appId: context.app.id,
    aiModelKey: selectedModel.key,
    permissionMode: 'readonly'
});
await client.connect();
await client.send(firstMessageWithAppContext, {
    skillList: selectedSkillKeys.join(','),
    kbFolderList: JSON.stringify(selectedKnowledgeBaseIds)
});

BASE、context、selectedModel、选择列表以及回调均由实际页面提供。普通续聊使用 client.send(),不要再次创建会话。

7. 配置可选模型与能力 ​

页面需要提供与当前用户权限一致的模型、技能、专家和知识库选项。接入前由管理员准备以下配置:

选择项网站需要的数据提交时使用的值
模型名称、模型 key、可用状态aiModelKey 使用模型 key
技能名称、技能 key、可用状态skillList 使用技能 key 列表
专家名称、专家 ID、职责说明expertId 使用专家 ID
专家团队名称、团队 ID、可用状态expertTeamId 使用团队 ID
团队知识库名称、知识库 ID、说明kbFolderList 使用知识库 ID 列表

可以先为网站配置一组已授权的固定选项,贯通完整会话。如果需要动态展示可用资源,应使用当前部署提供的资源查询接口;具体访问方式由管理员或交付人员提供,不要自行猜测接口路径。

显示名称用于用户选择,提交时必须使用对应的 key 或 ID。资源配置不能替代服务端授权;资源停用或用户失去权限时,页面应显示实际返回的错误并允许重新选择。

8. 附件与工作台保持一致 ​

工作台先上传附件,再将下载 URL 写入 message。不是直接向 /input 发送文件二进制,也不是传一个未经后端读取的 files 数组。

上传请求:

text
POST <服务根地址>/web{dbIndex}/file/company_upload
Content-Type: multipart/form-data,由浏览器自动生成 boundary
表单字段:file、token
成功响应中读取 data.path
javascript
/** 上传附件,读取工作台上传响应中的存储路径。 */
async function uploadAgentFile(uploadUrl, token, file) {
    const form = new FormData();
    form.append('file', file, file.name);
    form.append('token', token);
    const response = await fetch(uploadUrl, { method: 'POST', body: form });
    if (!response.ok) throw new Error(`附件上传失败,HTTP ${response.status}`);
    const result = await response.json();
    if (!result.data?.path) throw new Error('附件上传未返回文件路径');
    return result.data.path;
}

附件下载地址格式为 <服务根地址>/web0/file/company_download/<filePath>,其中 filePath 是上传成功返回的路径。附件消息尾部为:

text
请分析这份材料,"attachmentList":<完整下载URL1>,<完整下载URL2>

正文和附件标记之间使用中文逗号,标记后的冒号是中文冒号,多个 URL 用英文逗号连接。构造消息时保留 "attachmentList": 的约定。上传使用当前 dbIndex,下载例子使用现有工作台的 /web0/ 约定,配置时应分别确认上传与下载地址。

文件未上传成功前禁止发送。页面还应提供图片和附件预览、移除附件以及上传失败提示。展示附件标题时使用安全的文本渲染。

9. 历史记录、恢复与生命周期 ​

  1. 页面初始化查询自己的 typeList=default 会话,应用专用页面增加 appId 筛选。
  2. 用户选择会话后,读取历史消息第一页,并支持继续读取更早消息。工作台默认每页 50 条,不能只读第一页就当作完整记录。
  3. 解析历史消息中的用户正文、附件、能力选择和工具执行记录,并转换为页面中的聊天内容。
  4. 读取 /status,恢复运行状态及当前模型、权限等实际信息,再连接该 sessionId 的 SSE。
  5. 将历史消息与 SSE 回放协调,处理 replay_start/replay_end、重复快照及消息 ID,避免恢复后消息重复。
  6. 切换会话时取消旧的历史加载,断开旧 SSE 连接,防止迟到响应写入新会话。
  7. 页面卸载只断开连接。用户点击“停止”才调用 /stop,用户点击“删除会话”才调用 /delete。
  8. 会话不存在或没有权限时显示明确状态;不要静默创建空会话覆盖旧会话缓存。

本地缓存会话 ID 时使用用户、团队、应用、网站模块共同组成缓存键,避免同一浏览器切换账号后串会话。缓存的是索引信息,服务端会话归属检查始终是最终依据。

appId 筛选用于按应用查看会话,不代表同一应用下的多个网站助手已相互隔离。若需要网站级隔离,应在接入前与管理员确认服务端支持的隔离方案;仅用浏览器缓存区分不构成服务端隔离。

10. 权限与错误处理 ​

工作台当前会话页提供三种权限模式:

显示名称接口值用途
只读模式readonly对话、上传文件、外网访问等允许能力
数据模式dataAssistant在授权范围内读写应用数据
完全访问权限adminAssistant在授权范围内进行管理操作

普通会话页面使用上表中的权限模式,不应混入设计器专用权限选项。

权限模式限定本会话能力,不会扩大用户已有权限。新会话把选择写入创建参数;已存在会话通过 /permissionMode 更新,并采用服务端返回的规范化模式。正在生成时应按工作台行为禁用切换。

实现时必须处理:

  • HTTP 非 2xx:结束等待,显示请求失败。
  • HTTP 200 但 {ok:false,code,message}:按业务失败处理,不能继续一直显示“正在思考”。
  • SSE 命名 error 带 data:显示服务端错误。
  • SSE 连接错误没有 data:按连接中断处理,重连后同步状态和历史,不能把它当作最终模型回答。
  • 模型不可用、团队未授权、额度不足、技能或专家无权限:保留用户草稿,提示实际失败原因。
  • 删除、停止、断开连接的语义不同,不能在页面销毁时误删会话。

记录 sessionId、应用 ID、请求操作、HTTP 状态、连接状态、完成和停止等关键日志;不要记录 token、完整带 token 的 URL、模型密钥或全部上传内容。模型输出的 Markdown、链接和 HTML 应经过安全渲染处理,避免直接执行输出中的脚本。

11. 完整聊天页面需要提供的功能 ​

除基本问答外,与工作台一致的页面还需要提供以下能力:

  • 会话列表:新建、选择、置顶、重命名、删除,以及分页加载。
  • 会话设置:模型、关联应用和权限模式。
  • 能力选择:技能、专家、专家团队及知识库,支持查看与清空选择。
  • 消息展示:流式文本、工具执行状态、文件链接和交互卡片。
  • 附件操作:上传、预览、移除及失败提示。
  • 生命周期:停止生成、切换会话、历史恢复和断线恢复。
  • 会话导出:导出用户可见的完整内容,并保留必要的附件引用。

如需提供“核验会话”,应另行接入当前部署支持的核验服务,展示报告、证据和反馈。核验不是 /input 的普通参数,也不能仅通过发送一句“请核验”替代。

网站页面自行实现布局和事件处理,按本文协议调用会话服务。接入示例仅覆盖通信基础,完整功能需要结合实际需求开发和验收。

12. 发布前验收清单 ​

完成网站集成后,使用普通业务账号逐项验收。工作台功能可作为对照基线,网站中的同名入口应具备相同的调用语义。

验收项应达到的结果
会话列表显示当前账号自己的历史会话,并正确筛选当前应用
新会话与首轮输入首次发送才创建会话,列表出现新会话并收到答案
多轮上下文沿用同一会话,后续问题能引用上一轮信息
执行过程与完成状态展示初始化、工具执行和结果,完成后恢复输入
技能选择多选、清空和本轮参数准确生效
知识库问答使用所选知识库并提供资料依据,清空后范围符合预期
专家与专家团队正确应用所选身份、职责和资源范围;未启用的功能不展示
权限切换三种模式按用户授权生效,不能通过前端参数扩大权限
模型选择与锁定首轮使用所选模型,之后锁定;更换模型需新建会话
关联应用首轮上下文正确,切换后按服务端实际范围处理
附件与图片上传、解析、预览、移除、下载和失败提示正确
停止与运行中输入停止后可继续;运行中输入行为与工作台一致
历史与断线恢复刷新、切换、重连后记录完整且不重复
会话管理置顶、取消置顶、重命名和删除仅作用于指定会话
导出与会话核验内容完整,核验报告、证据和反馈入口按权限工作
数据与管理操作操作对象正确,用户权限有效,关键过程可追踪
登录失效与额度不足解除等待状态,保留草稿并显示明确原因
多账号与多网站会话索引不串用,服务端归属检查有效

建议的首轮验收

先使用只读模式,依次验证普通问答、多轮上下文、所选知识库问答和专家职责。随后验证附件、恢复和会话管理,最后再在测试应用中验证数据与管理操作。