AI 客服 CLI
供客户、内部人员与 Agent 调用的 AI 客服命令行工具。所有输出默认为 JSON 格式,便于程序解析。
安装
通过 npm 全局安装(推荐)
npm install -g @bty/customer-service-cli
安装后即可直接使用 cs-cli 命令。
从源码构建
pnpm install
pnpm build
构建产物位于 dist/bin.js,可通过 cs-cli 命令调用。
源码入口与多行配置
推荐在 packages/customer-service-cli 目录用 pnpm exec tsx src/bin.ts <args> 跑源码;生产配置写入须先取得明确授权,备份目标字段,写后回读并逐字核对。多行 SA 使用 UTF-8 文件(--situation-file / --action-file),Agent 补丁使用 --data @patch.json,文件读取保留 CRLF、末尾换行和字面反斜杠。
仓库的 pnpm --filter @bty/customer-service-cli --silent dev <args> 也保留真实换行。它通过本包启动器解码 pnpm 9 的原始 JSON 参数,并用无 shell 的 Node/tsx 运行 CLI,避免 pnpm 9 把 LF 变成字面 \n 或展开 $() 等内容;支持 macOS/Linux 的 POSIX shell + pnpm 9(仓库固定 9.15.4)。Windows、npm/yarn、其他 pnpm 大版本或不能解析的生命周期参数会停止执行,请改用上述 pnpm exec 入口。不要删掉 package.json 中 dev 脚本末尾的 #。
默认 API 地址
未传 --env 或使用 --env prod 时可使用以下内置地址;--env dev 需要先配置该环境的服务地址:
| 服务 | 默认地址 |
|---|---|
| 客服 API | https://customer-servhub-api.betteryeah.com |
| Dashboard 只读 API | 客服 API 地址追加 /observability |
| AI API | https://ai-api.betteryeah.com |
| Customer Agent | https://customer-agent.bantouyan.com |
| 任务中心(learning-center) | https://learning-center.betteryeah.com;--env dev 内置 https://dev-learning-center.betteryeah.com,无需配置 |
| Langfuse | http://192.168.40.10:3000 |
AI API 同时服务于登录认证(
auth login/auth whoami),不再区分独立的 "认证 API" 字段。
如需覆盖,可通过 cs-cli config set 修改:
cs-cli config set --cs-api https://your-api.example.com
Dashboard 命令会自动请求该地址下的 /observability/v1/dashboard/**。
API 地址优先级
未传 --env 时(等同线上,见下方「同时登录 dev 与线上」),每个 API 地址的读取顺序为 环境变量 > config.json > 内置默认值。环境变量为 undefined 或空字符串 "" 都视为未设置,继续向下 fallback。显式环境只读对应环境的配置;prod 可使用内置地址,dev 缺配置会报错,避免请求落到生产。
| 环境变量 | 覆盖字段 | 默认值 |
|---|---|---|
CS_CS_API_URL | customerServiceApiUrl | https://customer-servhub-api.betteryeah.com |
CS_AI_API_URL | aiApiUrl(同时服务 auth 调用) | https://ai-api.betteryeah.com |
CS_CUSTOMER_AGENT_URL | customerAgentApiUrl | https://customer-agent.bantouyan.com |
CS_CS_ADMIN_URL | csAdminUrl | https://customer-service-admin.betteryeah.com |
CS_LEARNING_CENTER_URL | learningCenterUrl | https://learning-center.betteryeah.com |
快速开始
# 登录
cs-cli auth login --phone 13800000000 --password yourpassword
# 查看当前用户
cs-cli auth whoami
# 设置默认工作空间
cs-cli config set-workspace <workspace_id>
# 列出 Agent
cs-cli agent list
同时登录 dev 与线上
全局 --env dev|prod 选择本次命令的 API 地址、登录态和默认工作空间,放在一级命令前。不传 --env 就是线上,与 --env prod 共用同一份配置和登录态;只有 dev 必须写 --env dev。每个环境登录一次即可交替执行,无需反复改配置:
# 一次性配置 dev;替换为部署提供的真实地址
cs-cli --env dev config set --cs-api <dev客服API地址> --ai-api <dev登录及AI地址>
# 使用 Customer Agent / cs-admin 命令时再配置相应服务
cs-cli --env dev config set --agent-api <devCustomerAgent地址> --admin-api <dev后台地址>
cs-cli --env dev auth login --phone 13800000000 --password yourpassword
cs-cli --env prod auth login --phone 13800000000 --password yourpassword
cs-cli --env dev config set-workspace <dev工作空间ID> --global
cs-cli --env prod config set-workspace <线上工作空间ID> --global
cs-cli --env prod agent list
cs-cli --env dev agent list
cs-cli --env dev config get
cs-cli --env prod auth whoami
# 只退出 dev,prod 登录态仍可使用
cs-cli --env dev auth logout
- 全局配置和凭据分别存入
~/.cs-cli/environments/dev/与~/.cs-cli/environments/prod/。CS_CLI_HOME只替换根目录;两个环境仍位于其environments/子目录。凭据文件权限为0600。 - 登出、过期和 401 只清理发起请求的环境;未登录时提示带同一
--env的登录命令。Dashboard 地址仍从该环境的客服 API 派生。 - 未传
--env按整个目录二选一,不拼两处的文件:environments/prod/目录存在(用过--env prod就有)就整体用 prod;没有 prod 目录、根目录有旧单环境文件时整体用根目录(与升级前一致,不用重登);两处都没有时用 prod。读写、401 / 过期清理都在选中的那个目录里;清掉 prod 凭据后仍是 prod(提示登录),不会落回根目录。有了 prod 目录后根目录旧config.json里的自定义地址、默认工作空间不再生效,要在 prod 里重新设置。 - 未传
--env的auth logout两处都清,根目录旧登录态一并清掉。显式--env prod只用 prod 目录、不看根目录,dev 永远不借用根目录或 prod。 - 通用
CS_AUTH、CS_WORKSPACE_ID、CS_AGENT_ID、CS_CS_API_URL、CS_AI_API_URL、CS_CUSTOMER_AGENT_URL、CS_CS_ADMIN_URL、CS_LEARNING_CENTER_URL没有环境归属,非空时与显式--env混用会报错,且不发请求。sandbox / CI 继续不传--env使用原注入方式;多环境调用先清除这些变量并配置各自环境。 config get返回当前environment(未传时为 prod)、实际使用的配置目录configDir及全局、本地配置。
Langfuse 通过 debug trace --langfuse-env dev|prod 单独选择;默认跟随全局 API 环境,未选 API 环境时默认 prod。旧的 debug trace <id> --env dev 仍只选择 Langfuse,API 环境保持原配置;若要同时选择 API 环境,必须把全局 --env 放在一级命令前。旧参数与 --langfuse-env 值冲突时拒绝执行。
cs-cli --env dev debug trace <trace_id>
cs-cli --env prod debug trace <trace_id> --langfuse-env dev
全局选项
| 选项 | 说明 | 默认值 |
|---|---|---|
--table | 以表格形式输出(默认 JSON) | false |
--env <dev|prod> | 本次 API 环境,独立配置与登录态 | prod(线上) |
--workspace <id> | 覆盖默认工作空间 ID | 配置文件中的值 |
--request-timeout <ms> | 单个 HTTP 请求超时(毫秒);--timeout 是相关子命令的轮询窗口 | 60000 |
本地配置 (.cs-cli.json)
支持在项目目录下放置 .cs-cli.json 文件,为不同项目配置不同的工作空间。
工作空间优先级
| 优先级 | 来源 | 说明 |
|---|---|---|
| 0 | CS_WORKSPACE_ID 环境变量 | env lock,最高优先级,override 硬失败(见下方"环境变量锁定") |
| 1 | --workspace <id> 参数 | 命令行临时覆盖 |
| 2 | .cs-cli.json (本地配置) | 当前目录或祖先目录 |
| 3 | ~/.cs-cli/environments/<env>/config.json | 全局默认配置(未传 --env 见上方「同时登录 dev 与线上」的目录规则,可能是 prod 或根目录旧文件) |
使用方式
# 在项目目录下初始化本地配置
cs-cli config init
# 设置工作空间(自动写入本地 .cs-cli.json)
cs-cli config set-workspace <workspace_id>
# 强制写入全局配置
cs-cli config set-workspace <workspace_id> --global
CLI 从当前目录向上查找 .cs-cli.json,找到第一个即使用其中的 workspaceId。
显式 --env 只读取同一文件的 environments.dev 或 environments.prod;缺该项则使用该环境的全局默认工作空间,不借用旧顶层 workspaceId 或另一环境。本地与全局默认值在查询参数及 HTTP workspace header 中使用同一优先级。config set-workspace 写入所选环境,保留另一环境和旧字段。未传 --env 仍读写旧顶层字段,与升级前一致。
.cs-cli.json 格式:
{
"workspaceId": "ws-abc123",
"workspaceName": "某客户项目"
}
同一目录保存两环境的格式:
{
"environments": {
"dev": { "workspaceId": "ws-dev", "workspaceName": "开发环境" },
"prod": { "workspaceId": "ws-prod", "workspaceName": "线上环境" }
}
}
set-workspace 写入规则
- 当前目录或祖先目录存在
.cs-cli.json→ 写入本地配置 - 不存在
.cs-cli.json→ 写入全局配置 - 使用
--global→ 强制写入全局配置
每次写入后会提示写入的目标路径。
环境变量锁定(sandbox / CI)
当 sandbox、CI 等非交互环境预先注入以下环境变量时,cs-cli 会透明地把 env 作为凭据与上下文来源,并拒绝任何运行时 override(--workspace / --agent / auth login 等),避免下游脚本在上下文被静默切换时产生未定义行为。
| 环境变量 | 作用 |
|---|---|
CS_AUTH | 登录凭据(等同 access token)。存在即视为"已锁定" |
CS_WORKSPACE_ID | 锁定工作空间 ID |
CS_AGENT_ID | 锁定默认 agent ID |
处理逻辑:
- env 优先:只要环境变量有值,cs-cli 就从 env 读取,忽略本地
credentials.json/.cs-cli.json/ 全局配置。 - override 硬失败:锁定后如果再通过
--workspace/--agent/auth login/auth logout/config set-workspace传入不一致的值,cs-cli 立刻报错退出,不会静默覆盖。 - 幂等传值:override 与 env 值完全一致时允许通过(便于脚本显式断言)。
使用示例:
export CS_AUTH="<your-access-token>"
export CS_WORKSPACE_ID="ws-abc123"
export CS_AGENT_ID="agent-xyz"
cs-cli agent list # 直接运行,无需 auth login
cs-cli --workspace ws-other agent list # ❌ 报错:CS_WORKSPACE_ID 已被锁定
要解除锁定,清空对应环境变量即可(unset CS_AUTH CS_WORKSPACE_ID CS_AGENT_ID)。
命令权限
客户与内部人员继续使用各自账号执行 auth login,共用登录体系。CLI 仅维护下表的 27 条内部受限命令,按当前账号的服务端 role_code 检查权限;未命中清单的命令不新增 CLI 角色校验,沿用原有登录与工作空间权限。
| CLI 权限 | 允许的角色 | 命令范围 |
|---|---|---|
| 普通 | 不增加平台角色要求 | 商品、SA、FAQ、知识、会话、调试、看板等业务命令;包括 product feedback get/save/accept/restore/revoke/mode/disable-image/enable-image |
| 内部普通 | DEVELOPER、ADMIN、SYSTEM_ADMIN | channel-metric query/backfill、monitor fields、monitor tickets list/delete、全部 ops-record 与 special-project 子命令、普通 key 的 system-config get |
| 内部高级 | ADMIN、SYSTEM_ADMIN | agent fork |
| 系统管理员 | SYSTEM_ADMIN | agent engine get/set、device list、token-usage summary、monitor agents/workspaces/statistics 与 monitor snapshots hourly/daily/daily-range |
system-config get 的以下四个 key 要求 SYSTEM_ADMIN:installer_package_api_keys、sop_main_engine_config、sop_main_engine_request_config、sop_main_engine_flow_service_config;其他 key 要求内部普通权限。SHOP_MANAGER、ASSISTANT 及未知角色不能执行内部命令。平台角色通过 CLI 检查后,服务端仍会执行原有业务和资源权限校验。
执行内部命令前,CLI 使用当前环境的登录凭据请求客服 API GET /v1/user/profile,不把角色写入凭据文件,也不跨进程缓存。角色无法确认或请求失败时,不执行目标业务命令;仅注入 CS_AUTH 而未设置 workspace 时,也能查询角色。auth、config、帮助和普通命令不增加此请求,auth whoami 仍返回原用户中心身份信息。
仅受限命令的 --help 增加权限标签。角色不足时输出 JSON 错误并以退出码 1 结束;未登录或 Token 失效为 2,网络或服务器错误为 3。本限制作用于本版 CLI;服务端接口与旧版 CLI 的行为未作调整。
本版移除了测试集与节点模板命令组,相关子命令不再注册;Sol 的 debug replay / debug overlay 流程保留。
命令速查表
认证 (auth)
| 命令 | 说明 |
|---|---|
auth login --phone <手机号> --password <密码> | 登录 |
auth logout | 退出登录 |
auth whoami | 查看当前登录用户 |
配置 (config)
| 命令 | 说明 |
|---|---|
config set [--cs-api <url>] [--ai-api <url>] [--agent-api <url>] [--admin-api <url>] [--learning-center <url>] | 设置当前环境的 API 地址 |
config get | 查看当前配置(含全局和本地) |
config init | 在当前目录初始化本地配置 (.cs-cli.json) |
config set-workspace <workspace_id> [--global] | 设置默认工作空间 |
工作空间 (workspace)
| 命令 | 说明 |
|---|---|
workspace list | 列出所有工作空间 |
workspace points-consumes-daily [--start <YYYY-MM-DD>] [--end <YYYY-MM-DD>] | 按天查询工作空间积分消耗(默认最近 30 天) |
workspace points-consumes-daily 需要可用的工作空间上下文(--workspace、本地 .cs-cli.json 或全局 defaultWorkspaceId)。
# 查询最近 30 天(默认)
cs-cli workspace points-consumes-daily
# 指定日期范围(含 start/end)
cs-cli workspace points-consumes-daily --start 2026-04-01 --end 2026-04-23
Agent 管理 (agent)
| 命令 | 说明 |
|---|---|
agent list [--keyword <名称>] [--page N] [--page-size N] [--fields <路径,...>] [--raw] | 列出 Agent 列表;--keyword 按名称模糊搜索;--fields 裁每一条记录;--raw 不遮蔽凭据 |
agent get <config_id> [--fields <路径,...>] [--raw] | 获取 Agent 详情;--fields 只输出指定字段;--raw 不遮蔽凭据 |
| `agent update <config_id> --data <json | @file>` |
agent fork --source-customer-config-id <id> --target-workspace-id <id> [选项] | 复制 Agent;CLI 要求内部高级权限(ADMIN 或 SYSTEM_ADMIN);同空间仍校验当前用户权限,跨空间服务端仍仅允许 SYSTEM_ADMIN |
agent engine get <config_id> | 查看 Agent 独立层引擎版本(顶层 + 设备定向;null 按 classic 跑),需超级管理员(SYSTEM_ADMIN) |
agent engine set <config_id> --to v2|v3|v4 [--device <设备ID>] / --device <设备ID> --clear | 切换引擎版本(写线上);不带 --device 为整体切换并清掉设备定向;返回切换前版本 |
agent list 每条都带完整 customer_config,单页可达数十万 token;只要 id 和名字时用 agent list --keyword <店名> --fields config_id,config_name。--fields 逗号分隔,点号取嵌套(如 customer_config.xxx),路径途经数组时作用到每个元素,不存在的路径直接省略,输出保持原嵌套结构;list 作用于 .data.items 每一条,分页字段保留;返回体没有 items 数组时往 stderr 打警告并对整个返回体裁剪。不带 --fields 时输出除凭据遮蔽外与之前相同。
agent get / agent list 默认按键名遮蔽凭据字段,值替换为 [REDACTED len=N]。规则比 debug trace 窄,只看键名、不扫正文:整键 token / session / authorization(仅字符串值)/ ak / sk / dsn / database_url,或键名(去掉 _、- 并转小写后)以 secret、password、passwd、access_token、refresh_token、api_token、auth_token、security_token、bearer_token、session_token、id_token、session_key、api_key、app_key、access_key、secret_key、private_key、cookie(s)、credential(s) 结尾;命中的数字值也遮(平台 appkey 常是纯数字),布尔、null、空串和空对象 / 数组不遮,值是 JSON 字符串时按同一规则处理其中的键。max_token、keep_session、need_authorization、cookie_rule、password_hint 这类键以及 prompt 正文里的 Cookie: 曲奇 不会被遮。agent update --data 里出现 [REDACTED len=N] 时会在调用接口前拒绝,所以带遮蔽占位的内容不能回传,只传要改的字段。确实需要真实值时加 --raw 关闭遮蔽:输出含明文凭据,不要贴进对话、日志或工单。
agent fork 必须显式指定来源 Agent 配置 ID 和目标工作空间 ID。--copy-product-data、--copy-activity-data 默认开启,可分别用 --no-copy-product-data / --no-copy-activity-data 关闭。--clone-tools 会复制来源 Agent 当前已绑定的全部工具(包括系统工具和自定义工作流工具),默认不复制;多数场景建议开启。--copy-authorized-shop-id 让克隆的工具沿用来源工具的店铺授权 authorized_shop_id,默认清空;仅与 --clone-tools 同用生效,只在用户明确要求全量复制工具时开启。--shop-id 可显式指定目标店铺 ID。
agent engine 读写的是 Agent 独立层的 version(v2=classic / v3=Luna / v4=Sol),这是 sop 收到的 extra.version 的唯一来源;判断引擎不要用 /effective 的合并结果。店铺还要在 sop_main_engine_config 的 internal 路由里(system-config get sop_main_engine_config),版本才会生效。
agent engine get/set、device list 和 token-usage summary 要求超级管理员(SYSTEM_ADMIN)账号。system-config get 按 key 区分权限,见下表;角色不足时应由具备相应权限的账号执行。
系统配置 / 设备(system-config / device)
| 命令 | 说明 |
|---|---|
system-config get <key> | 读一条全局 system_config;普通 key 要求内部普通权限,四个敏感 key 要求 SYSTEM_ADMIN(见「命令权限」) |
device list [--workspace-id <id>] [--channel <渠道>] [--equipment-id <id>] [--page N] [--page-size N] | 需 SYSTEM_ADMIN;分页列出设备,返回的 version 是客户端版本,不是引擎版本 |
场景动作 (sa)
| 命令 | 说明 |
|---|---|
sa list --agent <id> [--intent <意图>] [--first-label <标签>] [--second-label <标签>] | 列出场景动作 |
sa search --agent <id> --keyword <关键词> | 搜索场景动作 |
sa create --agent <id> --first-label <一级标签> --second-label <二级标签> --situation <场景> --action <动作> [--transfer] [--intent <意图>] | 创建场景动作 |
sa update --agent <id> --id <SA_ID> --first-label <一级标签> --second-label <二级标签> --situation <场景> --action <动作> [--transfer] | 更新场景动作 |
sa delete --agent <id> --id <SA_ID> --first-label <一级标签> --second-label <二级标签> | 删除场景动作 |
sa versions --agent <id> --id <SA_ID> | 查看修改记录 |
sa create/update 的场景必须从 --situation <文本> 与 --situation-file <路径> 中选一个,动作必须从 --action <文本> 与 --action-file <路径> 中选一个;两字段均必传,可混用文本与文件。文本参数含字面 \n 且没有真实 CR/LF 时会在调用 API 前拒绝,不会自动替换;有意写入字面 \n 请放入文件。--situation/--action @file 仍是普通文本,不读取文件。sa update 仍为全量更新,标签及转人工等字段需按备份回填。
# 本包目录,示例使用已配置的 dev;仅在确认范围与备份后执行
pnpm exec tsx src/bin.ts --env dev --workspace <workspace_id> sa update \
--agent <agent_id> --id <SA_ID> --first-label <一级标签> --second-label <二级标签> \
--situation-file ./situation.md --action-file ./action.md
工具 (tool)
| 命令 | 说明 |
|---|---|
tool list --agent <id> | 列出该 Agent 配置已绑定的工具(custom + system) |
tool create --agent <id> --name <名称> --key <标识> --source-id <flow_id> [--description <描述>] [--source-type <类型>] [--invocation-mode <模式>] [--input-vars <json>] | 创建绑定工作流(flow)的自定义工具 |
tool update <tool_id> [--name <名称>] [--key <标识>] [--description <描述>] [--source-id <flow_id>] [--invocation-mode <模式>] [--input-vars <json>] | 更新工具(仅透传实际提供的字段) |
tool delete <tool_id> | 删除(软删除)指定工具 |
tool workflow list [--keyword <关键词>] | 搜索可绑定的工作流(flow),取 source_id |
tool workflow detail <flow_id> | 查看工作流入参,辅助填 --input-vars |
tool workflow create --name <名称> --code <code|@file> [--description <描述>] [--input-vars <json|@file>] [--no-publish] [--code-node-name <名称>] [--version-desc <描述>] | 创建 START→CODE→END 骨架工作流,CODE 节点承载工具代码(仅 JavaScript),默认自动发布 |
tool workflow update <flow_id> --code <code|@file> [--no-publish] [--version-desc <描述>] | 只更新工作流唯一 CODE 节点的代码(其它节点原样保留),默认自动发布 |
tool workflow run <flow_id> [--input <json|@file>] | 运行已发布的工作流(HTTP 同步执行),返回 task_id / status / run_result |
tool workflow delete <flow_id> --yes | 硬删除工作流(不可恢复);缺 --yes 拒绝执行 |
tool workflow describe | 输出 CODE 节点(JavaScript)使用文档:入口/变量注入/返回值/内置包/SDK,依据官方文档整理 |
tool 命令组包装 customer-servhub-api 现有 /v1/tool 接口,管理 Agent 的自定义/覆盖工具;CLI 不改变服务端工具表或 sop-engine 的工具执行逻辑。--invocation-mode 取值 must_invoke / on_demand(默认)/ on_demand_async,非法值在发请求前本地报错;tool create --input-vars 接受 JSON 字符串,形如 {"order_id":{"description":"订单号","type":"string","required":true}},对应工作流入参描述;workspace_id 由当前工作空间自动回填。
tool workflow create/update/run/delete 直连 BetterYeah 平台(ai-api)程序化管理工作流本体:create 生成固定 START→CODE→END 三节点骨架并把代码写进 CODE 节点、默认发布,返回 flow_id 供 tool create --source-id 绑定;update 只暴露 CODE 节点代码的修改;run 是 HTTP 同步执行(自动经 GET /v1/workspaces/getKey/{ws} 用登录态换应用态 Access-Key 再调 execute_flow,替代平台画布的 wss 通道),--input 的键对应 START formConfig 的 variableName(默认 {});delete 是硬删除、必须显式 --yes。create/update 发布时可用 --version-desc 附版本描述(平台版本历史里可见,便于区分 CLI 改动;--no-publish 时忽略)。CODE 节点只支持 JavaScript(CommonJS require,不支持 ES Module)。--code / --input-vars 的值以 @ 开头时按文件路径读取(如 @./tool.js)。注意 tool workflow create --input-vars 覆盖的是 START 节点的 formConfig 入参声明,与 tool create --input-vars(工具记录的 input_var_descriptions)是不同字段。tool workflow describe 输出依据官方 JavaScript&Python 节点文档整理的 CODE 节点使用文档(入口 main()、变量注入、返回值约定、内置包、BetterYeah SDK),AI 编写工具代码前应先读。
商品管理 (product)
| 命令 | 说明 |
|---|---|
product list --agent <id> [--keyword <关键词>] [--status <状态>] [--tag <标签>] | 列出商品 |
product get --agent <id> --product-id <商品ID> | 获取商品详情(自动获取 db_id) |
product update --agent <id> --product-id <商品ID> --update <json|@file> | 更新商品信息 |
product shelf --agent <id> --status <上架|下架|预售> (--ids <id,id> | --ids-file <path>) [--concurrency <n>] [--yes] | 批量设置商品状态(上架 / 下架 / 预售,写「商品状态」列,写后回读校验) |
product update-sku --agent <id> (--sku <SKU名称> | --sku-id <id>) --update <json|@file> | 更新 SKU 信息(--sku-id 优先于 --sku) |
product add --agent <id> --data <json|@file> [--source <type>] [--no-identify] | 直接传入结构化商品数据(JSON 数组)异步学习(manual / identify 默认开启) |
product learn --agent <id> --url <URL...> [--source <type>] [--no-identify] | 通过商品 URL 异步学习(manual / identify 默认开启) |
product identify-all --agent <id> | 一键增强学习当前 Agent 下所有待增强商品 |
product sync-taobao --agent <id> [--skip-hash-check] [--sync-type <full|incremental>] | 触发淘宝店铺商品同步 |
product sync-taobao-item --agent <id> --product-id <商品ID> | 触发单个淘宝商品同步 |
product related-knowledge list --agent <id> --product-id <商品ID> | 列出商品详情绑定的 QA / 扩展知识库文件 |
product related-knowledge add --agent <id> --product-id <商品ID> --type <qa|common> (--file <文件名> | --file-id <id> --partition-id <id>) | 给商品追加关联知识库文件 |
product related-knowledge remove --agent <id> --product-id <商品ID> --type <qa|common> --file-id <id> | 移除商品绑定的指定知识库文件 |
product related-knowledge set --agent <id> --product-id <商品ID> --bindings <json|@file> | 覆盖商品绑定的全部知识库文件 |
product supplement list --agent <id> --product-id <商品ID> | 列出商品补充知识条目(含每条的 question / answer / images / videos) |
product supplement add --agent <id> --product-id <商品ID> --question <Q> --answer <A> [--image <path|url>...] [--video <path|url>...] [--dry-run] [--backup <path>] | 新增一条补充知识(Q/A + 可选图片/视频);本地媒体自动上传公开 OSS,URL 直写;read-modify-write 保留旧条目 |
product supplement append-media --agent <id> --product-id <商品ID> --index <n> [--image ...] [--video ...] [--dry-run] [--backup <path>] | 向指定下标条目追加图片/视频,其它条目原样保留、去重合并 |
product update 支持更新的字段包括:卖点、补充知识、tag、参数、轮播图识别结果、商品详情页识别结果 等。--update 接受 JSON 字符串或 @文件路径。
product add 与 product learn 走同一个上传接口(/v1/knowledge/products/upload),区别在于载荷:add 传结构化商品数据 product_items(已抓好的商品详情 JSON 数组),learn 传 product_urls(让后端去抓)。--data 接受 JSON 字符串或 @文件路径;传单个对象会自动包成数组,传 JSON 基本类型(数字 / 字符串等)会直接报错;--source 默认 manual,--no-identify 关闭自动识别。
product learn 提交商品详情页 URL 进入异步学习队列(/v1/knowledge/products/upload),返回 flow_id 和 knowledge_ids。--url 可多值,用空格分隔;--source 默认 manual;传 --no-identify 可关闭自动识别。
product identify-all 对接 POST /v1/knowledge/products/identify/all,会为当前 Agent 一键提交所有“已可用但尚未增强”的商品进入增强学习队列。它不是全量重学;当没有待增强商品时,服务端会返回“暂无需要识图的商品”。
product sync-taobao / product sync-taobao-item 调用 customer-servhub-api 的授权店铺同步接口,要求 --agent 已唯一绑定一个淘宝授权店铺。前者支持 --sync-type full|incremental,默认 full;后者按 product_id 补同步单个淘宝商品。
注意:这两个命令仅对已开通“高级工具”的店铺 Agent 生效。未开通高级工具时,即使 --agent 已绑定淘宝授权店铺,请求也可能在服务端失败。
product related-knowledge 管理商品详情的“关联知识库”文件级绑定。--type qa 对应 FAQ 知识库,--type common 对应扩展知识库。add / remove 会先读取当前绑定,再通过服务端全量替换接口写回;重复添加或移除不存在的文件保持幂等。--file <文件名> 会按当前 Agent 的知识库文件列表做精确匹配;文件名不存在或不唯一时,改用 --file-id + --partition-id 显式模式。
product supplement 维护商品「补充知识」的带图/视频问答(结构为 { question, answer, images: [URL], videos: [URL] }),与前端商品详情页的补充知识上传一致。写入采用 read-modify-write:先 product get 读取并解析当前补充知识,本地合并后再调既有 /v1/knowledge/product/update,绝不用新增项覆盖旧条目。--image / --video 可重复传多个,值可以是本地文件(先经 /v1/upload_sts 取 STS 凭证上传公开 OSS,key 为 /ai/knowledge/supplement/${timestamp}_${filename})或已有 http(s) URL(直写不重复上传)。图片限 image/* ≤ 10MB、视频限 video/* ≤ 200MB,超限或类型不符在发起上传请求前直接失败。--dry-run 只输出将写入的最终 JSON、不落库、不上传;--backup <path> 在写前把当前补充知识快照到本地文件。append-media 仅向 --index 指定的条目追加媒体,去重合并,其它条目原样保留。
单文件上传也可单独用 media upload(见下方「媒体上传」小节),拿到公网 URL 后再作为 --image / --video 的值传入。
# 更新卖点
cs-cli product update --agent <id> --product-id <商品ID> --update '{"卖点":"新卖点内容"}'
# 更新标签
cs-cli product update --agent <id> --product-id <商品ID> --update '{"tag":"[\"春季新品\",\"热卖\"]"}'
# 添加商品补充知识
cs-cli product update --agent <id> --product-id <商品ID> --update '{"补充知识":"[{\"question\":\"问题\",\"answer\":\"回答\"}]"}'
# 更新 SKU 补充知识(按 SKU 名称定位)
cs-cli product update-sku --agent <id> --sku "颜色分类:粉红" --update '{"补充知识":"说明内容"}'
# 更新 SKU 补充知识(按 sku_id 定位,推荐)
cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充知识":"说明内容"}'
# 给商品绑定一个 FAQ 文件
cs-cli product related-knowledge add --agent <id> --product-id <商品ID> --type qa --file "常见问题.xlsx"
# 显式 ID 模式绑定扩展知识文件
cs-cli product related-knowledge add --agent <id> --product-id <商品ID> --type common --file-id 622474 --partition-id 12345 --file-name "售后规则.md"
# 查看商品当前补充知识条目
cs-cli product supplement list --agent <id> --product-id <商品ID>
# 新增一条带图问答(本地图片自动上传,已有 URL 直写)
cs-cli product supplement add --agent <id> --product-id <商品ID> \
--question "尺码怎么选?" --answer "参考尺码表,拍下留言身高体重" \
--image ./size-chart.png --image https://xxx.com/a.png
# 先 dry-run 预览最终写入 JSON,不落库
cs-cli product supplement add --agent <id> --product-id <商品ID> \
--question "Q" --answer "A" --video ./demo.mp4 --dry-run
# 向第 0 条补充知识追加媒体,写前备份
cs-cli product supplement append-media --agent <id> --product-id <商品ID> \
--index 0 --image ./extra.png --backup ./supplement-backup.json
媒体上传 (media)
| 命令 | 说明 |
|---|---|
media upload --file <path> [--type <image|video>] [--path-prefix <prefix>] [--dry-run] | 上传单个本地图片/视频到公开 OSS,返回可访问 URL |
media upload 把单个本地文件上传到公开 OSS(resource_bucket),返回公网 URL,供 product supplement 的 --image / --video 复用。凭证走 GET /v1/upload_sts(返回 AES-CBC 加密,CLI 内解密),上传 key 为 <path-prefix>/<timestamp>_<filename>,--path-prefix 默认 /ai/knowledge/supplement。--type 缺省时按扩展名推断;图片限 image/* ≤ 10MB、视频限 video/* ≤ 200MB,超限/类型不符在发起上传前直接拒绝。传入的 --file 如果本身是 http(s) URL 会被拒绝(无需上传)。--dry-run 仅校验并输出将要上传的信息、不实际上传。
# 上传本地图片,拿到公网 URL
cs-cli media upload --file ./banner.png --type image
# 自定义路径前缀 + 预览(不实际上传)
cs-cli media upload --file ./demo.mp4 --path-prefix /ai/knowledge/supplement --dry-run
活动管理 (activity)
活动 V2(Issue #34)增删改查 + per-tenant V2 总开关。服务端 customer-servhub-api /v1/activity*;契约详情参见 docs/devkit/specs/2026-05-28-activity-v2-api-reference.md。
| 命令 | 说明 |
|---|---|
activity list --agent <id> [--page N] [--page-size N] [--search <text>] | 列出活动(返回 total / v2_activity_enabled / items[]) |
activity by-product --agent <id> --product-id <id> | 按 product_id 反查当前生效活动(仅 enabled、product_scope='all' 必入) |
activity create --data <json|@file> | 创建活动(payload 见 IActivityWritePayload) |
activity update <activity_id> --data <json|@file> | 整体更新活动(products 整组替换,非增量) |
activity set-enabled <activity_id> --enabled <true|false> | 切换单条活动启用状态(仅写 enabled) |
activity delete <activity_id> | 软删活动 + 级联软删关联 |
activity v2-enabled --agent <id> --enabled <true|false> | per-tenant 启停 V2 链路 |
--agent <id>对应服务端customer_agent_config_id(与sa/product命令同口径)。activity create/updatepayload 必填:customer_agent_config_id、activity_name、effective_type、activity_rule;effective_type=time_range要求start_time+end_time;product_scope='specific'(缺省)要求products ≥ 1。- 业务失败(参数非法 / 跨 workspace / 不存在)服务端返 HTTP 200 +
code:400,CLI 转为exit 1并打印INVALID_PAYLOAD: …。
# 列出活动
cs-cli activity list --agent <cfg_id> --search 返现
# 按商品反查
cs-cli activity by-product --agent <cfg_id> --product-id 914494989518
# 创建活动(从文件读 payload)
cs-cli activity create --data @activity.json
# 整体更新
cs-cli activity update 6 --data @activity.json
# 列表行 toggle 启用
cs-cli activity set-enabled 6 --enabled false
# 软删活动
cs-cli activity delete 6
# 为某 agent 启用 V2 链路
cs-cli activity v2-enabled --agent <cfg_id> --enabled true
工单管理 (issue)
| 命令 | 说明 |
|---|---|
issue list [--agent <id>] [--status <状态>] [--priority <优先级>] [--start <日期>] [--end <日期>] | 列出工单 |
issue get <issue_id> | 获取工单详情 |
issue create --title <标题> --content <内容> [--priority <优先级>] [--tags <标签>] | 单条创建工单 |
issue create --file <path> | --stdin [--dry-run] [--concurrency <n>] [--yes] | 批量创建工单(JSON 协议见下) |
| `issue update <issue_id> --data <json | @file>` |
| `issue update --ids <a,b,c> | --ids-file --data <json | @file> [--dry-run] [--concurrency ] [--yes]` |
issue update-owner <issue_id> --owner <user_id|花名> | 单条改派负责人(花名自动解析) |
issue update-owner --ids <a,b,c> | --ids-file <path> --owner <user_id|花名> [--dry-run] [--yes] | 批量改派负责人(走 cs-admin BFF,原子改派 + 自动 Feishu/DingTalk 通知,单批 ≤ 200) |
issue stats [--start <日期>] [--end <日期>] | 各工作空间 Issue 统计(open/closed/total) |
issue comment list <issue_id> | 列出工单评论 |
issue comment add <issue_id> --content <内容> | 添加评论 |
批量写约定(update / update-owner / create --file)
--ids "a,b,c"与--ids-file path.txt(一行一个 id,#注释、空行忽略)互斥;与单条<issue_id>互斥。--owner同时接受user_id(≤ 7 位纯数字)和工程师花名。花名经 cs-admin/api/account-roles解析(KA + SMB 合并去重,5 分钟内存 cache),同名 / 模糊歧义会报错列 candidates。--owner拒绝 11 位手机号(Issue #49,老--owner-phone0.5.0 起硬删)。--dry-run在所有批量子命令上都不会调写接口;create --file --dry-run会真跑user_name → conversation_id反查,以便提前发现NOT_FOUND/AMBIGUOUS。- N ≥ 20 且 stdout 是 TTY 时弹二次确认(输入
yes);非 TTY 必须显式--yes,否则拒收。 - 末尾报告统一 schema:
{version:"1", total, success_count, failed_count, skipped_count, aborted, success_ids[], failed[{id,code,msg}], skipped[{id,reason}]}。退出码:0全成功 /1全失败 /2部分失败 /130SIGINT。 update-owner --ids走 cs-admin BFFPOST /api/workbench/issues/batch-owner单次调用(原子),返回{updated, skipped:[{issueId, reason}], notify[]},与update的 runBatch 报告 schema 不同(保留 BFF 原样)。- 双后端单 token:servhub Bearer JWT 同时通过 cs-admin BFF 鉴权(实测验证),无需额外登录。
issue create --file JSON 协议
文件解析交给上游(LLM/Agent/脚本)整理成下面这份结构化 JSON,CLI 只做校验 + 反查 + 拼装 + 批量创建。
{
"version": "1",
"workspace_id": "ws_xxx", // 顶层,对所有 issue 生效;缺省时落到默认 workspace
"issues": [
{
"title": "客户反馈:A 问题答非所问", // 必填
"priority": "high", // 必填,critical|high|medium|low
"expected": "应该回答 X", // 必填,CLI 把它写进 content 的 ## Expected 段
"description": "上下文描述", // 可选,拼在 expected 前面
"conversation_id": "conv_xxx", // 与 user_name 二选一
"user_name": "张三", // 仅给昵称时,CLI 调 /v1/chat/conversations?user_name= 反查
"tags": ["badcase"], // 可选
"source_type": "manual_review", // 可选
"source_data": {"reviewer": "..."} // 可选
}
]
}
CLI 把 description + expected 拼成 content:
{description}(如有)
## Expected
{expected}
user_name 反查规则(5 分钟内存 cache,key = ${workspaceId}|${userName}):
- 1 条命中 → 用其
conversation_id - 0 条 → 该 issue 标记
NOT_FOUND,整批拒收(防止半批进创建) - 多条 → 该 issue 标记
AMBIGUOUS,提示改传显式conversation_id
priority 不在枚举内、title/expected 缺失等 → 客户端直接拒收(不打任何接口)。
聊天记录 (chat-history)
查询客户导入的聊天记录,用于 SA(场景动作)清洗,非 Agent 自身的对话记录。
| 命令 | 说明 |
|---|---|
chat-history --agent <id> [--page N] [--page-size N] | 查询客户导入的聊天记录 |
FAQ 知识库 (faq)
| 命令 | 说明 |
|---|---|
faq list --agent <id> | 列出 FAQ 文件 |
faq content --agent <id> --file <文件名> [--keyword <词>] [--page-size <n>] [--next-group-id <id>] | 列出文件内答案组(含 answer_group_id / 问题 / 答案) |
faq add --agent <id> --file <文件名> --questions <问题1,问题2> --answers <答案=xxx> | 添加 FAQ 内容 |
faq update --agent <id> --file <文件名> --group-id <id> [--questions <...>] [--answers <...>] [--delete-chunks <id1,id2>] | 更新已有 FAQ 答案组(--questions / --answers / --delete-chunks 至少一个) |
faq delete --agent <id> --file <文件名> --group-id <id> | 删除 FAQ 答案组 |
faq bind-products list --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) | 列出 FAQ 文件绑定的商品 |
faq bind-products add --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...> | 给 FAQ 文件追加绑定商品 |
faq bind-products remove --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...> | 从 FAQ 文件移除绑定商品 |
faq bind-products set --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...> | 覆盖 FAQ 文件绑定的全部商品 |
faq content 走 GET /mebsuta/api/v1/dataset/{knowledge_id}/faq_contents,列出文件内的答案组及其 answer_group_id,是 faq update / faq delete 拿 --group-id 的来源(faq list 只给文件,文件内的 group-id 要靠这条命令查)。支持 --keyword 搜索、--page-size 分页、--next-group-id 游标续翻。
faq update 按 answer_group_id 定位目标组,先读回这组的现值,只覆盖显式传入的字段,再 POST 同一个 faq_contents/save 接口完成字段替换、问题替换与 chunk 级删除。--questions 整组替换问法,没列出的原问法会被删掉。读不到现值、合并后没有问题或没有非空答案时拒绝保存。faq delete 走 DELETE /faq_contents/{group_id} 整组删除。
faq bind-products 固定写入 knowledge_type=qa 的商品绑定关系,适合从 FAQ 文件视角批量维护关联商品。--file 为精确文件名匹配;文件名不唯一时请传 --file-id 和 --partition-id。
扩展知识库 (knowledge)
Agent 关联的通用规则知识库(suffix_type=_common),与 FAQ / 商品知识并列的第三类知识源,支持段落(chunk)级 CRUD,统一走 /mebsuta/api/v1/dataset/{id}/contents/perform-operations。
| 命令 | 说明 |
|---|---|
knowledge list --agent <id> [--page N] [--page-size N] | 列出 Agent 关联的扩展知识库文件 |
knowledge content list --knowledge-id <id> [--page-size N] [--direction up|down] | 列出段落(chunk) |
knowledge content add --knowledge-id <id> --content <text|@file> [--keyword <k...>] [--after <chunk_id>] | 新增段落 |
knowledge content update --knowledge-id <id> --chunk-id <id> [--content <text|@file>] [--keyword <k...>] [--enable | --disable] | 更新段落(四个变更字段至少一个;未指定 --enable / --disable 时自动保留当前启停状态,避免后端 enable 必填校验失败) |
knowledge content delete --knowledge-id <id> --chunk-id <id> | 删除段落 |
knowledge bind-products list --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) | 列出扩展知识文件绑定的商品 |
knowledge bind-products add --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...> | 给扩展知识文件追加绑定商品 |
knowledge bind-products remove --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...> | 从扩展知识文件移除绑定商品 |
knowledge bind-products set --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...> | 覆盖扩展知识文件绑定的全部商品 |
knowledge content add / update 的 --content 支持 @路径 前缀从文件读取纯文本(不是 JSON)。--keyword 为 variadic 选项,空格分隔多个关键词。
knowledge bind-products 固定写入 knowledge_type=common 的商品绑定关系,适合从扩展知识文件视角批量维护关联商品。add / remove 会 read-modify-replace,重复添加或移除不存在的商品保持幂等。
会话管理 (conversation)
| 命令 | 说明 |
|---|---|
conversation list [--agent <id>] [--equipment-id <设备ID>] [--user <用户名>] [--start <日期>] [--end <日期>] [--query-content <文本>] | 搜索会话;--start/--end 按会话 updated_at 过滤(按时段算转人工率用 transfer-human);--query-content 按消息内容搜索,必须同时给起止时间 |
| `conversation records <conversation_id> [--page-size N] [--direction prev | next] [--current-id | --all]` |
conversation context-search (--query <文本> | --user <用户名>) [--limit <1~500>] [--start <时间>] [--end <时间>] | 通过上下文内容或买家用户名模糊搜索对话记录(返回匹配消息详情,时间范围最多 3 天) |
conversation find-order <订单号> --agent <id> --start <时间> --end <时间> | 按订单号反查会话与 record_id;超过 3 天自动按 3 天分段顺序查询,总跨度最多 31 天 |
conversation transfer-human --agent <customer_agent_config_id> --start <时间> --end <时间> [--only-abnormal] | 查询转人工会话及对应转人工消息记录(时间范围最多 7 天,自动 cursor 翻页;--only-abnormal 仅保留异常会话) |
Agent 调试 (debug)
| 命令 | 说明 |
|---|---|
debug ask --agent <id> (--text <消息> | --messages <json|@file>) [--user <用户名>] [--url <图片URL>] [--conversation <会话ID>] [--mock <json|@file>] [--expect <file>] [--data-overlay <json|@file> | --overlay <dir>] [--timeout <秒>] [--poll-interval <毫秒>] | 向 Agent 发送消息并等待回复 |
debug reproduce <record_id> [--agent <id>] [--mock <json|@file>] [--expect <file>] [--data-overlay <json|@file> | --overlay <dir>] [--replace-last <文本>] [--image <URL>] [--timeout <秒>] [--poll-interval <毫秒>] [--dry-run] | 根据 record_id 复现 Agent 回复(自动获取上下文);--replace-last / --image 换掉最后一条买家消息 |
debug data snapshot --agent <id> [--product-id <商品ID...>] | 生成可传给 --data-overlay @file 的 debug 数据覆盖 JSON |
debug record <record_id...> [--out <file.ndjson>] | 获取记录的调试信息(flow_info);多个 id 时最多 3 路并发,--out 按 NDJSON 每行一条写盘(附 engine / flow_engine),stdout 只给汇总;返回中包含 trace_id;Sol 引擎有存档时另有 sol_trace_id 与 sol_trace(服务端 view=diagnosis 的原样结果) |
debug trace <trace_id> [--langfuse-env <dev|prod>] | 根据 Langfuse Trace ID 获取完整 Trace 详情(经所选环境的服务端代理);Sol 轮次另附 sol_trace(服务端 view=diagnosis) |
debug trace (<st-…> | --record <record_id>) [--view summary|prompt|lean|full|otel] [--call <node>] [--out <file>] | Sol 引擎单轮完整 prompt 存档(服务端展开并逐字节校验);默认摘要 |
debug trace --date <YYYY-MM-DD> [--agent <id>] [--out <dir> [--label <l>]... [--node <n>]... [--limit <n>]] | 某天 Sol 存档按 workspace + agent 合并好的调用文件:列条数 / 下载并筛选 |
debug replay export (--trace <id...> | --record <id...> | --conversation <id> [--until <N>]) --out <case.json> | 导出同一会话的 Sol 轮次上下文及商品快照;--conversation 按会话自动收集 Sol trace |
debug replay append --case <case.json> --after <N> --text <text...> [--clock <iso>] --out <new-case.json> | 离线:保留前 N 轮,接一轮自定义买家消息(只能 rollout 跑) |
debug replay open --case <case.json> [--mode rollout|original] [--products <snapshot.json>] [--mocks <mocks.json>] [--products-patch <patch.json>] --out <run.json> | 初始化本地运行文件,默认沿用 dev 状态逐轮执行;可带工具 mock 与商品局部补丁 |
debug replay next --run <run.json> | 执行下一轮并保存完整结果与状态 |
debug replay run --run <run.json> [--until <N>] | 从保存的进度继续,逐轮落盘 |
debug replay fork --run <run.json> --at <N> [--products <snapshot.json>] [--mocks <mocks.json>] [--products-patch <patch.json>] --out <new-run.json> | 保留前 N 轮与对应状态,在新文件继续验证 |
debug replay inspect --run <run.json> [--turn <index>] [--view <view> | --path <pointer>] [--offset <N>] [--limit <N>] [--out <file>] | 只读本地摘要/卡片/工具/原文,按需取证 |
debug replay tools --run <run.json...> [--tool <name...>] [--turn <index>] [--limit <N>] | 只读:多个运行文件的逐工具调用次数、调用率、数据来源与缺录制 |
debug replay compare --baseline <run.json> --candidate <run-b.json> [--expect <expected.json>] [--ab] [--out <file>] | 同输入字段差异与显式断言(含 called / not_called 工具调用断言),区分执行和验证;两边 case.overlay hash 不同时默认拒绝,--ab 声明为配置 A/B |
debug mock init --case <case.json> --out <mocks.json> | 从回放包已录制的工具调用生成 tool-mock/v1 骨架(fill;回放 / sol-local 用) |
debug overlay init (--case <case.json> | --agent <id>) --out <dir> [--base current|incident] [--turn <N>] [--product <id...>] | 只读:把回放基线拉成可编辑的覆盖目录(Sol 含 tools.json;--product 预填 products_patch.json) |
debug overlay build [--case <case.json>] --overlay <dir> [--out <file>] [--format sol|v1|online] | 离线:把覆盖目录合并进 case 的 overlay 段(含 tools),并写 products_patch / tool_mocks(classic 输出 debug_data_overlay v1);--format online 输出线上模拟用的 {version, servhub, sol},不需要 --case,--out 可省(结果直接打印) |
debug ask 会自动创建调试会话、发送消息、轮询等待 Agent 回复,默认最大等待 30 秒,默认轮询间隔 2000ms。--text 与 --messages 二选一:--text 发送单条消息,--url 只在 --text 模式下作为附图 URL;--messages 传入完整消息列表(JSON 或 @文件)重放多轮对话,既接受 JSON 数组,也接受 conversation records 原始 { "msg_list": [...] } 对象。--conversation 可复用已有 debug 会话继续对话;--mock 可传工具结果 mock;--expect 对本轮线上回复做断言;--data-overlay 可传 debug_data_overlay JSON 或 @文件;--overlay <dir> 直接用覆盖目录现场生成线上模拟覆盖(Sol,与 --data-overlay 互斥)。
debug reproduce 根据一条回复记录自动复现 Agent 回复:通过 recordId 获取关联会话和 Agent 配置,拉取完整会话记录并截取目标 record 之前的上下文,使用原始用户名创建新 debug 会话并发送。默认最大等待 60 秒,默认轮询间隔 2000ms。--agent 可指定另一个 Agent 复现同一段上下文(A/B 对比);--mock、--expect 和 --data-overlay(或 --overlay <dir>,见「Sol 线上模拟」)会在复现发送时透传;--replace-last / --image 换掉最后一条买家消息;--dry-run 仅输出截断后的 msg_list(含替换结果)、mock 和 overlay,不发送。
debug data snapshot 生成 debug_data_overlay v1 JSON,适合把当前 Agent 的 SOP / 商品 / 活动等数据固定成一次 debug 覆盖输入,再通过 debug ask --data-overlay @file 或 debug reproduce --data-overlay @file 复跑。--agent <id> 必填;--product-id <商品ID...> 可重复传多个商品 ID,只导出指定商品,不传则分页导出全量商品。命令输出写到 stdout,通常重定向到文件保存。
# 只导出指定商品相关 overlay
cs-cli debug data snapshot --agent <id> --product-id 586812046546 > overlay.json
# 使用 overlay 跑一次 ask
cs-cli debug ask --agent <id> --text "https://item.taobao.com/item.htm?id=586812046546 这个商品名称是啥" --data-overlay @overlay.json
Sol 逐轮回放:先用生产环境的 CLI 配置运行 replay export,按轮次顺序传入同一会话的 1 到 50 个 sol_trace_id 或回复 record_id。导出依赖存档中的轮前状态、客户资产和商品数据;缺少可执行上下文的历史存档会由服务端明确报错。导出包顶层附 export_report(sol-replay-export-report/v1),逐轮标出回放会不会停:blocked 表示严格与 lenient 都会停,warn 表示严格会停、lenient 可继续(含跳过轮);有 warn/blocked 时 export 在 stderr 打印逐轮摘要(轮号、状态、规则码),stdout 与退出码不变。授权了推荐工具却没捕获 recommend_route 的轮由导出自动补(先借同包邻轮,借不到补空路由),来源记入 export_report.recommend_route_filled,不用再手工补。replay open 只生成本地 run.json,内嵌完整 case;消息卡片、未知字段与原时间戳均原样保存。
执行 next / run 时使用当前 CLI 环境的客服 API 和登录态;服务端仅在 dev 开放执行。预先按上面的多环境步骤分别配置并登录,生产导出使用 --env prod,执行使用 --env dev。rollout(默认)沿用 dev 每轮产生的状态,适合改了商品选择逻辑后验证后续轮次;original 每轮恢复对应线上状态,适合独立对照。
# dev 与 prod 已分别配置 API、工作空间并登录
cs-cli --env prod debug replay export --record <第一轮回复ID> <第二轮回复ID> --out case.json
cs-cli debug replay open --case case.json --out run.json
cs-cli --env dev --request-timeout 180000 debug replay next --run run.json
cs-cli --env dev debug replay run --run run.json --until 2
# 保留完成的第一轮,从其 dev 状态继续新分支;--at 0 从初始上下文开始
cs-cli debug replay fork --run run.json --at 1 --out run-b.json
cs-cli --env dev debug replay run --run run-b.json
# 新逻辑会查询 B:补入包含 B 的原始商品数据,再从同一个 checkpoint 分叉
cs-cli debug replay fork --run run.json --at 1 --products products-B.json --out run-products-B.json
cs-cli --env dev debug replay next --run run-products-B.json
open / fork --products snapshot.json 把原始商品数据对象固定到 case.products,显式作为所有后续轮次的数据源;商品 ID/SKU 查询和卡片生成仍由真实 Sol 代码执行。其余消息、客户身份、前 N 轮与 checkpoint 保持原样。快照应覆盖改动后会查到的商品及所需 SKU、库存、摘要;缺范围由服务端报错,不自动补空结果。不传 --products 则使用各轮自己的录制数据,库存等时点数据不会跨轮自动合并。
只想改几件商品(改状态 / 补库存或总结 / 补活动与关联知识)时,不必重写整份快照:在 case.json 顶层加 products_patch(products-patch/v1)即可,按商品 id 合并行、整块替换 SKU / 库存 / 总结、覆盖短链,并按商品集合补 enrichment;格式见 docs/devkit/specs/2026-10-27-590-sol-工具mock.md「商品局部补丁」。sol-local 对应 shop.products_patch 与 run --products-patch。不想手改 case 时,open / fork --products-patch patch.json 把补丁写进 case.products_patch,--mocks mocks.json(tool-mock/v1)写进 case.tool_mocks;两者都先按契约校验,非法时不建运行文件。fork 只替换给出的那一项,其余沿用原运行文件。
复现第 N 轮之后的回复:只知道会话 id 时,export --conversation <id> [--until N] 按时间顺序读 AI 回复的 record 诊断、收集去重后的 sol_trace_id 再导出(人工回复没有 Sol trace,自动跳过;超过 50 轮必须 --until)。要看「第 N 轮之后买家换一种说法 / 追问一句会怎么回」,用 append 离线造一轮:
cs-cli --env prod debug replay export --conversation <conversation_id> --until 3 --out case.json
cs-cli debug replay append --case case.json --after 3 --text "那 1.8 米的有现货吗" --out case.next.json
cs-cli debug replay open --case case.next.json --out run-next.json # 只能 rollout
cs-cli --env dev --request-timeout 180000 debug replay run --run run-next.json
- 合成轮复制第 N 轮的 request / context(资产、识图、商品快照不变),在对话末尾接上买家文本消息(多个
--text即连发),时钟默认第 N 轮 + 60 秒(--clock可指定),去掉只对原轮有效的 QA 预取录制与线上结果,tool_records清空,并标synthetic。第 N 轮之后的原有轮次丢弃。 - rollout 会丢掉第 N 轮线上 AI 回复、接在 dev 回复之后;第 N 轮到合成消息之间线上真实发生的人工 / 平台消息不会带上。
- 合成轮没有工具录制:模型调了非商品工具会 422 缺录制,用
--mocks给这些工具配fill规则;商品工具走商品快照。含合成轮的 case 拒绝--mode original。
--until N 表示执行到完成 N 轮,包含第 N 轮;不传则跑完。每轮用独立 request_id 关联同步终态,并原子保存结果及 checkpoint。failed / skipped 也作为该轮结果保存;HTTP 错误或返回关联不符时保留上一个已完成 checkpoint,再次执行即可从该处恢复。export / open / fork 不覆盖已有文件。运行文件使用同目录 .lock 防止并发推进;进程异常退出后,确认没有回放进程才可删除残留锁。文件包含客户上下文,默认权限为 0600。
供 AI 执行的输出与取证:next/run 默认仅返回进度、最后一轮 response_status、回复预览、焦点商品及卡片/工具/告警数量。execution_status=completed 表示命令完成,verification_status=not_evaluated 表示尚未判断业务预期;即使本轮 Sol 是 failed/skipped,仍完整存档并在摘要中明确显示。完整 response、trace、checkpoint 保存在 saved_to 指向的 run 文件。
inspect 只读本地文件,不需要联网或登录。--turn 使用从 0 开始的索引;不传则分页读取已完成轮次摘要。视图为 summary|response|cards|tools|trace|checkpoint|request|raw;cards 读取 checkpoint 中的 tool_result 事实载荷(包含沿用的历史事实),没有记录时提供 run_record 卡片摘要;原始业务载荷可取 /response/llm_payload。tools 来自 trace 的工具执行。--path 从本轮完整结果按 JSON Pointer 取字段(覆盖 view),支持 /→~1、~→~0 转义。未执行轮次可查 request。数组默认 10 项,--offset/--limit 分页,返回 total/next_offset;超过 12,000 bytes 的视图仅给标记截断的预览,可缩小路径或 --out 完整保存所选视图/数组页,未知字段不改写。
cs-cli debug replay inspect --run run.json
cs-cli debug replay inspect --run run.json --turn 0 --view cards --limit 5
cs-cli debug replay inspect --run run.json --turn 0 --view tools
cs-cli debug replay inspect --run run.json --turn 0 --path /checkpoint/head/focus_skus
cs-cli debug replay inspect --run run.json --turn 0 --view trace --out turn-0-trace.json
cs-cli debug replay compare --baseline run.json --candidate run-b.json --out comparison.json
cs-cli debug replay compare --baseline run.json --candidate run-b.json --expect expected.json --out verified.json
compare 要求 source、mode、逐轮 trace ID 和 request 相同,允许显式更换数据。比较共同已执行前缀的状态、回复、转人工、标签、事实卡及载荷、工具有效参数/结果、焦点商品/订单/SKU/场景;忽略卡片抓取时刻与工具耗时。case_equal/data_equal 和两份运行摘要用于标明输入包及数据是否一致;完成长度不同则 comparison_status=incomplete。默认只报差异位置和数量,完整 before/after 与断言证据可用 --out 保存,或通过 inspect 按位置读取。无 --expect 一律 not_evaluated,不把“无差异”判作“正确”。
预期文件只做显式逐轮字段断言(默认相等比较),不执行代码或自动语义评分;每条可加 op:equals(默认)/ not_equals / contains / not_contains / length / startswith / in,字段缺失一律判失败:
{"schema":"sol-replay-expect/v1","assertions":[
{"turn_index":0,"path":"/checkpoint/head/focus_product_ids","equals":["B"]},
{"turn_index":1,"path":"/checkpoint/head/focus_product_ids","equals":["B"]}
]}
断言工具调用用 op: "called" / "not_called",不写 path(或写 /tool_calls),equals 为 {tool, input?, include_prefetch?}:tool 接受配置名或 canonical 名(faq_knowledge = fetch_qa);input 对模型给的入参做子集匹配;默认只认模型调用(取自 trace.llm_calls 输出的 tool_calls,不含 read_block);引擎自己发起的执行——预取、选品轮按 must_invoke 补发的 product_recommendation 等——不算,include_prefetch: true 时任何执行都算。debug ask / debug reproduce --expect 同样可用,线上证据取 run_record.tool_calls,input_source=prefetch 的不算模型调用;补发的执行同样标 input_source=model,按本轮告警 recommendation_forced 认出来,不算模型调用(debug replay tools 里记 forced)。
{"schema":"sol-replay-expect/v1","assertions":[
{"turn_index":2,"op":"called","equals":{"tool":"order_query"}},
{"turn_index":2,"op":"not_called","equals":{"tool":"faq_knowledge","input":{"query":"运费"}}}
]}
debug replay tools --run run-1.json run-2.json ... 汇总多个运行文件:每个工具的 model_calls、turns_called、call_rate(调用轮数 / 已执行轮数,同一 case 多跑几次即调用率)、executions 按数据来源(recorded 录制 / mock / overlay 覆盖知识词法检索 / snapshot 商品快照 / prefetch 预取)计数、missing_recording(缺录制)与 failed,calls 给逐轮明细(--limit 截断)。回放里预取的非商品工具也按录制记 recorded,所以引擎发起(预取、must_invoke 补发)的次数要用 executions − model_calls 估。
全部声明断言满足才是 verification_status=passed;不相等或字段不存在为 failed,所需轮次尚未执行为 incomplete。这里的通过仅覆盖声明的断言,可用于验证 A→B 以及下一轮继续 B;回复质量仍需业务标准。比较命令成功时外层 success=true;断言失败/未完成额外设置退出码 1。无预期的差异报告和断言通过退出码为 0。
缺数 HTTP/业务 422 会在 CLI error 中保留受控的 reason/retryable/missing/next_action/truncated,例如 missing=[{"kind":"catalog","ids":["B"],"fields":["rows","covered_product_ids"]}]。snapshot_data_incomplete 对应 supply_snapshot,输入损坏的 replay_invalid_input 对应 repair_case;两者均 retryable=false。AI 应按 fields 补齐原始快照再 open/fork,或修复 case,随后从保存的轮次继续;重复同一请求不会产生缺失数据。诊断只含字段名和受控实体标识,不含凭据、任意上游异常或完整工具参数;非法诊断退回固定失败信息,不更新失败轮的 checkpoint。
所有回放命令默认 JSON 的最终输出信封(包含路径等元数据)按 12,000 bytes 控制。超限时返回 truncated=true、data.artifact 与 next_action=read_artifact,完整输出转存为权限 0600 的本地临时证据文件;运行文件和显式 --out 仍保留完整数据。AI 应先读取 artifact;需长期保存时将其复制到任务目录。非法或缺失结构化诊断的 422 始终使用固定文案,不回显上游 message。
回放配置覆盖(#442):在本地改 SA、FAQ、扩展知识、customer_config、工具、商品后重跑,不写线上。
cs-cli --env prod debug replay export --record <record_id> --out case.json
cs-cli --env prod debug overlay init --case case.json --out ov/ --product <商品id> # 只读;默认 --base current
# 编辑 ov/sa.json、ov/faq.json、ov/common_knowledge.json、ov/customer_config.json、ov/tools.json、ov/products_patch.json
cs-cli debug mock init --case case.json --out ov/tool_mocks.json # 可选:新增工具或要替换工具返回值时
cs-cli debug overlay build --case case.json --overlay ov/ --out case.ov.json
cs-cli --env dev debug replay open --case case.ov.json --out run-ov.json && cs-cli --env dev debug replay run --run run-ov.json
cs-cli debug replay compare --baseline run.json --candidate run-ov.json --ab
overlay init生成sa.json(SA 全量)、faq.json(FAQ 当前全集)、common_knowledge.json(扩展知识当前全集)、customer_config.json(深合并补丁,初始{})和.base.json(基线元信息)。不写request及其中凭据。--base current:取同一 Agent 最近一轮 Sol 回复的资产,再用sa list、agent get的当前值修正,差异写进stale_fields(只核对 SA 和 flow_instruction 槽位;所选回复超过 24 小时会告警,其他配置可能已改过);找不到 Sol record 时退回事故快照,.base.json标fallback: "incident"并在 stderr 告警。--base incident:取 case 第一轮(或--turn N)的资产。- FAQ 条目 id 写成
<file_id>-<answer_group_id>,知识条目写成<file_id>-<chunk_id>。 overlay build只写和基线不同的 SA,定位写 id(内容哈希),不写每轮排序编号ref;sa.json里 ref / id 重复会报错(复制条目当新增时去掉 ref 和 id)。faq.json/common_knowledge.json相对 init 有改动(含新增、删除)时整集写入,回放里对应的检索改为本地词法检索(报告标lexical_approx);没改或删掉文件时不写,仍用录制结果。标准 QA 不覆盖,报告固定写qa_assets: "baseline"。整份商品快照仍用replay open/fork --products,改几件商品用下面的products_patch.json。- 工具(Sol):
overlay init另写tools.json——回放资产tool_entries去重后的工具行全量(同一 canonical 名有多行时自定义行优先),基线存进.base.json的tools_baseline。可改description、input_var_descriptions、invocation_mode(must_invoke/on_demand/on_demand_async)、usage_guidance、selection_hint等字段,也可加一行新工具或删掉一行(或写"delete": true)。build按 canonical 名与基线 diff:改了的只写改动字段,删掉的写{tool, delete: true},新增整行写入overlay.tools,引擎同时同步请求的tools[](授权集合)。字段从行里删掉不会清空(浅合并,要清空写空字符串);Sol 自持工具(build_apply_link、fetch_product_supplement、改备注 / 改地址等)只读usage_guidance;usage_guidance/selection_hint回放能验证但tool update写不了;这些情况 build 在 stderr 提示。 - 新增工具在回放里没有录制,模型一调就 422 缺录制:用
debug mock init生成ov/tool_mocks.json并给它加规则(fill/override),build 原样写进case.tool_mocks;没配 mock 时 build 提示。 - 商品(Sol):
overlay init --product <id...>按商品 id 从 case 商品快照预填products_patch.json(products-patch/v1:目录行去掉商品id,可改 参数 / 卖点 / 补充知识 / 标题等列;该商品全部 SKU 行;总结;库存),快照里没有的商品写空行并告警。build对预填基线最小化:目录行只留改动列,SKU / 库存 / 总结整块比较,没改的商品不写;enrichment(按商品集合补活动 / 关联知识)与short_links原样保留;结果写进case.products_patch,全没改则不写。 --format v1不支持工具、商品补丁和工具 mock,三个文件存在时列进skipped。- 执行端 sop-engine 早于
overlay.tools支持时会静默忽略工具覆盖(hash 仍然通过);next/run发现overlay_report.applied没有tools时在摘要overlay_warnings和 stderr 告警,这时工具改动没生效。 hash与引擎同口径:去掉hash后键按码点排序、无空白分隔、非 ASCII 原样、UTF-8,取 sha256。- 每轮结果带
overlay_report(applied / missing / retrieval)。同样的 case 可直接给sol-local run --case case.ov.json。 - classic 店:
overlay init --agent <id>,overlay build输出debug_data_overlayv1,交给debug reproduce --data-overlay @file。v1 的 FAQ / 知识只带相对基线改动或新增的条目;v1 表达不了的改动(含删除条目)列在skipped。
--data-overlay 生效检查:debug ask / debug reproduce 带 --data-overlay(或 --overlay <dir>)时,发送前按目标 Agent 的顶层引擎(读不到时 reproduce 看原 record)拦截引擎不读的非空子树,退出码 2、不发送:sop 子树只有 classic 读(Sol 店会提示改用 sol 子树或 --overlay,Luna 的 SA / FAQ / 知识覆盖走 debug replay),sol 子树只有 Sol 读。发送后逐条读回 debug_data_overlay 回报并输出 debug_data_overlay_report(applied / missing / unused / sol 的 hash、base、检索口径);applied(sop、servhub、sol)全空时退出码 3,引擎回报 sol.invalid(子树不合法,本轮按无覆盖执行)时打印原因并退出码 3。
Sol 线上模拟(#610):在本地改 Sol 店的 SA、工具、标准 QA、FAQ、扩展知识、商品、开关、customer_config、违禁词后,用线上真实服务跑一轮,不写线上配置。覆盖只随这一次 debug 请求生效。
cs-cli --env prod debug overlay init --agent <config_id> --out ov/ # 只读:拉当前 SA / FAQ / 扩展知识作基线(也可 --case 用回放基线)
# 编辑 ov/sa.json、ov/faq.json、ov/common_knowledge.json、ov/customer_config.json;可选 ov/switches.json、ov/qa_items.json、ov/forbidden_words.json、ov/tools.json、ov/products_patch.json
cs-cli --env prod debug overlay build --overlay ov/ --format online # 可选:只看生成的 {version, servhub, sol}(加 --out 写文件)
cs-cli --env prod debug ask --agent <config_id> --text "问题" --overlay ov/
cs-cli --env prod debug reproduce <record_id> --replace-last "换个问法" --overlay ov/ [--image <url>] [--dry-run]
--overlay <dir>等于先overlay build --format online再--data-overlay;和--data-overlay互斥(同时传退出码 1)。目录相对 init 基线没有任何改动、文件格式错误时报错、不发送。- 输出形状:
{"version":1,"servhub":{customer_config?,forbidden_words?},"sol":{version:1,base,hash,sa?,tools?,qa_items?,faq?,common_knowledge?,products_patch?,switches?}}。没有 sol 内容时整个sol省略。sol不含 customer_config 与 assets_replace;sol.hash与--format sol同一套规范化 JSON sha256。 sa/tools/products_patch与--format sol同一套 diff(只发改动;SA 定位写 id)。faq/common_knowledge是补丁:只发改动、新增的条目;基线里有而目录里没有的条目(或写了"delete": true)发{id, delete:true, match_*};改动条目带基线原文match_questions(FAQ 原问法)/match_content(知识原正文),引擎靠它在真实检索结果里定位。原文存在.base.json的knowledge_baseline,旧版init生成的目录没有它:补丁照发但不带match_*,skipped里提示重新init。- 可选文件,缺了就不发对应项,格式错误明确报错:
switches.json:{"full_product_detail":bool,"order_promise_ship_time":bool,"image_rule_transfer":bool},只允许这三个布尔开关。qa_items.json:数组,条目{ref?|id?, questions?, answer_text?, delete?};带ref/id的是改或删,不带的是新增(必须同时给questions与answer_text)。forbidden_words.json:字符串数组,整体替换线上违禁词表,进servhub.forbidden_words。
init --agent只读拉 SA / FAQ / 扩展知识基线(servhub 读口),不拉工具行也不预填商品:没有 case 快照时tools.json/products_patch.json不会生成,要改工具或商品就手写增量文件(工具行只写要改的字段,删除写"delete": true;build提示「没有工具基线,按增量原样发送」)。要拿到工具基线与商品预填,用init --case <case.json>(回放资产快照)。sol.base=incident的覆盖在线上仍套在当前线上资产上,不是事故时刻的资产(条目对不上的会在missing里);ask/reproduce发送前打印一行提示。- 带 overlay 或
--mock时,输出里始终有本轮tool_calls:{model, prefetch, forced}三组,每项{tool, status, source, args},stderr 同步打印[tool-calls] model=N prefetch=N forced=N。prefetch是引擎预取(input_source=prefetch/prefetch_mock),forced是选品轮must_invoke补发(按本轮告警recommendation_forced认出),两者都不算模型调用,口径与called/not_called断言一致。统计落库晚于回复,取不到 flow_info 时 stderr 提示「tool_calls 为空不代表没调用」。 reproduce --replace-last <文本>把上下文里最后一条买家消息的文本换掉,--image <url>换 / 加图片(可同用),其余上下文不变;--dry-run展示替换后的msg_list与replaced_last,不发送。上下文里没有买家消息时报错。- 判读顺序:先看
debug_data_overlay_report.records[].applied(改动有没有生效)、missing(条目对不上)、unused(声明了但本轮没读到),再看tool_calls(本轮实际调了什么)和回复。
工具 mock(Sol):debug ask --mock @mocks.json / debug reproduce --mock @mocks.json 会把工具返回值替换成声明的数据(真实工具 handler、工具录制采集与 flow 点上报都不执行),模型仍自行决定是否、何时调用;买家的真实链路不带这个字段。模型调用本身仍会产生 token 成本。回放(debug replay / sol-local)与实时共用同一份 tool-mock/v1 契约:
{
"schema": "tool-mock/v1",
"rules": [
{"id": "order-signed", "tool": "order_query", "mode": "override", "call": 1,
"input": {"order_id": "123456"},
"response": {"status": "success", "result": [ ... ]}}
]
}
mode=override压过回放录制;mode=fill只补缺失(默认)。旧的{工具名: {status, result}}与[{tool_name, result}]仍可用,等价fill。call是该工具本轮第几次调用(1-based),input是入参子集(匹配有效输入:模型可见参数 + 被拆到网关侧通道的query/product_ids);多条规则按声明顺序取第一条。- 命中与未命中都可见:结果带
tool_mock_report{applied[{tool,call,rule,mode}], unused[{rule,tool,reason}]},reason为tool_not_called/input_mismatch/recording_present。实时请求里规则非法时不打断本轮,按无 mock 执行并在warnings记tool_mock_invalid;回放 / sol-local 的规则非法则直接判用例非法(422 / 退出 2)。 - 从已有回放包生成可编辑骨架:
cs-cli debug mock init --case case.json --out mocks.json(按轮次 / 调用序号展开,response取自录制,改完即可用)。 - 批量:
sol-local bench run --tool-mocks mocks.json [--products-patch patch.json] --strict-mocks,整集未命中的规则会让命令非零退出。
线上回报与断言:debug ask / debug reproduce 带 --mock 时,同步响应与返回 data 都带 tool_mock_report;报告同时写进回复的 flow_infos,之后用 debug record <record_id> 也能查到(OSS 不可用时 DB slim 版仍保留该字段)。规则非法时没有报告,单独返回 tool_mock_warnings(code=tool_mock_invalid),stderr 同时打印 applied / unused / invalid 摘要。
--expect <file> 复用 sol-replay-expect/v1,对本次线上回复做单轮断言;turn_index 只支持 0,其余 op / 字段缺失判失败的规则与 debug replay compare --expect 完全一致。断言路径相对线上证据对象:
| 路径 | 内容 |
|---|---|
/response/messages | 本次调试会话里各条助手回复文本 |
/response/transfer_to_human | 回复记录上的转人工标记(未取到时为 null) |
/response/transfer_decision | Sol run_record.transfer_decision(有存档时) |
/tool_mock_report | {applied, unused};可断言 /tool_mock_report/unused 的 length 为 0 |
/warnings | 引擎告警列表;tool_mock_invalid 也在里面 |
/cards | Sol 本轮卡片(来自 flow_infos,没有时为 []) |
{"schema":"sol-replay-expect/v1","assertions":[
{"turn_index":0,"path":"/response/messages","op":"contains","equals":"已签收"},
{"turn_index":0,"path":"/response/transfer_to_human","equals":false},
{"turn_index":0,"path":"/tool_mock_report/unused","op":"length","equals":0}
]}
断言失败或 incomplete 时设置退出码 1;全通过为 0。这里只验证声明的断言,回复质量仍按业务标准判断。
cs-cli debug mock init --case case.json --out mocks.json
cs-cli --env dev debug ask --agent <id> --text "帮我查下订单 123456" --mock @mocks.json
Sol 完整 prompt 存档(debug trace 的第二种 id):Sol 引擎(路由 v4)每轮把每次 LLM 调用发给模型的原样 messages / tools 存到 OSS(30 天),debug record 返回的 sol_trace_id(st-YYYYMMDD-<uuid>)即存档 id。存档格式与各种视图都由服务端定义,CLI 只传参、写文件(设计见 docs/devkit/specs/2026-09-23-sol-trace-完整prompt回溯与AI取数.md §9.20)。只接受登录用户,且需有该存档所属 workspace 的权限。
- 单轮:
--view summary(默认)给身份 / 结局 /labels/decision/ 每次调用一行。--view diagnosis是给客服助手的更短卡片(无身份 id、无工具入参,不超过 4KB)。要原文再取prompt(--call选,默认第一次 main)、lean、full或otel。verified是服务端哈希校验结果。 - 按天:每天北京时间 02:30 合并前一天,当天的请用单轮(先在 Langfuse 按结局 tag 筛出轮次,再拿
sol_trace_id)。workspace 取全局--workspace/ 默认配置。不带--out只列各 agent 的轮数;--out <dir>下载服务端展开好的调用文件到<dir>/<date>/<workspace>/<agent>/calls.jsonl(一次调用一行,lean 形态,每行带轮次上下文、labels、decision)。--label(可重复,AND)按结局标签筛轮次,如transfer、repair、llm-error、status:failed、warn:<告警码>;--node只保留某类调用;--limit限制轮数(跨 agent 累计)。
# 某条回复为什么这么回:record 里直接带 decision;要原文再看 prompt
cs-cli debug record <record_id>
cs-cli debug trace --record <record_id> --view prompt
cs-cli debug trace st-20260923-<uuid> --view prompt --call repair
# 批量:昨天某 agent 所有转人工轮次的主调用
cs-cli --workspace <workspace_id> debug trace --date 2026-09-23 --agent <agent_id> --out ./sol-trace --label transfer --node main
debug trace(v0.4.0 起,行为变更)不再由 CLI 直连 Langfuse REST API,改为请求 customer-servhub-api 的 GET /v1/debug/langfuse/trace/{trace_id}?env=<env>,走 CLI 标准 Bearer 鉴权,由服务端按 env 选择 Langfuse 凭据并代理拉取 Trace。Trace ID 从 debug record 返回的 trace_id 字段获取。
工作空间 (workspace)
| 命令 | 说明 |
|---|---|
workspace list | 列出当前账号可访问的工作空间 |
workspace points-consumes [--page <n>] [--page-size <n>] | 分页查询积分账户消耗流水,固定返回 extra 调试字段 |
workspace points-consumes-daily [--start <YYYY-MM-DD>] [--end <YYYY-MM-DD>] | 按天查询积分消耗趋势 |
debug trace --langfuse-env <dev|prod>:指定 Langfuse 环境,默认跟随全局 API 环境;未传全局--env时默认prod。非法值报错并以非 0 退出,不发请求。
# 默认 prod 环境
cs-cli debug trace <trace_id>
# 指定 dev 环境
cs-cli debug trace <trace_id> --langfuse-env dev
迁移(v0.4.0 BREAKING):
config set --langfuse-host / --langfuse-public-key / --langfuse-secret-key及CLIConfig.langfuseHost / langfusePublicKey / langfuseSecretKey已移除;环境变量LANGFUSE_BASE_URL / LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY在 CLI 侧不再被读取。~/.cs-cli/config.json中相关字段可直接删除。Langfuse 连接信息(含 dev/prod 双环境凭据)现由 customer-servhub-api 服务端的system_config表langfuse_config行统一管理(不再读服务端环境变量 / 内置常量),CLI 侧无需也无法再配置。
修复记录 (repair-record)
| 命令 | 说明 |
|---|---|
repair-record list [--issue <工单ID>] [--agent <AgentID>] [--workspace <工作空间ID>] [--page N] [--page-size N] | 列出修复记录 |
repair-record create --issue <工单ID> --agent <AgentID> --action <修复动作> [--agent-name <名称>] [--type <类型>] [--status <状态>] [--duration <毫秒>] [--result <JSON>] [--workspace <工作空间ID>] | 创建修复记录 |
repair-record update <record_id> --data <json|@file> | 更新修复记录 |
--status 可选值:pending、success、failed、partial。
repair-record update 的 --data 支持的字段:repair_action、repair_result(JSON 对象)、repair_type、repair_status、duration_ms。
repair_result 结构
--result 或 --data 中的 repair_result 字段应为结构化 JSON,用于记录 AI 修复的完整推理过程,支持未来 AI 自我进化。
| 字段 | 类型 | 说明 |
|---|---|---|
failure_type | string | 问题分类: wrong_answer / missing_answer / hallucination / wrong_routing / slow_response / other |
root_component | string | 归因组件: sa_policy / faq / product_knowledge / customer_config / prompt / multiple / unknown |
input | string | 触发问题的用户输入 |
expected | string | 期望的正确回复 |
actual | string | 实际的错误回复 |
diagnosis_reasoning | string | AI 的诊断推理过程:排查了什么、怎么定位根因、排除了哪些可能性(最高价值字段) |
diagnosis_confidence | string | 诊断置信度: high / medium / low |
hypotheses_considered | array | 考虑过的假设列表,每项含 hypothesis、evidence_for、evidence_against、verdict |
fix_strategy | string | 修复策略: create_sa / update_sa / delete_sa / update_faq / add_faq / update_product / update_config / multi_step |
fix_reasoning | string | AI 的修复决策推理:为什么选这个方案、为什么不选其他方案、预期风险和收益 |
alternatives_rejected | array | 被否决的方案列表,每项含 approach、reason |
changes | array | 变更快照,每项含 component、action、target_id、before、after |
target_fixed | boolean | 目标问题是否修复 |
regression_summary | string | 回归验证结果摘要 |
retry_history | array | 重试记录,每项含 round、what_failed、lesson、adjustment |
duration_ms | number | 修复总耗时(毫秒) |
repair_status | string | 最终状态: success / failed / partial |
resolved_date | string | 修复完成时间(ISO 格式) |
加粗的两个字段(diagnosis_reasoning 和 fix_reasoning)是对 AI 自我进化价值最大的:没有它们只能做模式匹配,有了它们才能做推理。
运维操作记录 (ops-record)
本组全部命令要求内部普通权限(DEVELOPER、ADMIN 或 SYSTEM_ADMIN)。
| 命令 | 说明 |
|---|---|
ops-record list [--workspace <工作空间ID>] [--agent <AgentID>] [--page N] [--page-size N] | 列出运维操作记录 |
ops-record get <record_id> | 获取运维操作记录详情 |
ops-record create --workspace <工作空间ID> --agent <AgentID> [--workspace-name <名称>] [--agent-name <名称>] [--path <文件路径>] [--remark <备注>] | 创建运维操作记录 |
ops-record update <record_id> --data <json|@file> | 更新运维操作记录 |
ops-record delete <record_id> | 删除运维操作记录(软删除) |
ops-record update 的 --data 支持的字段:workspace_name、agent_name、path、remark。
创建记录时 operator_id 和 operator_name 自动从当前登录用户获取,无需手动指定。
商品变更事件消费 (change-consumer)
客服运维助手订阅并消费商品变更事件(pull 模式)。后端走 /v1/change-consumers/*,CLI 标准 Bearer 鉴权。默认 consumer_key=ops_agent_assistant。
标准工作流:sub create 创建订阅 → delivery list 轮询待消费项 → delivery claim 认领 → 处理 → delivery complete 回写。
| 命令 | 说明 |
|---|---|
change-consumer sub create --workspace-id <id> [--agent-config <id>] [--events <list>] [--resource-type product] [--consumer-key <key>] [--consumer-name <名称>] [--disabled] [--data <json|@file>] | 创建订阅(最简只需 --workspace-id;--agent-config 缺省表示该工作空间全部商品事件) |
change-consumer sub list [--workspace-id <id>] [--agent-config <id>] [--consumer-key <key>] [--enabled <true|false>] [--page N] [--page-size N] | 查询订阅列表 |
change-consumer sub update <subscription_id> --data <json|@file> | 更新订阅(enabled / events / filters / consumer_name) |
change-consumer delivery list [--workspace-id <id>] [--agent-config <id>] [--consumer-key <key>] [--statuses <list>] [--cursor-created-at <iso>] [--cursor-delivery-id <id>] [--limit N] | 查询待消费项(不传 --statuses 时后端默认返回 pending/claimed/failed;--cursor-* 做增量拉取) |
change-consumer delivery claim <delivery_id> --claimed-by <id> [--consumer-key <key>] [--lease-seconds N] | 认领待消费项(已被其他实例认领且未过期时认领失败) |
change-consumer delivery complete <delivery_id> --status <completed|ignored|failed> [--result-action <action>] [--result-note <note>] [--last-error <error>] [--consumer-key <key>] [--data <json|@file>] | 回写处理结果 |
sub create默认--events product.updated,product.deleted、--resource-type product;--disabled创建为停用态(默认启用)。delivery complete的--status仅接受completed/ignored/failed,其它值直接报错退出;不要长时间停留在claimed不回写。--result-action建议值:supplemental_knowledge/product_association/rerun_product_study/refresh_recommended_qa/ignore_change/manual_follow_up。- 各子命令
--data <json|@file>为高级用法,提供时覆盖对应结构化选项。
# 1. 创建订阅(该工作空间全部商品 更新/删除 事件)
cs-cli change-consumer sub create --workspace-id <ws> --events product.updated,product.deleted
# 2. 轮询待消费项
cs-cli change-consumer delivery list --workspace-id <ws> --statuses pending
# 3. 认领
cs-cli change-consumer delivery claim <delivery_id> --claimed-by ops-assistant-1
# 4. 处理后回写
cs-cli change-consumer delivery complete <delivery_id> --status completed \
--result-action supplemental_knowledge --result-note "已补充商品知识"
运营监控 (monitor)
直接调用 /v1/operation 底层接口,返回原始数据,由调用方决定如何聚合统计。fields、tickets list/delete 要求内部普通权限;其余六个数据查询命令要求 SYSTEM_ADMIN。
字段说明
| 命令 | 说明 |
|---|---|
monitor fields [resource] | 查看监控资源的指标字段说明;本地静态输出,仍要求内部普通权限 |
Agent 生命周期
| 命令 | 说明 |
|---|---|
monitor agents [--page N] [--page-size N] | Agent 生命周期列表(含构建进度、会话统计等原始数据) |
监控工单
| 命令 | 说明 |
|---|---|
monitor tickets list [--agent <id>] [--status <状态>] [--severity <级别>] | 列出监控工单 |
monitor tickets delete <ticket_id> | 删除监控工单 |
监控快照
| 命令 | 说明 |
|---|---|
monitor snapshots hourly --agent <id> --start <ISO> --end <ISO> | 查询小时快照 |
monitor snapshots daily --agent <id> --start <日期> --end <日期> | 查询日快照 |
monitor snapshots daily-range --agent <id> --start <日期> --end <日期> | 查询日快照范围(含趋势) |
Agent 运营统计
| 命令 | 说明 |
|---|---|
monitor statistics [--start <ISO> --end <ISO>] [--page N] [--page-size N] | Agent 运营统计(会话量、转人工率、响应时间等) |
运营工作空间
| 命令 | 说明 |
|---|---|
monitor workspaces [--has-agent] [--page N] [--page-size N] | 运营工作空间列表(含合同、客户信息) |
模型 Token 成本(token-usage,需超级管理员(SYSTEM_ADMIN))
成本以 customer-observability-api 账本为准;cost_cny 是刊例价,payable_cost_cny / discount_rate 是实付。
| 命令 | 说明 |
|---|---|
token-usage summary --start <时间> --end <时间> [--workspace-id <id>] [--agent <id>] [--engine sol|luna|classic] [--include-test] | 时间窗内的成本汇总 |
数据看板 (dashboard)
转人工率 / 接待量 / AI 回复量等运营指标。数据 T+1(--end 不能晚于昨天,否则后端返回 400);--start / --end 为闭区间。渠道枚举:qianniu(千牛/淘宝)/ jingdong / pinduoduo / douyin。CLI 只产结构化数据,运营报告由上层(如 LLM)按场景加工。
| 命令 | 说明 |
|---|---|
dashboard summary [--config-id <id>] [--start <d>] [--end <d>] [--channel <c>] | 全局或单店 KPI 汇总 + 环比(不传 --config-id 为全店铺聚合) |
dashboard trend [--config-id <id>] [--start <d>] [--end <d>] [--granularity day/week/month] [--channel <c>] | 趋势(每日/周/月接待客户数、转人工数、转人工率),--granularity 默认 day |
dashboard shops [--start <d>] [--end <d>] [--channel <c>] | 全部店铺统计列表(默认按转人工客户数降序),用于横向对比 |
dashboard export --start <d> --end <d> [--config-id <id> ...] [--channel <c>] [--out <path>] | 店铺维度每日明细。默认解析为 JSON 行;--out 落盘原始 CSV |