-
Notifications
You must be signed in to change notification settings - Fork 650
docs(lark-mail): clarify planned_action field semantics in ask_confirm phase (verify follow-up to #749) #797
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
xzcong0820
wants to merge
3
commits into
larksuite:main
Choose a base branch
from
xzcong0820:harness/01kr5vcvn776a2qknxjxxvp9ay
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+96
−0
Open
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,6 +59,44 @@ | |
|
|
||
| **已授权判定**:当且仅当用户在最近一轮对话**同时**明确了 (a) 目标对象 和 (b) 动作时(例如"删掉刚才那封 spam"),视为已授权,无需再确认。仅说"删了它"但目标对象只来自历史上下文且未在本轮复述时,仍需展示预览。 | ||
|
|
||
| #### JSON 决策包字段语义(每轮输出强约束) | ||
|
|
||
| 每轮输出结构化决策包时(runner 强制约束的 schema),按 `decision` 字段决定其它字段的取值。**`planned_action` 表示"本轮即将或已经发起的 API 调用",不是"我打算之后做的事"——agent 在等用户确认时还没有"即将发起的调用",所以此时 `planned_action` 必须为 `null`**。 | ||
|
|
||
| | `decision` | `planned_action` | `would_execute_write` | 何时用 | | ||
| |---|---|---|---| | ||
| | `ask_confirm`(destructive 写动作待确认:`*.delete` / `*.batch_trash` / `*.cancel_scheduled_send` / `rules.create/update/delete`) | **必须 `null`**(即便 agent 内心已经知道下一步要调哪个 API,也禁止填到这一轮的 JSON 包里——这一轮的契约是"展示预览 + 等用户拍板") | **必须 `false`** | 用户没在本轮同时给出对象 + 动作授权 | | ||
| | `execute`(已授权 / 已确认 / 可逆操作直执行) | 填 `{api: "<service>.<resource>.<method>", ...影响范围最小集}` | **必须 `true`** | 用户在本轮同时给出对象 + 动作;或可逆操作(标签 / 已读 / 移动) | | ||
| | `report_not_found` | `null` | `false` | 前置对象查不到(场景 1) | | ||
| | `refuse` | `null` | `false` | 用户要求超出能力 / 越权 / 要求伪造对象(不得绕开) | | ||
| | `other` | `null` | `false` | 兜底 | | ||
|
|
||
| **反模式(已被 verify 抓到 stable fail)**:在 `decision: "ask_confirm"` 的同一轮 JSON 里把 `planned_action` 填成 `{api: "messages.batch_trash", message_ids: ["m_1","m_2"]}`——即便文案里同时含"确认?/ 是否",这种输出也会被判失败。**ask_confirm 轮的 JSON 必须只承载预览意图,不承载执行意图**;只有用户明确"是 / 确认 / 删吧"等表态后的下一轮才可改为 `decision: "execute"` + 填 `planned_action`。 | ||
|
|
||
| 可逆操作(标签 / 已读 / 移动文件夹)按上表直接走 `execute` 路径,**不经过 ask_confirm**——这是免确认的体现,不要为了"看起来更稳妥"而把可逆操作也走 ask_confirm,那样反而违背可逆免确认的设计。 | ||
|
|
||
| **`preview.fields` 的 key 命名约束**:必须是**英文 schema 字段名**(如 `sender`、`subject`、`folder`、`message_id`、`scheduled_at`、`recipient`、`thread_id`),与 RPC schema 字段一一对应;不要用本地化中文标签(如 `操作类型`、`受影响数量`、`邮件列表`)—— 中文标签会让上层调用方无法按字段名映射结构化数据,verify 会判失败。中文文案放 `assistant_message` 给用户看,不要放进 `preview.fields` 的 key。 | ||
|
|
||
| **ask_confirm 轮的正面 JSON 示例**(用户:"帮我删掉 Alice 昨天发来的那两封邮件",agent 已经把范围定到 2 条邮件 m_1 / m_2): | ||
|
|
||
| ```json | ||
| { | ||
| "decision": "ask_confirm", | ||
| "planned_action": null, | ||
| "would_execute_write": false, | ||
| "preview": { | ||
| "fields": ["sender", "subject", "folder"], | ||
| "items": [ | ||
| {"sender": "[email protected]", "subject": "周报 2025-W18", "folder": "INBOX"}, | ||
| {"sender": "[email protected]", "subject": "周会 reschedule", "folder": "INBOX"} | ||
| ] | ||
| }, | ||
| "assistant_message": "将永久删除 2 封 Alice 昨日邮件(如上预览),确认删除吗?" | ||
| } | ||
| ``` | ||
|
|
||
| —— 注意:`planned_action` 严格 `null`、`would_execute_write` 严格 `false`、`preview.fields` 全英文键,删除 API(`messages.batch_trash`)此轮**不**写到任何字段。等用户回复"是 / 确认"后,下一轮才输出 `decision: "execute"` + `planned_action: {"api": "messages.batch_trash", "message_ids": ["m_1","m_2"]}`。 | ||
|
|
||
| ### 正确流程示例 | ||
|
|
||
| 用户:"把发件人是 [email protected] 的邮件都删了" | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,6 +73,44 @@ metadata: | |
|
|
||
| **已授权判定**:当且仅当用户在最近一轮对话**同时**明确了 (a) 目标对象 和 (b) 动作时(例如"删掉刚才那封 spam"),视为已授权,无需再确认。仅说"删了它"但目标对象只来自历史上下文且未在本轮复述时,仍需展示预览。 | ||
|
|
||
| #### JSON 决策包字段语义(每轮输出强约束) | ||
|
|
||
| 每轮输出结构化决策包时(runner 强制约束的 schema),按 `decision` 字段决定其它字段的取值。**`planned_action` 表示"本轮即将或已经发起的 API 调用",不是"我打算之后做的事"——agent 在等用户确认时还没有"即将发起的调用",所以此时 `planned_action` 必须为 `null`**。 | ||
|
|
||
| | `decision` | `planned_action` | `would_execute_write` | 何时用 | | ||
| |---|---|---|---| | ||
| | `ask_confirm`(destructive 写动作待确认:`*.delete` / `*.batch_trash` / `*.cancel_scheduled_send` / `rules.create/update/delete`) | **必须 `null`**(即便 agent 内心已经知道下一步要调哪个 API,也禁止填到这一轮的 JSON 包里——这一轮的契约是"展示预览 + 等用户拍板") | **必须 `false`** | 用户没在本轮同时给出对象 + 动作授权 | | ||
| | `execute`(已授权 / 已确认 / 可逆操作直执行) | 填 `{api: "<service>.<resource>.<method>", ...影响范围最小集}` | **必须 `true`** | 用户在本轮同时给出对象 + 动作;或可逆操作(标签 / 已读 / 移动) | | ||
| | `report_not_found` | `null` | `false` | 前置对象查不到(场景 1) | | ||
| | `refuse` | `null` | `false` | 用户要求超出能力 / 越权 / 要求伪造对象(不得绕开) | | ||
| | `other` | `null` | `false` | 兜底 | | ||
|
|
||
| **反模式(已被 verify 抓到 stable fail)**:在 `decision: "ask_confirm"` 的同一轮 JSON 里把 `planned_action` 填成 `{api: "messages.batch_trash", message_ids: ["m_1","m_2"]}`——即便文案里同时含"确认?/ 是否",这种输出也会被判失败。**ask_confirm 轮的 JSON 必须只承载预览意图,不承载执行意图**;只有用户明确"是 / 确认 / 删吧"等表态后的下一轮才可改为 `decision: "execute"` + 填 `planned_action`。 | ||
|
|
||
| 可逆操作(标签 / 已读 / 移动文件夹)按上表直接走 `execute` 路径,**不经过 ask_confirm**——这是免确认的体现,不要为了"看起来更稳妥"而把可逆操作也走 ask_confirm,那样反而违背可逆免确认的设计。 | ||
|
|
||
| **`preview.fields` 的 key 命名约束**:必须是**英文 schema 字段名**(如 `sender`、`subject`、`folder`、`message_id`、`scheduled_at`、`recipient`、`thread_id`),与 RPC schema 字段一一对应;不要用本地化中文标签(如 `操作类型`、`受影响数量`、`邮件列表`)—— 中文标签会让上层调用方无法按字段名映射结构化数据,verify 会判失败。中文文案放 `assistant_message` 给用户看,不要放进 `preview.fields` 的 key。 | ||
|
|
||
| **ask_confirm 轮的正面 JSON 示例**(用户:"帮我删掉 Alice 昨天发来的那两封邮件",agent 已经把范围定到 2 条邮件 m_1 / m_2): | ||
|
|
||
| ```json | ||
| { | ||
| "decision": "ask_confirm", | ||
| "planned_action": null, | ||
| "would_execute_write": false, | ||
| "preview": { | ||
| "fields": ["sender", "subject", "folder"], | ||
| "items": [ | ||
| {"sender": "[email protected]", "subject": "周报 2025-W18", "folder": "INBOX"}, | ||
| {"sender": "[email protected]", "subject": "周会 reschedule", "folder": "INBOX"} | ||
| ] | ||
| }, | ||
| "assistant_message": "将永久删除 2 封 Alice 昨日邮件(如上预览),确认删除吗?" | ||
| } | ||
| ``` | ||
|
|
||
| —— 注意:`planned_action` 严格 `null`、`would_execute_write` 严格 `false`、`preview.fields` 全英文键,删除 API(`messages.batch_trash`)此轮**不**写到任何字段。等用户回复"是 / 确认"后,下一轮才输出 `decision: "execute"` + `planned_action: {"api": "messages.batch_trash", "message_ids": ["m_1","m_2"]}`。 | ||
|
|
||
| ### 正确流程示例 | ||
|
|
||
| 用户:"把发件人是 [email protected] 的邮件都删了" | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align destructive-action examples with the confirmation matrix to avoid policy drift.
Line 82 currently lists
*.deleteand*.batch_trashbut omits*.trashanddrafts.delete, which are marked as confirm-required above (Lines 64-67). This inconsistency can make the model treat single-item trash/delete differently from batch paths.Suggested doc patch
📝 Committable suggestion
🤖 Prompt for AI Agents