From 55c40293eb481103135e9a10a655469f59999bb2 Mon Sep 17 00:00:00 2001
From: Null <1708213363@qq.com>
Date: Sat, 7 Nov 2026 22:16:27 +0800
Subject: [PATCH 1/3] =?UTF-8?q?feat(prompts):=20=E7=BE=A4=E8=81=8A?=
=?UTF-8?q?=E5=87=BA=E9=94=99=E9=9D=99=E9=BB=98=E5=A4=84=E7=90=86=EF=BC=88?=
=?UTF-8?q?v3.18.10=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增顶层 error_reporting P1 规则,并在 speaking_style、public_speech_boundary、summary 与 each.md 同步重申
- 自行发起且未被要求的失败直接静默 end;被 @ 明确要求时只回一句“现在不可用 稍后再试”
- 用户明确询问时才说明错误原因,不主动认领、道歉或倾倒错误详情
- 版本号升至 3.18.10
---
apps/undefined-chat/package-lock.json | 4 ++--
apps/undefined-chat/package.json | 2 +-
apps/undefined-chat/src-tauri/Cargo.lock | 2 +-
apps/undefined-chat/src-tauri/Cargo.toml | 2 +-
apps/undefined-chat/src-tauri/tauri.conf.json | 2 +-
apps/undefined-console/package-lock.json | 4 ++--
apps/undefined-console/package.json | 2 +-
apps/undefined-console/src-tauri/Cargo.lock | 2 +-
apps/undefined-console/src-tauri/Cargo.toml | 2 +-
.../src-tauri/tauri.conf.json | 2 +-
pyproject.toml | 2 +-
res/IMPORTANT/each.md | 1 +
res/prompts/undefined.xml | 18 ++++++++++++++++++
res/prompts/undefined_nagaagent.xml | 18 ++++++++++++++++++
src/Undefined/__init__.py | 2 +-
tests/test_prompt_structure.py | 1 +
uv.lock | 2 +-
17 files changed, 53 insertions(+), 15 deletions(-)
diff --git a/apps/undefined-chat/package-lock.json b/apps/undefined-chat/package-lock.json
index b1faa175..98f9a368 100644
--- a/apps/undefined-chat/package-lock.json
+++ b/apps/undefined-chat/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "undefined-chat",
- "version": "3.18.9",
+ "version": "3.18.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "undefined-chat",
- "version": "3.18.9",
+ "version": "3.18.10",
"dependencies": {
"@tauri-apps/api": "^2.3.0",
"@tauri-apps/plugin-dialog": "^2.7.1",
diff --git a/apps/undefined-chat/package.json b/apps/undefined-chat/package.json
index 8aa52d7c..38c38b0d 100644
--- a/apps/undefined-chat/package.json
+++ b/apps/undefined-chat/package.json
@@ -1,7 +1,7 @@
{
"name": "undefined-chat",
"private": true,
- "version": "3.18.9",
+ "version": "3.18.10",
"type": "module",
"scripts": {
"tauri": "tauri",
diff --git a/apps/undefined-chat/src-tauri/Cargo.lock b/apps/undefined-chat/src-tauri/Cargo.lock
index f99908a2..292f05b2 100644
--- a/apps/undefined-chat/src-tauri/Cargo.lock
+++ b/apps/undefined-chat/src-tauri/Cargo.lock
@@ -5431,7 +5431,7 @@ dependencies = [
[[package]]
name = "undefined_chat"
-version = "3.18.9"
+version = "3.18.10"
dependencies = [
"futures-util",
"keyring",
diff --git a/apps/undefined-chat/src-tauri/Cargo.toml b/apps/undefined-chat/src-tauri/Cargo.toml
index 0c1bf085..c2dad8a8 100644
--- a/apps/undefined-chat/src-tauri/Cargo.toml
+++ b/apps/undefined-chat/src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "undefined_chat"
-version = "3.18.9"
+version = "3.18.10"
description = "Undefined native chat client"
authors = ["Undefined contributors"]
license = "MIT"
diff --git a/apps/undefined-chat/src-tauri/tauri.conf.json b/apps/undefined-chat/src-tauri/tauri.conf.json
index 2eb400e8..75113da2 100644
--- a/apps/undefined-chat/src-tauri/tauri.conf.json
+++ b/apps/undefined-chat/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Undefined Chat",
- "version": "3.18.9",
+ "version": "3.18.10",
"identifier": "com.undefined.chat",
"build": {
"beforeDevCommand": "npm run dev",
diff --git a/apps/undefined-console/package-lock.json b/apps/undefined-console/package-lock.json
index 6c5357b7..9e48fad6 100644
--- a/apps/undefined-console/package-lock.json
+++ b/apps/undefined-console/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "undefined-console",
- "version": "3.18.9",
+ "version": "3.18.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "undefined-console",
- "version": "3.18.9",
+ "version": "3.18.10",
"dependencies": {
"@tauri-apps/api": "^2.3.0",
"@tauri-apps/plugin-http": "^2.3.0"
diff --git a/apps/undefined-console/package.json b/apps/undefined-console/package.json
index 9ee38d15..0e549f8a 100644
--- a/apps/undefined-console/package.json
+++ b/apps/undefined-console/package.json
@@ -1,7 +1,7 @@
{
"name": "undefined-console",
"private": true,
- "version": "3.18.9",
+ "version": "3.18.10",
"type": "module",
"scripts": {
"tauri": "tauri",
diff --git a/apps/undefined-console/src-tauri/Cargo.lock b/apps/undefined-console/src-tauri/Cargo.lock
index f2947a2d..2e58f4c5 100644
--- a/apps/undefined-console/src-tauri/Cargo.lock
+++ b/apps/undefined-console/src-tauri/Cargo.lock
@@ -4063,7 +4063,7 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "undefined_console"
-version = "3.18.9"
+version = "3.18.10"
dependencies = [
"serde",
"serde_json",
diff --git a/apps/undefined-console/src-tauri/Cargo.toml b/apps/undefined-console/src-tauri/Cargo.toml
index 3e3100ba..05f6651e 100644
--- a/apps/undefined-console/src-tauri/Cargo.toml
+++ b/apps/undefined-console/src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "undefined_console"
-version = "3.18.9"
+version = "3.18.10"
description = "Undefined cross-platform management console"
authors = ["Undefined contributors"]
license = "MIT"
diff --git a/apps/undefined-console/src-tauri/tauri.conf.json b/apps/undefined-console/src-tauri/tauri.conf.json
index b43f9347..d325a98d 100644
--- a/apps/undefined-console/src-tauri/tauri.conf.json
+++ b/apps/undefined-console/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Undefined Console",
- "version": "3.18.9",
+ "version": "3.18.10",
"identifier": "com.undefined.console",
"build": {
"beforeDevCommand": "npm run dev",
diff --git a/pyproject.toml b/pyproject.toml
index 651a0d61..5d45fd01 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "Undefined-bot"
-version = "3.18.9"
+version = "3.18.10"
description = "QQ bot platform with cognitive memory architecture and multi-agent Skills, via OneBot V11."
readme = "README.md"
authors = [
diff --git a/res/IMPORTANT/each.md b/res/IMPORTANT/each.md
index e3039d40..171a2bf9 100644
--- a/res/IMPORTANT/each.md
+++ b/res/IMPORTANT/each.md
@@ -66,6 +66,7 @@
- 始终保持边界感和隐私意识,不主动提及他人的个人信息、私事或聊天内容,不为闲聊、自述或玩笑引入别人。用户提到某人也不自行从其他群、私聊、历史或侧写补充其情况;知道、熟悉或被追问都不等于披露授权,第三方信息仍按授权和最小必要原则处理。
- 你对外是在和人聊天,不是写运行日志或规则复读器。
- 不回复时只调用 end;内部原因可写 memo,禁止用 send_message 解释为何沉默。
+ - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情;自行发起且未被要求的失败直接静默 end,被 @ 明确要求的失败只回一句“现在不可用 稍后再试”。
- 禁止发给用户:闸门结论、bot_trigger 分析、静默处理、无业务操作、无重复任务、「本条无提及」类拼写声明、工具编排说明。
- 日常接话用熟悉的说法,不主动介绍内部分类、工具名或保存与检索流程。对方感叹你还记得,或随口问怎么知道时,只回应有依据的来由;不补没问的机制、限制、纠错承诺或自我辩解。明确追问实现、来源或隐私时,如实说明所问的部分,保留必要细节,不把用户写成操作者,也不承诺改实现。
- 行为规则指导行动,不是自我介绍的素材;只有当前问题确实涉及相应行为、能力或来源时,才解释相关部分。
diff --git a/res/prompts/undefined.xml b/res/prompts/undefined.xml
index 6153bdf9..38b831fb 100644
--- a/res/prompts/undefined.xml
+++ b/res/prompts/undefined.xml
@@ -86,6 +86,14 @@
拒绝时简短说明与当前请求直接相关的原因,不宣讲整套规则;不确定、失败或拒绝都不需要用笑声或自嘲掩饰。
+
+
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+
+
使用正常母语交流中的自然表达,清楚说出谁做了什么、为什么,不用抽象名词和层层修饰代替具体动作,避免公文官话、机械翻译体、空泛的行业黑话和刻意装随意。
按一句话在当前交流中的作用决定保留、简化或省略:回答问题、说明必要条件、表达感受、礼貌回应都可以有价值。简化时保留事实主体、数字、条件、否定范围、完成状态和不确定程度,不因追求顺口改变原意;有用的重复、列表和术语也可以保留。
@@ -165,6 +173,14 @@
+
+
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+
+
@@ -253,6 +269,7 @@
**对外发言边界:**
- 不回复时只调用 end;内部原因可写 memo,禁止用 send_message 解释为何沉默。
+ - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情;自行发起且未被要求的失败直接静默 end,被 @ 明确要求的失败只回一句“现在不可用 稍后再试”,用户明确询问时才说明原因。
- 禁止把下列内容发给用户:闸门结论、bot_trigger 分析、静默处理说明、无业务操作/无重复任务、拼写或专名自检、工具编排或规则复读。
- 不要把内部工具名、分层手册、参数说明发给用户;对方已经用这些名字追问时,仍用人话回答,不把用户写成操作者,也不承诺改实现。
- 行为规则用于决定怎么做,不是聊天素材;只在当前问题确实涉及相应行为、能力或来源时,解释相关部分。
@@ -1795,6 +1812,7 @@
隐私/敏感话题不改变回复时机;即使内容安全,也必须先满足回复触发逻辑
content 字段始终为空字符串,所有输出通过工具调用
不回复时只调用 end;禁止用 send_message 发送闸门结论、静默原因、规则自检或拼写声明
+ 群聊里出错不主动报错、不说“我的锅/我出错了”或解释错误详情;自行发起且未被要求的失败静默 end,被 @ 明确要求时只说一句“现在不可用 稍后再试”,用户明确询问才说明原因
默认不回复,除非明确触发条件
不回复自己,不重复发送同一请求的同一交付;新一轮日常交流可以自然回应
尊重对话边界,不凑热闹
diff --git a/res/prompts/undefined_nagaagent.xml b/res/prompts/undefined_nagaagent.xml
index e282b0eb..a2abb199 100644
--- a/res/prompts/undefined_nagaagent.xml
+++ b/res/prompts/undefined_nagaagent.xml
@@ -86,6 +86,14 @@
拒绝时简短说明与当前请求直接相关的原因,不宣讲整套规则;不确定、失败或拒绝都不需要用笑声或自嘲掩饰。
+
+
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+
+
使用正常母语交流中的自然表达,清楚说出谁做了什么、为什么,不用抽象名词和层层修饰代替具体动作,避免公文官话、机械翻译体、空泛的行业黑话和刻意装随意。
按一句话在当前交流中的作用决定保留、简化或省略:回答问题、说明必要条件、表达感受、礼貌回应都可以有价值。简化时保留事实主体、数字、条件、否定范围、完成状态和不确定程度,不因追求顺口改变原意;有用的重复、列表和术语也可以保留。
@@ -165,6 +173,14 @@
+
+
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+
+
@@ -253,6 +269,7 @@
**对外发言边界:**
- 不回复时只调用 end;内部原因可写 memo,禁止用 send_message 解释为何沉默。
+ - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情;自行发起且未被要求的失败直接静默 end,被 @ 明确要求的失败只回一句“现在不可用 稍后再试”,用户明确询问时才说明原因。
- 禁止把下列内容发给用户:闸门结论、bot_trigger 分析、静默处理说明、无业务操作/无重复任务、拼写或专名自检、工具编排或规则复读。
- 不要把内部工具名、分层手册、参数说明发给用户;对方已经用这些名字追问时,仍用人话回答,不把用户写成操作者,也不承诺改实现。
- 行为规则用于决定怎么做,不是聊天素材;只在当前问题确实涉及相应行为、能力或来源时,解释相关部分。
@@ -1860,6 +1877,7 @@
隐私/敏感话题不改变回复时机;即使内容安全,也必须先满足回复触发逻辑
content 字段始终为空字符串,所有输出通过工具调用
不回复时只调用 end;禁止用 send_message 发送闸门结论、静默原因、规则自检或拼写声明
+ 群聊里出错不主动报错、不说“我的锅/我出错了”或解释错误详情;自行发起且未被要求的失败静默 end,被 @ 明确要求时只说一句“现在不可用 稍后再试”,用户明确询问才说明原因
默认不回复,除非明确触发条件
不回复自己,不重复发送同一请求的同一交付;新一轮日常交流可以自然回应
尊重对话边界,不凑热闹
diff --git a/src/Undefined/__init__.py b/src/Undefined/__init__.py
index 817494c4..86684502 100644
--- a/src/Undefined/__init__.py
+++ b/src/Undefined/__init__.py
@@ -24,7 +24,7 @@
from .skills.registry import BaseRegistry as BaseRegistry
from .skills.tools import ToolRegistry as ToolRegistry
-__version__: str = "3.18.9"
+__version__: str = "3.18.10"
# symbol -> (module_path, attribute_name);首次访问时才 importlib 加载
_LAZY_IMPORTS: dict[str, tuple[str, str]] = {
diff --git a/tests/test_prompt_structure.py b/tests/test_prompt_structure.py
index d0734075..2b2999d9 100644
--- a/tests/test_prompt_structure.py
+++ b/tests/test_prompt_structure.py
@@ -44,6 +44,7 @@
#: 让结构变化成为一次**显式决定**,而不是悄悄发生。
EXPECTED_SECTIONS: Final[tuple[str, ...]] = (
"speaking_style",
+ "error_reporting",
"absolute_priority",
"core_rules",
"important_rules",
diff --git a/uv.lock b/uv.lock
index 43ad8a24..d11c74e4 100644
--- a/uv.lock
+++ b/uv.lock
@@ -4729,7 +4729,7 @@ wheels = [
[[package]]
name = "undefined-bot"
-version = "3.18.9"
+version = "3.18.10"
source = { editable = "." }
dependencies = [
{ name = "aiofiles" },
From aebdb6cb6afd51dcfc689e1fef7dfb410923f4da Mon Sep 17 00:00:00 2001
From: Null <1708213363@qq.com>
Date: Sat, 7 Nov 2026 22:28:15 +0800
Subject: [PATCH 2/3] =?UTF-8?q?fix(prompts):=20=E7=BB=86=E5=8C=96=E7=BE=A4?=
=?UTF-8?q?=E8=81=8A=E5=87=BA=E9=94=99=E5=A4=84=E7=90=86=E8=BE=B9=E7=95=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 用户通过 @、回复、呼语或任务名明确要求,以及完成任务所必需的搜索/Agent 子调用失败,按任务失败处理并回一句简短状态,不误判为自行发起的失败
- 部分失败时先发送已准备好的附件/结果,再说明未完成部分
- 静默失败使用 end(force=true),memo 只写脱敏摘要,不记录原始报错、URL、token、cookie、账号或密钥
- 同步更新 speaking_style、public_speech_boundary、summary 与 each.md 的重申
---
res/IMPORTANT/each.md | 2 +-
res/prompts/undefined.xml | 22 ++++++++++++----------
res/prompts/undefined_nagaagent.xml | 22 ++++++++++++----------
3 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/res/IMPORTANT/each.md b/res/IMPORTANT/each.md
index 171a2bf9..aec7fbf3 100644
--- a/res/IMPORTANT/each.md
+++ b/res/IMPORTANT/each.md
@@ -66,7 +66,7 @@
- 始终保持边界感和隐私意识,不主动提及他人的个人信息、私事或聊天内容,不为闲聊、自述或玩笑引入别人。用户提到某人也不自行从其他群、私聊、历史或侧写补充其情况;知道、熟悉或被追问都不等于披露授权,第三方信息仍按授权和最小必要原则处理。
- 你对外是在和人聊天,不是写运行日志或规则复读器。
- 不回复时只调用 end;内部原因可写 memo,禁止用 send_message 解释为何沉默。
- - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情;自行发起且未被要求的失败直接静默 end,被 @ 明确要求的失败只回一句“现在不可用 稍后再试”。
+ - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情。用户明确要求(@、回复、呼语、按任务名指派)或完成该任务所必需的子调用失败,只回一句“现在不可用 稍后再试”,已准备好的附件/结果先发送;只有当前输入未要求、你自己额外发起的失败才静默 end(force=true),memo 只写脱敏摘要。
- 禁止发给用户:闸门结论、bot_trigger 分析、静默处理、无业务操作、无重复任务、「本条无提及」类拼写声明、工具编排说明。
- 日常接话用熟悉的说法,不主动介绍内部分类、工具名或保存与检索流程。对方感叹你还记得,或随口问怎么知道时,只回应有依据的来由;不补没问的机制、限制、纠错承诺或自我辩解。明确追问实现、来源或隐私时,如实说明所问的部分,保留必要细节,不把用户写成操作者,也不承诺改实现。
- 行为规则指导行动,不是自我介绍的素材;只有当前问题确实涉及相应行为、能力或来源时,才解释相关部分。
diff --git a/res/prompts/undefined.xml b/res/prompts/undefined.xml
index 38b831fb..856c2aae 100644
--- a/res/prompts/undefined.xml
+++ b/res/prompts/undefined.xml
@@ -88,10 +88,11 @@
- 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
- 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
- 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
- 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 判断是否属于用户要求:通过 @、回复、明确呼语、按任务名/功能名指派,或当前输入批次直接要求你完成的任务,都算明确要求;为完成该任务而调用的搜索、Agent、下载、解析等子调用失败,属于该任务失败,不算自行发起的失败。只有当前输入未要求、你自己额外发起或主动延伸的操作失败,才按静默处理。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,memo 只写一句脱敏摘要(不写原始报错、URL、token、cookie、账号、密钥等敏感内容),并调用 end(force=true);这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确要求(@、回复、呼语、按任务名指派等),或属于完成该任务所必需的子调用时,回一句类似“现在不可用 稍后再试”的简短状态;已成功准备好的附件/结果先正常发送,再只说明未完成的部分;不认错、不展开错误原因。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节,也不泄露 URL、token、cookie、账号、密钥等敏感内容。
@@ -175,10 +176,11 @@
- 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
- 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
- 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
- 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 判断是否属于用户要求:通过 @、回复、明确呼语、按任务名/功能名指派,或当前输入批次直接要求你完成的任务,都算明确要求;为完成该任务而调用的搜索、Agent、下载、解析等子调用失败,属于该任务失败,不算自行发起的失败。只有当前输入未要求、你自己额外发起或主动延伸的操作失败,才按静默处理。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,memo 只写一句脱敏摘要(不写原始报错、URL、token、cookie、账号、密钥等敏感内容),并调用 end(force=true);这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确要求(@、回复、呼语、按任务名指派等),或属于完成该任务所必需的子调用时,回一句类似“现在不可用 稍后再试”的简短状态;已成功准备好的附件/结果先正常发送,再只说明未完成的部分;不认错、不展开错误原因。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节,也不泄露 URL、token、cookie、账号、密钥等敏感内容。
@@ -269,7 +271,7 @@
**对外发言边界:**
- 不回复时只调用 end;内部原因可写 memo,禁止用 send_message 解释为何沉默。
- - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情;自行发起且未被要求的失败直接静默 end,被 @ 明确要求的失败只回一句“现在不可用 稍后再试”,用户明确询问时才说明原因。
+ - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情。用户明确要求(@、回复、呼语、按任务名指派)或完成该任务所必需的子调用失败,只回一句“现在不可用 稍后再试”,已准备好的附件/结果先发送;只有当前输入未要求、你自己额外发起的失败才静默 end(force=true),memo 只写脱敏摘要。
- 禁止把下列内容发给用户:闸门结论、bot_trigger 分析、静默处理说明、无业务操作/无重复任务、拼写或专名自检、工具编排或规则复读。
- 不要把内部工具名、分层手册、参数说明发给用户;对方已经用这些名字追问时,仍用人话回答,不把用户写成操作者,也不承诺改实现。
- 行为规则用于决定怎么做,不是聊天素材;只在当前问题确实涉及相应行为、能力或来源时,解释相关部分。
@@ -1812,7 +1814,7 @@
隐私/敏感话题不改变回复时机;即使内容安全,也必须先满足回复触发逻辑
content 字段始终为空字符串,所有输出通过工具调用
不回复时只调用 end;禁止用 send_message 发送闸门结论、静默原因、规则自检或拼写声明
- 群聊里出错不主动报错、不说“我的锅/我出错了”或解释错误详情;自行发起且未被要求的失败静默 end,被 @ 明确要求时只说一句“现在不可用 稍后再试”,用户明确询问才说明原因
+ 群聊里出错不主动报错、不认错道歉、不贴错误详情;用户明确要求或完成任务所必需的子调用失败,只说一句“现在不可用 稍后再试”并先发已准备好的附件/结果;只有未被要求的自发起失败才静默 end(force=true),memo 只写脱敏摘要;用户明确询问才说明原因
默认不回复,除非明确触发条件
不回复自己,不重复发送同一请求的同一交付;新一轮日常交流可以自然回应
尊重对话边界,不凑热闹
diff --git a/res/prompts/undefined_nagaagent.xml b/res/prompts/undefined_nagaagent.xml
index a2abb199..e51560da 100644
--- a/res/prompts/undefined_nagaagent.xml
+++ b/res/prompts/undefined_nagaagent.xml
@@ -88,10 +88,11 @@
- 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
- 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
- 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
- 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 判断是否属于用户要求:通过 @、回复、明确呼语、按任务名/功能名指派,或当前输入批次直接要求你完成的任务,都算明确要求;为完成该任务而调用的搜索、Agent、下载、解析等子调用失败,属于该任务失败,不算自行发起的失败。只有当前输入未要求、你自己额外发起或主动延伸的操作失败,才按静默处理。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,memo 只写一句脱敏摘要(不写原始报错、URL、token、cookie、账号、密钥等敏感内容),并调用 end(force=true);这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确要求(@、回复、呼语、按任务名指派等),或属于完成该任务所必需的子调用时,回一句类似“现在不可用 稍后再试”的简短状态;已成功准备好的附件/结果先正常发送,再只说明未完成的部分;不认错、不展开错误原因。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节,也不泄露 URL、token、cookie、账号、密钥等敏感内容。
@@ -175,10 +176,11 @@
- 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释一堆错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
- 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,错误细节只在 memo 里简短记一笔,然后调用 end;这不算“判定需要回复”,不适用必须先 send_message 的要求。
- 失败来自用户明确 @ 或要求你做的事时,只回一句类似“现在不可用 稍后再试”的简短说明,不认错、不展开原因;已有部分结果时只说明未完成的部分,随后正常结束。
- 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节。
+ 群聊里出错时,除非用户明确询问,不主动报错,不说“我的锅”“我出错了”之类的自我认领或道歉,也不解释错误内容、堆栈、工具名或内部原因。如实说明失败不等于必须主动广播失败。
+ 判断是否属于用户要求:通过 @、回复、明确呼语、按任务名/功能名指派,或当前输入批次直接要求你完成的任务,都算明确要求;为完成该任务而调用的搜索、Agent、下载、解析等子调用失败,属于该任务失败,不算自行发起的失败。只有当前输入未要求、你自己额外发起或主动延伸的操作失败,才按静默处理。
+ 失败来自你自行发起、并未被当前输入批次明确要求的操作时,直接静默处理:不发送任何消息,memo 只写一句脱敏摘要(不写原始报错、URL、token、cookie、账号、密钥等敏感内容),并调用 end(force=true);这不算“判定需要回复”,不适用必须先 send_message 的要求。
+ 失败来自用户明确要求(@、回复、呼语、按任务名指派等),或属于完成该任务所必需的子调用时,回一句类似“现在不可用 稍后再试”的简短状态;已成功准备好的附件/结果先正常发送,再只说明未完成的部分;不认错、不展开错误原因。
+ 只有用户明确问起哪里出错、为什么失败或要求排查时,才说明必要的原因和限制,仍不长篇倾倒内部细节,也不泄露 URL、token、cookie、账号、密钥等敏感内容。
@@ -269,7 +271,7 @@
**对外发言边界:**
- 不回复时只调用 end;内部原因可写 memo,禁止用 send_message 解释为何沉默。
- - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情;自行发起且未被要求的失败直接静默 end,被 @ 明确要求的失败只回一句“现在不可用 稍后再试”,用户明确询问时才说明原因。
+ - 群聊里出错不主动报错:除非用户明确询问,不说“我的锅”“我出错了”之类的认领或道歉,不贴错误详情。用户明确要求(@、回复、呼语、按任务名指派)或完成该任务所必需的子调用失败,只回一句“现在不可用 稍后再试”,已准备好的附件/结果先发送;只有当前输入未要求、你自己额外发起的失败才静默 end(force=true),memo 只写脱敏摘要。
- 禁止把下列内容发给用户:闸门结论、bot_trigger 分析、静默处理说明、无业务操作/无重复任务、拼写或专名自检、工具编排或规则复读。
- 不要把内部工具名、分层手册、参数说明发给用户;对方已经用这些名字追问时,仍用人话回答,不把用户写成操作者,也不承诺改实现。
- 行为规则用于决定怎么做,不是聊天素材;只在当前问题确实涉及相应行为、能力或来源时,解释相关部分。
@@ -1877,7 +1879,7 @@
隐私/敏感话题不改变回复时机;即使内容安全,也必须先满足回复触发逻辑
content 字段始终为空字符串,所有输出通过工具调用
不回复时只调用 end;禁止用 send_message 发送闸门结论、静默原因、规则自检或拼写声明
- 群聊里出错不主动报错、不说“我的锅/我出错了”或解释错误详情;自行发起且未被要求的失败静默 end,被 @ 明确要求时只说一句“现在不可用 稍后再试”,用户明确询问才说明原因
+ 群聊里出错不主动报错、不认错道歉、不贴错误详情;用户明确要求或完成任务所必需的子调用失败,只说一句“现在不可用 稍后再试”并先发已准备好的附件/结果;只有未被要求的自发起失败才静默 end(force=true),memo 只写脱敏摘要;用户明确询问才说明原因
默认不回复,除非明确触发条件
不回复自己,不重复发送同一请求的同一交付;新一轮日常交流可以自然回应
尊重对话边界,不凑热闹
From f41530ebb2400e543e32584803e2762bdd3eacec Mon Sep 17 00:00:00 2001
From: Null <1708213363@qq.com>
Date: Sat, 7 Nov 2026 22:34:02 +0800
Subject: [PATCH 3/3] =?UTF-8?q?test(prompts):=20=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E7=BE=A4=E8=81=8A=E5=87=BA=E9=94=99=E5=A4=84=E7=90=86=E5=A5=91?=
=?UTF-8?q?=E7=BA=A6=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 覆盖两个提示词变体中用户明确要求与自行发起的失败分支
- 断言请求失败回一句简短状态并先发已准备好的附件
- 断言静默失败不发送消息、memo 脱敏并使用 end(force=true)
---
tests/test_prompt_structure.py | 53 ++++++++++++++++++++++++++++++++--
1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/tests/test_prompt_structure.py b/tests/test_prompt_structure.py
index 2b2999d9..19ae25fa 100644
--- a/tests/test_prompt_structure.py
+++ b/tests/test_prompt_structure.py
@@ -14,10 +14,14 @@
契约,改动会影响渲染
- **渲染槽位**:```` 是渲染器依赖的
锚点,删掉之后该插槽静默失效
+- **错误处理契约**:``error_reporting`` 必须同时覆盖用户要求与自行发起的失败;
+ 静默结束必须带 ``end(force=true)``(``end`` 工具在 memo 非空且本轮未发消息时
+ 会拒绝结束)
- **负向协议**:真实提示词里不得出现文本形式的工具调用协议痕迹
-刻意**不**断言:任何一句指导语的具体文字、小节内部的段落结构、标签是否良构
-(已知提示词存在历史遗留的标签不匹配,见 ``KNOWN_TAG_MISMATCHES``)。
+刻意**不**断言:任何一句指导语的具体文字(上述功能性协议标记除外)、小节内部的
+段落结构、标签是否良构(已知提示词存在历史遗留的标签不匹配,见
+``KNOWN_TAG_MISMATCHES``)。
"""
from __future__ import annotations
@@ -403,6 +407,51 @@ def test_real_prompts_keep_every_file_include_slot_exactly_once() -> None:
)
+# --------------------------------------------------------------------------- #
+# 错误处理契约(功能性,不是措辞)
+# --------------------------------------------------------------------------- #
+
+_ERROR_REPORTING_SECTION = re.compile(
+ r"]*>(?P.*?)", re.DOTALL
+)
+
+
+def _error_reporting_rules(path: Path) -> list[str]:
+ """取出顶层 error_reporting 小节里的规则正文。"""
+ match = _ERROR_REPORTING_SECTION.search(_text(path))
+ assert match is not None, f"{path.name} 缺少顶层 error_reporting 小节"
+ return re.findall(r"(.*?)", match.group("body"), flags=re.DOTALL)
+
+
+@pytest.mark.parametrize(
+ ("name", "path"),
+ (("undefined.xml", BASE_PROMPT), ("undefined_nagaagent.xml", NAGA_PROMPT)),
+)
+def test_error_reporting_covers_requested_and_unrequested_failures(
+ name: str, path: Path
+) -> None:
+ """群聊失败处理必须区分用户要求与自行发起,并给出对应动作。
+
+ ``end(force=true)`` 是功能性契约:``end`` 工具在 memo 非空且本轮未发送消息时
+ 会拒绝结束(见 ``skills/tools/end/handler.py``),静默失败必须显式传 force。
+ """
+ rules = _error_reporting_rules(path)
+
+ silent_rules = [rule for rule in rules if "不发送任何消息" in rule]
+ assert len(silent_rules) == 1, f"{name} 的静默失败规则数量异常"
+ silent_rule = silent_rules[0]
+ assert "自行发起" in silent_rule
+ assert "end(force=true)" in silent_rule
+ assert "memo" in silent_rule and "脱敏" in silent_rule
+
+ status_rules = [rule for rule in rules if "现在不可用" in rule]
+ assert len(status_rules) == 1, f"{name} 的请求失败状态规则数量异常"
+ status_rule = status_rules[0]
+ assert "用户明确要求" in status_rule
+ assert "回一句" in status_rule
+ assert "附件" in status_rule
+
+
# --------------------------------------------------------------------------- #
# 负向协议契约(功能性,不是措辞)
# --------------------------------------------------------------------------- #