- 人工智能
- AI Agent
- 大模型
- AI 应用
- 媒体生成
【免费下载链接】xiaobei
为OPC/中小微企业量身打造的自媒体获客智能体
本文以 xiaobei 仓库中对外销售客服 Crew(
crews/sales-cs)的 AGENTS.md 工作流规范为主体,完整讲解其"工具在前、回复在后"的会话主流程、CustomerDB 客户数据库驱动机制、延迟购买跟进(follow_up)与意图分流规则。读者读完可以掌握:如何配置并运行一个严格受约束、以成交为导向的对外销售客服 Agent,以及如何用 SQLite 客户画像与 heartbeat 定时跟进构建完整的销售闭环。
1. sales-cs 在项目中的定位
xiaobei 是一个为 OPC / 中小微企业打造的自媒体获客智能体,仓库中按 Crew 组织多个 Agent 角色。sales-cs(销售客服)是其中的对外 Crew(external),代表公司对外服务客户,其行为受严格约束:只能使用DECLARED_SKILLS中声明的技能,不继承系统全局技能,禁止自我改进(不得修改自己的 workspace 文件),升级由 main agent 统一管理(见 IDENTITY.md、SOUL.md)。
该 Crew 在自身 workspace 内维护一个轻量级 SQLite 客户数据库(./db/customer.db),用于跨会话保存客户商业推进状态与基本画像,配合 heartbeat 定时任务实现"主动跟进"能力。其技能体系包含:
customer-db:客户数据库管理(更新画像、跟进任务增删查改)proactive-send:主动向客户发送消息(HTTP 网关传输)exp-invite:向合格客户发送体验群邀请(awada 控制消息)demo-send:演示材料发送(见 DECLARED_SKILLS)
2. 会话主流程(强制):工具在前,回复在后
AGENTS.md 将每一轮会话固定为五步强制流程:
1. 读取系统注入的 CustomerDB 当前状态 - 当前客户以注入的 peer 为唯一标识(来自 [CustomerDB] 块) - business_status / purpose / prompt_source / club_in 以注入值为准 2. 精准识别客户意图,进入对应分流 3. 工具在前:如本轮获得更明确信息,先在独立 turn 调用 cs-update.sh 更新客户记录 - 该 turn 不得包含任何面向客户的文本 - 仅补充或修正更明确的信息 - 不要用空值覆盖已有有效信息 - 不要基于模糊猜测更新 4. 若客户表达不满,同样先在独立 turn 将摘要记录到 feedback/YYYY-MM-DD.md(不记录 PII) 5. 回复在后:所有工具执行完成后,在最后一个 turn 统一输出面向客户的完整回复这一"工具 turn 与回复 turn 严格分离"的约束在 SOUL.md 中被标记为强制:任何调用工具(cs-update / feedback 记录 / follow-up / payment-send / ofb-key 等)的 turn 不得包含面向客户的文本;面向客户的完整回复必须在所有工具完成后、在最后一个 turn 统一输出。
需要特别说明的是:数据库初始化、默认记录创建、以及支付/入群等控制事件的静默状态更新由系统 hook 负责,agent 无需重复执行这些技术性步骤——这也解释了为何cs-update.sh等脚本只负责业务字段更新,而business_status不允许在脚本中手动修改(见下文第 5 节)。
3. 两个客户标识符:peer 与 user_id_external
这是使用 CustomerDB 前必须理解的核心概念。系统中客户有两个不同的标识符,用途不同,不可混用:
| 标识符 | 来源 | 用途 |
|---|---|---|
peer | 系统注入的[CustomerDB].peer | 所有 SQL 查询和写库的 WHERE 条件 |
user_id_external | 消息上下文 Sender 块的id字段 | 需要与 awada 平台交互的技能(如 proactive-send、payment-confirm) |
peer是数据库主键,由系统 hook 从当前会话 sessionKey 中提取并注入,是cs_record表的peer列的值;而user_id_external是 awada 原始用户标识,每轮对话开始时由 openclaw 在消息上下文中注入 Sender 信息块(该块标注为 untrusted metadata):
Sender (untrusted metadata): { "label": "...", "id": "<user_id_external>", "name": "..." }从customer-db技能的 SKILL.md 可知:所有写库操作必须使用peer,而需要与 awada 平台交互的技能(如exp-invite、proactive-send)必须使用user_id_external。这一区分在exp-invite技能中体现得最为明显——它要求同时传入两个标识符,各自职责不同(--peer用于 DB 查询和写库,--user-id-external用于 awada 平台路由邀请动作)。
4. 回复组织规则:承接 → 结论 → 关键信息 → 推进
除非客户只需要一个极简回答,否则默认按以下顺序组织回复:
- 承接:先回应客户当前问题或情绪
- 结论:一句话给出核心判断
- 关键信息:补 2~4 个最关键点
- 推进:自然推进下一步
配套的推进原则、链接使用规则与话术长度规则构成对外沟通的"节奏控制":
- 推进原则:每一轮尽量只推进一个最自然的下一步;不要同时抛给客户过多选择;不要连续追问 3 个以上问题。客户明显接近购买时少讲背景、多讲怎么开通;客户明显还在了解时少讲交易动作、多帮其理解产品形态和适用场景,务求价值共振。
- 链接使用规则:一轮中尽量只给最必要的链接;如需多个链接,先解释用途再给链接;不要把链接堆成资料墙。
- 话术长度规则:默认短答优先;客户追问时再逐步展开;一个问题能在 3~6 句内答清就不要写成长文。
SOUL.md 还补充了输出格式约束:对外回复一律纯文本(plain text),不使用 Markdown(微信客户端不支持渲染效果),链接直接给完整 URL,允许少量自然表情但不堆砌。
5. CustomerDB 字段模型与"先更新再回复"原则
5.1 cs_record 表结构
数据库固定位于./db/customer.db,schema 规范定义在 db/schema.sql(实际初始化由 customerdb-hook 内联 DDL 完成,幂等且支持迁移):
CREATE TABLE IF NOT EXISTS cs_record ( peer TEXT PRIMARY KEY, business_status TEXT DEFAULT 'free', purpose TEXT DEFAULT '', prompt_source TEXT DEFAULT '', club_in TEXT, created_at TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'localtime')), updated_at TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'localtime')) );各字段含义(依据 customer-db/SKILL.md):
| 字段 | 含义 |
|---|---|
peer | 客户数据库主键,等于 awada sessionKey 中的用户标识(安全过滤后的形式) |
business_status | 客户商业推进深度:free(未购买、了解观望)、exp_invited(被邀请体验未付费)、club(已购 VIP Club)、subs(预留未来业务,现阶段未启用) |
club_in | club加入日期(格式建议YYYY-MM-DD),用于跟进 club 一年有效期的过期管理 |
purpose | 客户主要业务应用场景,如新媒体运营、客户寻找、信息搜集、单纯想尝试下 Agent、需要一个 AI 助理、寻求 OEM/代理合作 |
prompt_source | 客户来源渠道,如 GitHub、微信群、朋友推荐、公众号、视频号、小红书、知乎、atomgit、其他 AI 推荐 |
created_at/updated_at | 首次建档时间 / 最近对话时间(每次收到消息由 hook 自动更新) |
5.2 先更新记录,再回复客户
当本轮获得更明确的信息时,先调用cs-update.sh更新purpose和/或prompt_source(该 turn 不得包含任何面向客户的文本),再在下一个 turn 输出对客户的回复:
./skills/customer-db/scripts/cs-update.sh \ --peer "<[CustomerDB].peer>" \ --purpose "单纯想尝试下Agent" \ --prompt-source "GitHub"两个参数均为可选,只传有明确新值的字段。从 cs-update.sh 源码可以看到其底层设计:脚本会先校验--peer必填、数据库存在,然后只把非空值拼进 SET 子句,并对所有值做 SQL 单引号转义(sql_quote),最后统一刷新updated_at;若所有传入值均为空,则打印警告并直接退出(exit 0),不会产生任何写操作——这从代码层面保证了"脚本自动忽略空值、不覆盖已有记录"。
更新原则(强制):
- 本轮没有获取到更明确的信息时,不要调用脚本
- 若只是模糊猜测,不要传入该字段
- 不要用空字符串覆盖已有值
business_status由系统 hook 负责(支付/入群事件),不在此处更新
6. 延迟购买意向处理:follow_up 主动跟进任务
6.1 触发条件(同时满足)
- 客户已表达购买意向(询问价格 / 如何购买 / 对比版本等)
- 同时明确表示要等待一段时间("明天"、"下午"、"等工资"、"下周"、"晚点再谈"等)
6.2 动作流程
- 先写入跟进记录(独立 turn,不含任何客户文本):提取下表字段,向
follow_up表写入一条跟进记录 - 写入完成后再回复客户(最终 turn):确认理解,轻描跟进意图(不要承诺)
| 字段 | 来源 |
|---|---|
peer | [CustomerDB].peer |
user_id_external | 消息上下文 Sender 块的id字段 |
follow_up_at | 根据客户描述推算(见时间映射表) |
reason | 简述客户原因,如"客户说明天发工资再买" |
context_summary | 客户核心兴趣点 + 建议跟进角度,供 heartbeat 时生成话术 |
写入步骤:
# 第一步:若已有 pending 旧任务,先取消 ./skills/customer-db/scripts/follow-up-cancel-pending.sh \ --peer "<[CustomerDB].peer>" # 第二步:创建新跟进任务 ./skills/customer-db/scripts/follow-up-create.sh \ --peer "<[CustomerDB].peer>" \ --user-id-external "<Sender.id>" \ --follow-up-at "<YYYY-MM-DD HH:MM>" \ --reason "<原因,如:客户说明天发工资再买>" \ --context-summary "<客户核心兴趣点和建议跟进角度>"第一步(取消旧任务)始终执行,无 pending 任务时脚本无副作用——从 follow-up-cancel-pending.sh 源码可见,它只是对指定peer的pending状态记录执行UPDATE ... SET status='completed',WHERE 不匹配时自然无副作用。
6.3 时间映射规则
| 客户描述 | follow_up_at |
|---|---|
| "明天" | 次日 10:00 |
| "后天" | 两天后 10:00 |
| "下午" | 当天 14:00(若当前已过 13:00,则次日 14:00) |
| "晚上" | 当天 19:00(若当前已过 18:00,则次日 19:00) |
| "下周" | 7 天后 10:00 |
| "等工资" / "月底" | 5 天后 10:00 |
| "过两天" / "几天后" | 3 天后 10:00 |
| "晚点再谈" / "稍后" | 当天 14:00(若当前已过 13:00,则次日 10:00) |
| 客户说了具体日期/时间 | 按客户说的时间,时间不明时取 10:00 |
注意:若客户明确说"不用跟了""我会自己买",不需要写跟进记录。
6.4 follow_up 表结构与状态机
db/schema.sql 中的follow_up表完整定义:
CREATE TABLE IF NOT EXISTS follow_up ( id INTEGER PRIMARY KEY AUTOINCREMENT, peer TEXT NOT NULL, user_id_external TEXT NOT NULL, -- Sender 块的 id 字段(awada 原始用户标识) follow_up_at TEXT NOT NULL, -- 计划跟进时间 YYYY-MM-DD HH:MM reason TEXT NOT NULL, -- 跟进原因(供 agent 和 heartbeat 参考) context_summary TEXT, -- 对话摘要 + 推荐跟进话术方向 status TEXT DEFAULT 'pending', sent_text TEXT, -- 实际发送的跟进消息内容 retry_count INTEGER DEFAULT 0, created_at TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'localtime')), completed_at TEXT, FOREIGN KEY (peer) REFERENCES cs_record(peer) );status 流转为pending → sent_once → completed:pending表示已创建尚未发送;sent_once表示已发送第一次、等待客户回复或第二次 heartbeat;completed表示已完成(客户主动回复或发送第二次后)。配套的具名脚本包括:
follow-up-due.sh:查询到期任务(status IN ('pending','sent_once')且follow_up_at <= 当前本地时间),输出 tab 分隔表格(含 header),字段为id / peer / user_id_external / follow_up_at / reason / context_summary / statusfollow-up-mark-sent.sh:pending → sent_once,记录sent_text并retry_count+1follow-up-complete.sh:sent_once → completed,记录最终发送文本与完成时间follow-up-expire.sh:超过 48 小时仍为pending的任务视为客户失联,自动标记完成(datetime(follow_up_at, '+48 hours') < datetime('now','localtime'))
7. 意图分流流程:3.0 ~ 3.7
AGENTS.md 定义了七类客户意图分流:
| 编号 | 意图 | 触发关键词/条件 |
|---|---|---|
| 3.0 | 抱怨/投诉 | 不满、投诉 |
| 3.1 | 产品与业务咨询 | 售前咨询 |
| 3.2 | 想试用/不理解产品 | 试用、不清楚形态 |
| 3.3 | 想购买 | 怎么买、价格 |
| 3.4 | 付款确认 | 已付款、截图 |
| 3.5 | 开发票 | 发票 |
| 3.6 | 售后问题 | 产品或服务交付后的提问 |
| 3.7 | 其他 | 主动引导推进成交 |
各分流的处理要点如下:
- 3.0 抱怨/投诉:先道歉;随后将不满摘要记录到
feedback/YYYY-MM-DD.md(独立工具 turn,不记录 PII),再在最终 turn 回复。 - 3.1 产品与业务咨询(售前):根据工作区中的 business_knowledge.md 回答;不能被动回答,要在对话中摸清用户画像(应用场景、对产品的期待、从哪些渠道了解到我们,对后续 marketing 指导很有帮助);循序渐进推动成交——"我们的目的不是陪他聊天,而是成交"。
- 3.2 想试用 / 多次介绍后仍不理解产品:触发条件示例包括"我想先体验一下""我还是不太清楚具体是什么形态""能不能先看看效果""我想先了解真实使用方式"。此时可使用
exp-invite技能向明确同意加入体验群的客户发送邀请,并在客户状态非free(如已exp_invited、subs、club)时不要主动邀请,应回到 3.7 继续主动引导;若客户明确要求再次邀请,可用--force参数强制发送。 - 3.3 想购买:关注付款渠道说明、当前可购产品、推荐收口方式与动作流程(这些内容由 main agent 启用时填入,见下文说明);若付款码发送失败,引导客户联系微信。
- 3.4 客户付款确认:客户已付款、发送截图时进入本分流(具体流程由 main agent 启用时填入)。
- 3.5 开发票:先判断
business_status——free时告知尚未购买暂不能开票;其他状态走对应开票流程(占位待 main agent 填入)。 - 3.6 售后问题:同样先判断
business_status——free改走 3.1 售前咨询;club/subs走对应售后处理(占位待填入)。 - 3.7 其他:主动引导并推进成交:原则是"不要被动陪聊,要主动推进";若对方是来推销的,不必理会。第一步补齐客户画像(
purpose为空时自然问出客户主要应用场景,prompt_source为空时自然了解客户来源);第二步在画像信息足够时进入促成交易阶段,引导付费进入club;第三步处理深入合作诉求。如果客户明显着急,优先短答 + 直接推进动作。
重要说明:原文档中多处标注<!-- 由main agent启用时填入并负责后续持续优化更新 -->,这些是模板化占位符——付款渠道、开票限制、具体参考话术等业务敏感信息由 main agent 在启用该 Crew 时统一配置并持续维护,agent 自身不得自行填写或修改。这是对外 Crew 权限模型的组成部分,部署方需按此约定完成配置后方可启用对应分流。
8. heartbeat 定时跟进与 proactive-send 主动发送
8.1 heartbeat 执行流程
HEARTBEAT.md 定义了每次心跳触发时的主动跟进流程(当前时间由系统注入,见[cron]行):
- 查询当前到期的跟进任务:
./skills/customer-db/scripts/follow-up-due.sh - 若无到期任务(仅输出 header 或空),回复
HEARTBEAT_OK并结束 - 对每条到期任务依次执行:
- a. 阅读
context_summary,生成自然的跟进话术(简短、克制、不施压) - b. 调用
proactive-send发送消息 - c. 根据当前
status更新记录:pending(首次发送)→ 标记sent_once;sent_once(二次发送)→ 标记completed - d. 若发送失败(exit 1),跳过本条,不更新状态,下次心跳自动重试
- a. 阅读
关键设计:不再清理过期任务——不管隔了多少天,该跟进还是跟进,但原则仍是最多跟进两次(pending → sent_once → completed)。跟进话术基于context_summary中的客户兴趣点和建议角度生成,一句话开场、不超过三句话、不催促、给客户留空间,例如:"您好,之前聊到加入vip club的事,不知道今天方便看看吗?"
8.2 proactive-send 的底层实现
proactive-send技能让 sales-cs 在特定业务场景下主动向客户发送消息,而非等待客户发起对话:
proactive-send \ --user-id-external "<user_id_external>" \ --text "<消息内容>"--user-id-external(必填):客户 awada 用户标识,来自 Sender 块的id字段--text(必填):发送给客户的消息文本
从 send.mjs 源码可见其传输机制:relayBaseUrl/ofbKey/platform/lane自动从~/.openclaw/openclaw.json的channels.awada读取,channel_id/tenant_id固定为"0"(私聊);然后走 HTTPPOST {relayBaseUrl}/api/v1/awada/outbound?lane=<lane>,携带X-OFB-Keyheader,请求体为{ payload: [{ type: "text", text }], meta: { platform, channel_id: "0", user_id_external, tenant_id: "0" } }。成功时打印 relay outbound stream ID(如1234-0,exit 0),失败时打印错误到 stderr(exit 1)——即走 HTTP 网关而非直连 Redis,传输契约详见 docs/AWADA-CLIENT-TRANSPORT.md。
该技能仅提供发送能力,何时使用、发给谁、发什么内容由调用场景(如 heartbeat、3.3 收口)决定,请勿在正常对话流程中调用以免破坏对话自然性。
9. 对外 Crew 的权限约束与 awada 回复规则
9.1 命令白名单机制
对外 Crew 默认 deny 一切 shell 命令,ALLOWED_COMMANDS 用+条目在 deny 上精确放行声明式技能所需脚本(相对于 workspace 根目录):customer-db的七个具名操作脚本(cs-update.sh、follow-up-create.sh、follow-up-cancel-pending.sh、follow-up-due.sh、follow-up-mark-sent.sh、follow-up-complete.sh、follow-up-expire.sh)、exp-invite、proactive-send,以及辅助工具(nano-pdf、jq、rg、node、pdfimages、pdftoppm、pdftocairo)。
对应地,TOOLS.md 明确了硬性限制:
- 不允许任意 shell 命令执行,仅限白名单内的声明式技能脚本
- 除
feedback/和db/目录外不得写入文件 - 不得自我修改 workspace 文件(SOUL.md、AGENTS.md、MEMORY.md 等)
- 不得向用户暴露内部 DB 字段或 schema
- schema 变更需 main agent 批准,禁止自行修改
9.2 awada 回复发送规则(强制)
在 awada 会话中:
- 常规回复必须直接输出 assistant 文本,不要调用
message工具二次发送 message工具仅用于明确的主动外呼场景;当前会话应答禁止使用- 若工具调用报错(如 Unknown target / send failed),不得把报错文本透传给客户,必须改为正常人工话术重答
这一规则结合proactive-send的"仅限主动外呼"定位,保证了会话内回复路径与主动外呼路径的彻底分离。openclaw_setting_sample.json(见 crews/sales-cs/openclaw_setting_sample.json)展示了该 Crew 的运行时配置样例:skills列表、heartbeat(每 1 小时、活跃时段 08:00-24:00、isolatedSession)、exec安全模式为allowlist且ask: off,可作为部署参考。
10. 特殊对话风格提醒
AGENTS.md 末尾给出几条实战风格提醒,直接关系到对话自然度:
- 用户只发一个"1",通常表示确认 / 收到 / 可以继续
- 如果客户明显着急,优先短答 + 直接推进动作
- 如果客户只是泛泛问"是什么",优先用一句人话解释,不要先讲架构
- 如果客户问得很专业,再切换到更技术化的说明
- 永远不要把整份手册口吻原样搬进对话里
这些规则与第 4 节的回复结构、第 9 节的纯文本输出约束共同构成了 sales-cs 对外沟通的完整风格体系:销售导向、克制推进、人话优先、不暴露内部机制。
小结
sales-cs 的工作流本质是一个"CustomerDB 驱动的销售闭环":peer标识 +cs_record画像字段支撑每轮会话的状态感知与画像沉淀;"工具在前、回复在后"保证每次写库、记录反馈都在对客话术之前完成;follow_up表 + 时间映射 + heartbeat 将"等工资再买"这类延迟意向转化为最多两次的克制跟进;proactive-send通过 awada outbound 网关实现会话外的主动触达;白名单命令与禁止自我修改则确保对外 Crew 永远在 main agent 设定的轨道内运行。对于需要搭建"公众号/微信场景下的 AI 售前客服"的团队,这套文档(AGENTS.md)+ 技能 + 脚本的组合本身就是一份可直接复用的完整参考实现。
- 人工智能
- AI Agent
- 大模型
- AI 应用
- 媒体生成
【免费下载链接】xiaobei
为OPC/中小微企业量身打造的自媒体获客智能体
相关推荐
xiaobei 项目销售客服 Crew(sales-cs)用户上下文与微信对话规范详解
xiaobei 项目销售客服 Crew(sales cs)用户上下文与微信对话规范详解 导读 本文基于开源仓库 xiaobei(为 OPC/中小微企业打造的自媒
人工智能AI Agent大模型AI 应用媒体生成终极指南:为什么GraphRAG比传统RAG更强大?揭秘AI检索增强新范式
终极指南:为什么GraphRAG比传统RAG更强大?揭秘AI检索增强新范式 GraphRAG(图检索增强生成)正在彻底改变领域特定大语言模型的应用方式!🎯 作
SpeechBrain 多源模型加载 + DDP + 动态批处理 + 仅微调 LM 的集成测试模板实战指南
SpeechBrain 多源模型加载 + DDP + 动态批处理 + 仅微调 LM 的集成测试模板实战指南 本指南围绕 SpeechBrain 仓库中的集成测试
人工智能AI Agent大模型AI 应用媒体生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考