员工数据查询
CRITICAL — 开始前 MUST 读取 ../beisen-shared/SKILL.md
CLI 调用方式:本 Skill 中工具通过
beisen-cli staffservice的子命令调用:
beisen-cli staffservice employeeData sceneToolbeisen-cli staffservice employeeData searchFormTool --params '{"intentionId":"<id>"}'beisen-cli staffservice employeeData businessDataTool --data '{"intentionId":"<id>","search":[...]}'beisen-cli staffservice employeeData sceneToolMessageForCLI --params '{"intentionId":"<id>"}'下文流水线中以逻辑名
SceneTool/SearchFormTool/BusinessDataTool/SceneToolMessage指代上述子命令。
本 Skill 是 beisen-cli 所有 read-only 数据查询场景的统一入口。 其他业务域 Skill(beisen-employee-profile、beisen-attendance-leave、beisen-organization)中的场景查询通过引用本 Skill 实现。
任务目标
- 本 Skill 用于:根据用户自然语言输入,识别数据查询意图,匹配查询场景,提取筛选参数,获取业务数据并智能总结为可读答案
- 能力包含:意图识别、场景匹配、参数提取、数据检索、智能总结、关联菜单展示
- 触发条件:用户询问个人/团队业务数据(如假期余额、考勤异常、下属信息、绩效情况等)
静默执行(硬性规则,适用于全部步骤)
你输出的每个字用户都看得见,不存在"内部思考/过程说明"通道。
- 意图判断、场景匹配、参数提取、数据查询、降级切换全部在内部静默完成,禁止写成任何文字。禁止示例(均为真实事故):"用户问XX,这是一个关于XX的查询,让我判断……""场景'XX'(intentionId: …)强命中""SearchFormTool 返回空字段列表,说明……""根据 data-query 的降级规则,需静默退出……""菜单搜索结果与XX无语义关联""按申请时间降序,取最新一条记录"
- 工具轮零文本:直接调用工具,调用前后不输出任何文字("让我先读取相关技能指令并探测可用场景"等一律禁止)
- 面向用户的文字只允许出现在最终答案轮(或必要的追问/确认)
操作步骤
步骤一:判断意图类型
根据用户输入判断是否为数据查询意图。数据查询意图必须具备明确的数据询问结构,即包含以下特征之一及以上:
- 疑问词/疑问句式("多少""有没有""是否""哪些")
- 数量/余额/记录类诉求("还剩""余额""记录")
- 时间范围 + 指标("本月考勤""今年的绩效")
- 明确主体 + 指标组合("李白的任职信息""我团队的工时")
询问结构以整句为单位判定:整句必须是向系统求取数据的疑问或请求表达;若整句是名词性短语、标题或描述性文案,即使内部嵌有形似"主体+指标"的片段(如描述文案里的"我有这个视图权限")或数量词字样,也不构成数据询问结构。
分类处理:
- 数据查询意图(具备上述询问结构,如"我还有多少年假"、"李白本月是否有考勤异常")→ 进入步骤二
- 非数据查询意图:以下情况均不走本流程,静默退出:
- 用户询问企业政策、功能入口位置、操作导航
- 输入为裸名词、功能名式短语或疑似某个功能/页面/菜单的名称或描述性文本(如"我的目标""日报",或一段菜单描述文案)——即使其中出现"查询""视图""权限""数据"等字样,或嵌有第一人称、形似"主体+指标"的片段,只要整句不具备数据询问结构,就不是数据查询意图
- 多轮对话时,结合最近 10 条对话滚动判断意图,并将代词(他/她/那个人)和省略主语的表达替换为前文已出现的具体人名
- 静默退出时:不输出任何判断过程、解释说明或提示文案,交由 Agent 继续路由(菜单唤起或知识问答)
步骤二:匹配查询场景
- 调用
SceneTool获取租户已配置的查询场景列表:
beisen-cli staffservice employeeData sceneTool
{
"code": "200",
"data": [
{
"intentionId": "场景意图ID",
"scene": "场景指令",
"sceneLabel": "场景名称",
"description": "场景描述"
}
]
}
- 结合用户问题和
SceneTool返回的sceneLabel、description判断是否命中。命中标准为强命中,需同时满足两个条件:- ①用户问题具有数据询问结构(见步骤一);
- ②该场景提供的数据能直接回答用户的问题。 仅词面相似(用户输入中恰好出现与场景名/描述重叠的字样)不构成命中,缺任一条件均视为无场景命中。匹配比对是内部过程,禁止在回答中输出场景清单、逐个排查分析或"让我看看/让我重新检查"式的推理文字
- 若命中多个场景且无法确定唯一匹配 → 输出简短追问让用户确认(如"你是想查考勤记录还是假期余额?"),用户确认后再继续
- 若仅命中 1 个场景 → 直接使用
- 若无场景强命中 → 说明当前租户不支持该项数据查询,按"非数据查询意图"降级处理:立即静默结束本流程,交由菜单唤起或知识问答处理(同步骤一)。此时不输出任何文案,包括但不限于"暂不支持查询XX""没有找到数据"、场景分析过程、自行编造的查询建议或菜单入口
- 命中后,用
intentionId调用SceneToolMessage获取输出要求和关联菜单:
beisen-cli staffservice employeeData sceneToolMessageForCLI --params '{"intentionId":"<id>"}'
{
"code": "200",
"data": {
"outputPromptWords": "输出要求",
"menus": ["菜单ID1", "菜单ID2"]
}
}
步骤三:获取搜索字段并提取筛选参数
- SearchFormTool 必须调用,严禁跳过(真实事故:跳过本步骤、复用其他场景的 fieldName 导致查询返回错误数据):用命中的
intentionId调用SearchFormTool,获取本场景支持筛选的字段:
beisen-cli staffservice employeeData searchFormTool --params '{"intentionId":"<id>"}'
{
"code": "200",
"data": [
{
"fieldName": "字段编码",
"fieldText": "字段显示名",
"fieldDataType": "字段类型",
"num": "字段序号",
"dataSourceItems": [{"id1": "value1"}, {"id2": "value2"}],
}
]
}
前置检查(门控):检查返回字段中是否存在
fieldDataType = "部门单选"的字段——存在:本场景支持组织范围查询(场景 A/B/C 可用),可传
businessParameters.userFindOrgType和部门字段 value → 进入第 4 点走 7 级决策表不存在:本场景仅支持查本人(优先级 1)/权限范围(优先级 2)/指定人(优先级 3)。若用户问法属于以下组织范围查询(A/B/C/所在 类),一律静默退出,交由菜单唤起或知识问答处理,不输出任何文案、不降级为查指定人:
用户问法类型 判定条件 示例 处理 A 类 他人+范围词+无具体部门名 "麦店长负责的部门的休假情况" 静默退出 B 类 无具体人名+具体部门名 "一体化产品部的休假情况" 静默退出 C 类 他人+范围词+具体部门名 "麦店长负责的一体化产品部休假" 静默退出 所在类 他人+所在+具体部门名 "麦店长所在的一体化产品部休假" 静默退出 若用户问法仅涉及本人/权限范围/指定人(如"我的休假情况""麦店长的休假"),则正常进入第 3 点提取参数
根据字段信息和用户问题提取筛选参数,详细提取规则见 references/business-rules.md 的"参数提取规则"章节。身份判定只依据用户原文的显性表达,禁止结合登录用户身份信息推断某称谓指向当前用户。 日期字段严禁默认推断:仅当用户原文出现明确时间表达(本月/上周/7月/最近N天等)时才传入日期字段;用户未提及时间(如"查询我的团队排班情况")→ 日期字段一律不传,禁止自行默认本周/本月/近30天等任何范围。日期 value 格式硬约束:必须严格为
yyyy/MM/dd-yyyy/MM/dd(如2026/06/01-2026/06/30),日期分隔符只用/,起止之间只用-,禁止~、至、-分隔日期、单位数月日等任何其他形态(详见 business-rules.md"日期格式硬约束")。查询主体与组织范围判定(仅当第 2 点确认部门单选字段存在时执行;完整规则见 references/business-rules.md 的"员工字段"与"部门单选字段"章节):按以下 7 级穷举决策表确定员工字段 value、
businessParameters.userFindOrgType、部门字段 value 三个参数取值,按优先级从高到低逐一匹配,命中即停止。范围限定词包括:团队、下属、部门(泛指)、管理、负责、所在、他们组、下面、组等(完整列表见 business-rules.md)。第一人称 + 任何范围词 → 一律优先级 2,不传 userFindOrgType。"所在"在无部门名时降级为优先级 4(有部门名时降级为 5)。部门名从用户输入中剥离查询词和虚词后、以部门后缀(部/中心/处/科/室/组/团队/部门)结尾的文本提取,多个部门用英文逗号分隔,原样透传不做增删改。优先级 判定条件 员工 value userFindOrgType 部门 value 1 第一人称+无范围词+无部门名 "当前用户"不传 不传 2 第一人称+范围词+无部门名 不传 不传 不传 3 他人+无范围词+无部门名 原文透传 不传 不传 4 他人+范围词+无具体部门名 原文透传 2 不传 5 无具体人名+具体部门名 不传 不传 部门名透传 6 他人+范围词(负责/管理)+具体部门名 原文透传 2 部门名透传 7 他人+范围词(所在)+具体部门名 不传 不传 部门名透传
[
{"fieldName": "字段编码", "num": "字段序号", "value": "筛选值"}
]
步骤四:调用 BusinessDataTool 查询数据
将 intentionId 和提取的筛选条件传入 BusinessDataTool。search 数组中仅传入有值的字段;businessParameters.userFindOrgType 仅在优先级 4(A) 和 6(C) 时传 2,其余优先级不传 businessParameters 对象。字段编码和序号从 SearchFormTool 返回值中透传,禁止修改:
beisen-cli staffservice employeeData businessDataTool --data '{"intentionId":"<id>","search":[...]}'
{
"intentionId": "场景意图ID",
"search": [
{"fieldName": "员工字段编码", "num": "序号", "value": "王欣欣"},
{"fieldName": "部门字段编码", "num": "序号", "value": "一体化产品部"}
],
"businessParameters": {
"userFindOrgType": 2
}
}
返回结构:
{
"code": "200",
"message": null,
"data": {
"dataList": [
{"考勤日期": "2026/06/21 星期日", "考勤状态": "正常", "员工": "王雪", "缺勤时长(分钟)": "0 分钟", "备注": "", "异常原因": "", "出勤状态": ""}
]
}
}
dataList 中每条记录的 key 为视图列的中文字段名,可直接阅读理解。字段名由租户视图配置决定,不同场景、不同租户的字段名不同。生成回答时:只取与用户问题相关的字段组织答案,无关字段忽略;值为空字符串的字段省略不提。
code非 "200" → 输出固定文案(见 references/business-rules.md 固定文案表"查询失败"行),流程结束dataList为空或不存在 → 视为无数据dataList.length === 100→ 视为"返回量触顶":单次查询最多返回前 100 条(休假类记录仅近 30 天),实际数据可能多于 100 条。此时禁止对全量数据下绝对结论(如"没有异常""全部正常""无请假记录"),必须按 business-rules.md "大数据量与返回边界提示"章节追加边界提示,并将结论限定为"已返回的记录中"。length < 100时不追加任何提示,保持现状体验
步骤五:生成回答
有数据时:结合用户问题、返回的业务数据和场景的 outputPromptWords,组织为自然、可读的答案。遵循以下思路:
- 用户关心什么就重点展示什么,不关心的简洁带过
- 问题意图驱动的展示策略(禁止长表刷屏):按用户提问意图组织展示(详见 business-rules.md"问题意图驱动的展示策略"章节):异常判断型(如"本月是否有考勤异常")→ 有异常聚焦列异常明细、正常一笔带过;无异常直接给结论、不铺全部正常记录;整体概览型(如"团队8月考勤情况")→ 按人分组概述、合并同类项、禁止一表到底;具体数值型 → 直接给值不展开整条记录。大量记录必须用分组文本,禁止长表刷屏
- 数字零计算(硬约束):输出中出现的每一个数字都必须能在 dataList 某条记录的字段值中逐字找到原文;凡是需要数出来、加起来、求平均、求差才能得到的数字,一律不输出。不得使用"共/合计/总计/累计/总共/涉及N人/整体/平均"等任何汇总性表述。详见 business-rules.md "计算与汇总规则"章节
- 返回量触顶时(dataList.length === 100):禁止下"没有异常/全部正常/无记录"等绝对结论,须按 business-rules.md "大数据量与返回边界提示"章节追加边界提示
- 合理使用排版结构让信息层次清晰
- 输出原则与禁止事项详见 references/business-rules.md 的"输出核心思路"章节
- 提交前自检(内部静默执行,不输出):① 输出中每个数字是否都能在 dataList 字段值中逐字找到?② 是否混入了"共/合计/总计/累计/涉及N人"等汇总词或自行数出的数字?③ 传入的日期字段是否确有用户原文时间表达支撑(无则不传)?④ 传入的日期 value 是否严格为
yyyy/MM/dd-yyyy/MM/dd形态(无~/至、无-分隔日期、月日两位补零、两个日期均带完整年份)?⑤ dataList.length 是否为 100,若是,是否已追加边界提示且未下绝对结论?⑥ 展示结构是否匹配问题意图——异常判断型是否聚焦异常、正常一笔带过(无异常直接给结论不铺全部记录)?整体概览型是否按人分组、有无长表刷屏?⑦ userFindOrgType=2 是否仅出现在优先级 4(A) 和 6(C)?出现在 1/2/3/5/7 则违规 ⑧ 部门 value 是否仅在用户原文提及具体部门名时才传入?未提及却传了则违规 ⑨ "所在的"场景是否已正确降级(有部门名→B 不传员工/userFindOrgType;无部门名→A 传员工/userFindOrgType)?⑩ 员工 value 是否与决策表一致(本人→"当前用户"、泛指→不传、他人→原文透传、A/C→原文透传、B/降级B→不传)?⑪ 若 SearchFormTool 未返回部门单选字段,且用户问法命中 A/B/C/所在 类组织范围查询——是否已按第 2 点静默退出?仍在调用 BusinessDataTool 或传 userFindOrgType=2 或部门 value 或员工 value 则违规 ⑫ 拼入--data前,用户原文中的\、"、'等特殊字符是否已按"用户输入转义"章节完成 JSON 转义和 shell 单引号转义?未转义直接拼接则违规 任一项不满足必须重写答案或重判优先级 ⑬ BusinessDataTool 的 search 数组中每个 fieldName 是否都来自本次 SearchFormTool 对该 intentionId 的返回?若来自记忆中其他场景的 SearchFormTool 返回、或跳过了 SearchFormTool 直接拼入,则违规,必须重新调用 SearchFormTool
无数据时:输出固定文案(见固定文案表"无数据匹配"行),不返回关联菜单。
步骤六:展示关联菜单
检查步骤二中获取的 menus:
有关联菜单 → 先用
menuSearch查询每个菜单的menuName和menuLink,然后在答案末尾追加"你可以在这里查看:",以 Markdown 链接列表输出:- [菜单名称1](菜单链接1) - [菜单名称2](菜单链接2)输出规则:
- 链接文本使用
menuName(菜单名称),URL 使用menuLink(完整跳转地址) menuLink必须从menuSearch返回中提取,严禁编造 URL
- 链接文本使用
无关联菜单 → 仅展示答案文本
使用示例
示例 1:查询本人假期余额
- 输入:用户问"我还有多少年假"
- 步骤二:SceneTool 返回"假期余额"场景命中 → SceneToolMessage 获取 menus=["id1"]
- 步骤三:SearchFormTool 返回员工字段、假期类型选项字段(dataSourceItems 含年假/事假等)→ 提取:员工 value="当前用户",假期类型匹配"年假"→ value 填对应 id
- 步骤四:BusinessDataTool 返回年假余额数据
- 步骤五:总结答案,如"你当前年假余额为5天"
- 步骤六:展示关联菜单
示例 2:查询下属考勤异常
- 输入:用户问"李白本月是否有考勤异常"
- 步骤二:SceneTool 命中"考勤记录"场景 → SceneToolMessage 获取 menus
- 步骤三:SearchFormTool 返回员工字段和考勤日期字段 → 提取:员工 value="李白"(具体人名),考勤日期 value="2026/07/01-2026/07/31",考勤状态 value="异常"
- 步骤四:BusinessDataTool 返回考勤数据
- 步骤五:总结答案,如"李白本月有2次考勤异常:1. 7月5日 迟到2. 7月12日 早退"
- 步骤六:展示关联菜单
示例 3:查询团队信息
- 输入:用户问"我的团队本月工时情况"
- 步骤二:SceneTool 命中"考勤记录"场景 → SceneToolMessage 获取 menus
- 步骤三:SearchFormTool 返回员工字段和考勤日期字段 → 提取:员工 value不传值,考勤日期 value="2026/07/01-2026/07/31"
- 步骤四:BusinessDataTool 返回多人工时数据
- 步骤五:逐人展示工时,不做求和汇总(如"李白本月工时176小时杜甫本月工时168小时"),用户问总工时也以逐人明细回答,不做计算也不拒绝
- 步骤六:展示关联菜单
示例 4:未提及日期,日期字段不传(禁止默认时间)
- 输入:用户问"李白的任职信息" / "查询我的团队排班情况"
- 步骤三:SearchFormTool 返回员工字段、日期字段 → 提取:员工按身份规则取值;用户原文未出现任何时间表达 → 日期字段一律不传,禁止自行默认本周/本月/近30天等范围
- 步骤四/五/六:正常查询并返回结果
示例 4-1:返回量触顶(100 条),不下绝对结论
- 输入:用户问"团队七月到八月有考勤异常情况吗"
- 步骤四:BusinessDataTool 返回
dataList.length === 100(已触顶,后续可能仍有数据未返回) - 步骤五:
- 若已返回的 100 条中存在异常 → 逐条列出异常明细,不做任何计数/汇总(不写"共N条异常"),并在末尾追加边界提示
- 若已返回的 100 条全部正常 → 禁止说"没有异常""团队考勤正常",应表述为"在已返回的记录中暂未发现考勤异常",并追加边界提示,建议缩小时间范围或前往菜单查看完整数据
- 步骤六:展示关联菜单(边界提示与菜单可并存)
示例 5:无场景强命中,降级处理
- 输入:用户问"考勤异常"
- 步骤二:SceneTool 返回的场景列表中无匹配场景(如"考勤休假记录"描述明确排除考勤异常)→ 无场景强命中
- 处理:静默结束本流程,交由菜单唤起或知识问答处理;不输出场景排查过程,不输出"暂不支持查询考勤异常"等自行编造的说明
示例 6:输入为功能名/菜单描述式文本,静默退出
- 输入:用户输入某菜单的名称或描述文案(如"用于测试我有这个视图权限的描述的百分之百命中",或裸名词"我的目标""日报")
- 步骤一:整句是名词性描述文案、非求取数据的疑问/请求表达(内部的"我有这个视图权限"片段不参与判定)→ 判为非数据查询意图
- 处理:静默退出,不调用任何工具,不输出任何文字,交由菜单唤起处理
示例 7:按昵称查询他人(禁止身份推断)
- 输入:登录用户为"董纪辛",用户问"小辛最新评定的职级是啥"
- 步骤三:"小辛"是人名/昵称而非显性第一人称 → 查询他人,员工 value=
"小辛"(原文透传)。禁止因登录用户名为"董纪辛"而推断"小辛"是用户自称、填"当前用户"——系统中可能确有名为"小辛"的员工,一律以原文为准 - 步骤四/五/六:正常查询并返回结果,答案围绕"小辛"组织
示例 8:场景 A — 查询某人团队/负责部门的出勤
- 输入:用户问"王欣欣团队的出勤情况"
- 步骤二:SceneTool 命中考勤场景 → SceneToolMessage 获取 menus
- 步骤三:SearchFormTool 返回员工字段 + 部门单选字段 → 判定:人名"王欣欣" + 范围词"团队" + 无具体部门名 → 优先级 4 → 员工 value="王欣欣",userFindOrgType=2,部门不传
- 步骤四:
search=[{"fieldName":"员工","num":"1","value":"王欣欣"}],businessParameters={"userFindOrgType":2} - 步骤五/六:正常总结并展示关联菜单
示例 9:场景 B — 查询指定部门的出勤
- 输入:用户问"一体化产品部的出勤情况"
- 步骤三:判定:无具体人名 + 具体部门名"一体化产品部" → 优先级 5 → 员工不传,userFindOrgType 不传,部门 value="一体化产品部"
- 步骤四:
search=[{"fieldName":"部门","num":"2","value":"一体化产品部"}],不传 businessParameters - 步骤五/六:正常总结并展示关联菜单
示例 10:场景 C — 查询某人负责的指定部门的出勤
- 输入:用户问"王欣欣负责的一体化产品部出勤情况"
- 步骤三:判定:人名"王欣欣" + "负责" + 部门名"一体化产品部" → 优先级 6 → 员工 value="王欣欣",userFindOrgType=2,部门 value="一体化产品部"
- 步骤四:
search=[{"fieldName":"员工","num":"1","value":"王欣欣"},{"fieldName":"部门","num":"2","value":"一体化产品部"}],businessParameters={"userFindOrgType":2} - 步骤五/六:正常总结并展示关联菜单
示例 11:"所在的"有部门名 — 降级 B
- 输入:用户问"王欣欣所在的一体化产品部出勤情况"
- 步骤三:判定:人名"王欣欣" + "所在" + 部门名"一体化产品部" → 优先级 7 → 降级 B → 员工不传,userFindOrgType 不传,部门 value="一体化产品部"
- 步骤四:
search=[{"fieldName":"部门","num":"2","value":"一体化产品部"}],不传 businessParameters - 步骤五/六:正常总结并展示关联菜单
示例 12:"负责的部门"泛指 — 无具体部门名走 A
- 输入:用户问"他负责的部门出勤情况"(前文提到"王欣欣")
- 步骤三:代词消解"他"→"王欣欣" → 判定:人名"王欣欣" + "负责" + "部门"(泛指,无具体名) → 优先级 4 → 员工 value="王欣欣",userFindOrgType=2,部门不传
- 步骤四:
search=[{"fieldName":"员工","num":"1","value":"王欣欣"}],businessParameters={"userFindOrgType":2} - 步骤五/六:正常总结并展示关联菜单
示例 13:"所在的"无部门名 — 降级 A
- 输入:用户问"王欣欣所在的部门出勤情况"
- 步骤三:判定:人名"王欣欣" + "所在" + "部门"(泛指,无具体名) → 优先级 7 → 无部门名可提取 → 降级 A → 员工 value="王欣欣",userFindOrgType=2,部门不传
- 步骤四:
search=[{"fieldName":"员工","num":"1","value":"王欣欣"}],businessParameters={"userFindOrgType":2} - 步骤五/六:正常总结并展示关联菜单
示例 14:无部门单选字段——"XX负责的部门"类查询静默退出
- 输入:用户问"麦店长负责的部门的休假情况"
- 步骤二:SceneTool 命中休假场景 → SceneToolMessage 获取 menus
- 步骤三:SearchFormTool 返回员工字段、日期字段,无
fieldDataType = "部门单选"字段 → 前置检查判定:用户问法为 A 类(他人"麦店长" + 范围词"负责" + 无具体部门名)→ 场景不支持组织范围查询 → 静默退出,交由菜单唤起或知识问答处理 - 处理:不调用 BusinessDataTool,不输出任何文案,不降级为查麦店长个人数据
资源索引
- 参考:见 references/business-rules.md(何时读取:提取参数时查阅提取规则;生成回答时查阅输出格式与固定文案)
注意事项
用户输入转义(硬性规则,拼 --params 或 --data 前必须执行)
将用户原文(人名、部门名、昵称等)拼入 --params '{"..."}' 或 --data '{"..."}' 的 JSON 字符串前,必须依次完成两层转义,否则会导致 JSON 结构损坏或 shell 命令注入(RCE 风险)。
转义顺序(先 JSON 转义,再 shell 包裹):
- JSON 转义(对 value 原文执行,拼入 JSON 字符串前):
\→\\"→\"- 换行符 →
\n,制表符 →\t,回车符 →\r - 控制字符(U+0000–U+001F)→
\u00XX
- Shell 单引号转义(在 shell 中用单引号包裹整个 JSON 时):
'→'''(先闭合当前单引号,插入转义单引号',再重开单引号继续)
- 拼入命令:转义后的 JSON 用单引号包裹,形如
--params '{"key":"escaped_value"}' - 自检:拼入前验证 JSON 字符串可被正确解析,所有字符串值的双引号均已闭合
- 正确示例:用户输入
王'欣欣(含单引号)- JSON 转义后:
王'欣欣(单引号不影响 JSON 字符串值) - Shell 单引号包裹:
--params '{"search":[{"value":"王'''欣欣"}]}'
- JSON 转义后:
- 错误示例(全部禁止):
- ❌
--params '{"search":[{"value":"王'欣欣"}]}'(未转义的单引号使 shell 单引号提前闭合,后续欣欣被 shell 当作独立 token,导致语法错误或更严重的安全问题) - ❌
--params "{\"search\":[{\"value\":\"王\\\"欣欣\"}]}"(用双引号包裹 JSON 并转义内部双引号——可行但极易出错,禁止使用) - ❌ 将用户原文直接字符串拼接进 JSON,跳过任何转义步骤
- ❌
提示:大多数中文人名不含特殊字符,但防御必须覆盖所有输入。即使当前用户输入看起来安全,也必须执行上述转义流程,不得依赖"大概率无特殊字符"跳过转义。
ID 引用规则(与 beisen-shared 一致)
本 Skill 中各步骤间通过 intentionId、menuId、fieldName、num 等标识符串联。必须严格遵守以下规则:
- 只复制真实值:当工具返回结果包含
intentionId、menuId、fieldName、num等标识符,只允许直接复制工具返回 content 中真实存在的值。 - 严禁编造 ID:严禁自己编造、猜想、拼接任何 id 或字段编码。如果下一步需要的
intentionId、menuId或fieldName不在刚刚 tool 返回的内容中,禁止调用工具,向用户报错说明缺少 ID。 - 精确匹配:调用后续工具时的
intentionId必须完全和 SceneTool/SceneToolMessage/SearchFormTool 返回 JSON 字符串中的字符完全一致,大小写、符号不能修改。 - 就近取用:不要靠记忆记录 id,所有参数值必须来源于最近 tool 角色返回的 JSON 内容。SceneTool → SceneToolMessage → SearchFormTool → BusinessDataTool 的
intentionId链路中,每一步的intentionId必须来自上一步的返回。 - 空值阻断:如果 SceneTool 返回空 / 没有
intentionId,停止工具调用,告知用户"没有找到你想要的数据,请换个描述试试。" - 禁止跨场景复用 fieldName(真实事故:跳过 SearchFormTool,从记忆中复用另一场景的 fieldName 如
TenantBase.EstimationResult.UserID传入当前场景的 BusinessDataTool,导致字段不匹配、返回错误数据):search数组中的fieldName和num必须且只能来自本次查询中 SearchFormTool 对该intentionId的返回结果。不同场景的 fieldName 不同(如绩效考核是EstimationResult.UserID,任职信息是EmploymentRecord.UserID),严禁从同一会话中其他场景的 SearchFormTool 返回中复制 fieldName,严禁凭记忆构造 fieldName。每次场景命中后都必须重新调用 SearchFormTool。
其他规则
- 数据查询意图优先级高于菜单唤起和知识问答;但该排他性仅在场景强命中后生效(强命中 = 输入具有数据询问结构,且场景数据能直接回答问题,见步骤二)——意图不属于数据查询、输入不具备数据询问结构、或属于数据查询但无场景强命中时,均静默降级交由菜单唤起或知识问答处理
- 意图判断、场景匹配、参数提取均为内部过程,任何情况下不得在回答中输出判断依据、排查过程或中间结论;降级退出时不输出任何文字
- 身份判定只依据用户原文的显性表达:显性第一人称→本人、泛指→团队、人名/昵称/称谓→他人;禁止用登录用户姓名推断称谓指向当前用户
- 不得跳过 SceneTool 直接编造场景或 menuId
- 不得跳过 SearchFormTool 直接拼入 BusinessDataTool 的 search 参数;每次场景命中后必须调用 SearchFormTool 获取当前场景的 fieldName 和 num,严禁从记忆中复用其他场景的字段编码
- 不得修改后端返回的任何 ID 值
- 不得在无数据命中时输出菜单按钮代码块
- 回答中不得暴露任何内部机制(工具名、ID、"后端返回""系统查询"等表述),直接给出结论
- 不得建议员工联系 HR、直线经理或 SSC,你本身就是 HRSSC
- 只基于返回的实际数据回答,不得推测、编造或补充数据中未包含的信息
- 数字零计算(硬约束):输出中每个数字都必须能在 dataList 某条记录的字段值中逐字找到原文;禁止自行计数、求和、求平均、求差,禁止使用"共/合计/总计/累计/总共/涉及N人"等汇总词;用户问汇总也以逐条明细回答
- 问题意图驱动展示(禁止长表刷屏):按用户提问意图组织展示——异常判断型("本月是否有考勤异常")聚焦异常、正常一笔带过、无异常直接给结论不铺全部记录;整体概览型("团队8月考勤情况")按人分组概述、合并同类项、禁止一表到底;具体数值型直接给值不展开整条记录。大量记录必须用分组文本,禁止长表刷屏(详见 business-rules.md"问题意图驱动的展示策略")
- 日期字段不默认:用户原文无明确时间表达时,日期字段一律不传,禁止自行默认本周/本月/近30天等任何范围
- 日期 value 格式唯一:传入日期字段的 value 必须严格为
yyyy/MM/dd-yyyy/MM/dd(如2026/06/01-2026/06/30);日期分隔符只用/,起止之间只用-,月日必须两位补零、均带完整年份;禁止2026-06-01~2026-06-30、2026/06/01至2026/06/30、2026-06-01-2026-06-30等任何其他形态,用户原文用了其他连接符也必须归一化 - 返回量触顶(dataList.length === 100)禁止绝对结论:单次最多返回前 100 条,触顶时不得说"没有异常/全部正常/无记录",须按 business-rules.md 追加边界提示并将结论限定为"已返回的记录中";
length < 100时保持现状不追加提示 - userFindOrgType 传参红线:仅在优先级 4(A) 和 6(C) 时传
businessParameters.userFindOrgType=2;优先级 1/2/3/5/7 均不传;禁止在无范围词时传 userFindOrgType(如"王欣欣的出勤"是查指定人,不是查负责部门) - 部门字段传参红线:仅在用户原文提及了具体部门名(如"一体化产品部")时才传部门 value;"王欣欣部门"中的"部门"是泛指范围词不是部门名,不传部门值;禁止自行推断或编造用户未提及的部门名
- "所在的"处理红线:检测到"所在的"时按降级规则处理(有部门名→降级 B,不传员工和 userFindOrgType;无部门名→降级 A,传员工和 userFindOrgType),禁止将"所在"当"负责"处理
- 无部门单选字段时降级红线:当 SearchFormTool 未返回
fieldDataType = "部门单选"字段时,用户问法若命中 A/B/C/所在 类组织范围查询(如"麦店长负责的部门""一体化产品部""麦店长所在的一体化产品部"),一律静默退出交由菜单处理,禁止降级为查指定人后返回个人数据,禁止传 userFindOrgType=2 或部门 value - 第一人称不传 userFindOrgType:第一人称(我/自己/本人)+ 任何范围词 → 优先级 2(权限范围),不传员工值、不传 userFindOrgType
- 多个场景同时命中时,先追问确认再查询,不要自行猜测用户意图
- 菜单链接必须按步骤六中的 Markdown 链接格式严格输出(
- [menuName](menuLink)),不得用其他格式 - 输出原则与禁止事项详见 references/business-rules.md 的"输出核心思路"章节