approval
feishu.agent.approval
¶
人在环(human-in-the-loop)审批引擎:把「确认即执行」升级为「校验—认领—执行—记账」。
feishu.agent.approval.ApprovalEngine 是 feishu.agent.loop.AgentEngine 审批环节的可插拔策略对象。
默认实现 feishu.agent.approval.DefaultApprovalEngine 在执行被审批工具前依次完成:负载防篡改校验、
幂等重放(同一请求重复确认只执行一次)、并发认领(防止重复执行)、执行后记账与审计,并在执行结果未知时
冻结审批而非放任重试。所有面向用户的措辞均通过 outcome_status 注入,SDK 仅保留中性英文兜底,不内置任何
产品文案。
与 feishu.agent.loop.AgentEngine 的对接(集成步骤,非本模块职责):
_request_approval改为构造带payload_sha256/idempotency_key/ 归属信息的 feishu.agent.session.PendingApproval,调用await approval_engine.on_request(approval),并由可注入的 卡片构造器渲染携带payload_sha256的确认卡片;handle_card_action从回传值读取payload_sha256,调用await approval_engine.on_decision(approval_id, decision, expected_payload_sha256=..., dispatch=...), 依据返回的 feishu.agent.approval.ApprovalOutcome 决定回传给模型的工具结果与更新后的卡片。
ApprovalStatus
¶
一次审批决策的归一化结果,驱动回传给模型的工具结果与卡片更新。
由于继承自 str,枚举成员可直接与字符串字面量比较。面向用户的具体措辞由
feishu.agent.approval.DefaultApprovalEngine 的 outcome_status 注入,本枚举仅作稳定的机器可读标识。
示例:
源代码位于: feishu/agent/approval.py
ApprovalOutcome
dataclass
¶
审批决策的结构化结果,告知 feishu.agent.loop.AgentEngine 如何回传模型与更新卡片。
content 是回传给模型的工具结果:EXECUTED/REPLAYED 时为真实执行结果,其余情形为一段状态说明文本。
is_error 为 True 时模型据此调整后续行为;status 供产品侧映射卡片样式与展示措辞。若审批通过后工具发现
缺少用户授权,auth_scopes 会携带原始工具结果声明的授权范围,供 Agent 创建可恢复的授权挂起记录。
示例:
| Python Console Session | |
|---|---|
源代码位于: feishu/agent/approval.py
ExecutionResultStore
¶
Bases: Protocol
幂等执行结果缓存协议:按负载摘要键存取一次成功执行的结果,供重复确认时重放。
用于实现「已执行的写操作被再次确认时,返回先前结果而非二次提交」。纯机制,不含任何产品语义。
源代码位于: feishu/agent/approval.py
AuditLog
¶
Bases: Protocol
仅追加(append-only)审计日志协议:记录审批生命周期事件,供排障与合规复盘。
事件类型字符串由调用方给出(如 write_request/confirm/execute/cancel),存储仅负责落盘。
源代码位于: feishu/agent/approval.py
ApprovalEngine
¶
Bases: Protocol
审批引擎协议,是 feishu.agent.loop.AgentEngine 人在环环节的可插拔策略契约。
on_request 在工具要求审批时被调用以持久化并准备审批;on_decision 在用户于卡片上做出决策后被调用,
完成校验、执行与记账并返回 feishu.agent.approval.ApprovalOutcome。内置实现为
feishu.agent.approval.DefaultApprovalEngine。该协议标注了 runtime_checkable。
示例:
| Python Console Session | |
|---|---|
源代码位于: feishu/agent/approval.py
on_request
async
¶
on_request(approval: PendingApproval) -> None
on_decision
async
¶
on_decision(approval_id: str, decision: Decision, *, expected_payload_sha256: str | None = None, dispatch: DispatchTool) -> ApprovalOutcome
依据用户决策完成校验、执行与记账,返回 feishu.agent.approval.ApprovalOutcome。
源代码位于: feishu/agent/approval.py
DefaultApprovalEngine
¶
feishu.agent.approval.ApprovalEngine 的参考实现:防篡改 + 幂等重放 + 并发认领 + 冻结未知 + 审计。
一次 approve 决策依次经历:可选的幂等重放命中检查 → 携 expected_payload_sha256 的并发认领
(feishu.agent.session.PendingApprovalStore.claim)→ 经 dispatch 执行工具 → 记录执行结果与审计;
执行抛错时冻结审批(execution_unknown)而非放任重试。reject 决策直接取消。所有面向用户的措辞均取自
注入的 outcome_status(缺省回退到中性英文),SDK 不内置任何产品文案;idempotency_namespace 由产品
提供以隔离 id 空间。
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
|
PendingApprovalStore
|
必需 | |
|
ExecutionResultStore | None
|
可选的幂等执行结果缓存 feishu.agent.approval.ExecutionResultStore。 |
None
|
|
AuditLog | None
|
可选的审计日志 feishu.agent.approval.AuditLog。 |
None
|
|
Mapping[str, str] | None
|
由 feishu.agent.approval.ApprovalStatus 值到展示措辞的映射,覆盖中性英文兜底。 |
None
|
|
str
|
派生幂等键 / id 时的命名空间,用于隔离不同产品的 id 空间。默认为 |
'feishu'
|
示例:
| Python Console Session | |
|---|---|
源代码位于: feishu/agent/approval.py
| Python | |
|---|---|
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 | |
on_request
async
¶
on_request(approval: PendingApproval) -> None
持久化挂起审批并写入 write_request 审计事件;缺省时按命名空间派生幂等键。
源代码位于: feishu/agent/approval.py
on_cancel
async
¶
on_cancel(approval_id: str) -> None
撤销一次尚未决策的挂起审批:移除记录并写入 cancel 审计事件。
用于确认卡片下发失败等「审批已落库但永远不会被决策」的情形清理,避免留下用户无法确认的悬挂审批。
无需先 claim:调用方场景下卡片从未送达,不存在并发确认与之竞争(与 on_decision 的 reject 分支不同)。
审批不存在时为无操作。
源代码位于: feishu/agent/approval.py
on_decision
async
¶
on_decision(approval_id: str, decision: Decision, *, expected_payload_sha256: str | None = None, dispatch: DispatchTool) -> ApprovalOutcome
依据用户决策完成校验、执行与记账。
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
|
str
|
审批标识。 |
必需 |
|
Decision
|
用户决策, |
必需 |
|
str | None
|
卡片回传携带的负载摘要,用于防篡改校验。 |
None
|
|
DispatchTool
|
工具分发函数,通常为 feishu.agent.tools.ToolRegistry.dispatch。 |
必需 |
返回:
| 类型 | 描述 |
|---|---|
ApprovalOutcome
|
源代码位于: feishu/agent/approval.py
| Python | |
|---|---|
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | |
action_value
¶
从飞书卡片回调事件中提取 action value,兼容 SDK 与测试里的简化事件。
源代码位于: feishu/agent/approval.py
request_approval
async
¶
request_approval(agent: Any, event: Event, session_id: str, history: list[Message], call: ToolCall, progress: _ProgressCard) -> bool
为需审批的工具创建挂起审批并发送确认卡片;返回是否已挂起本轮。
审批记录先落库再发卡,发卡失败会取消刚创建的 pending,避免用户点不到或无法恢复的悬挂状态。
源代码位于: feishu/agent/approval.py
| Python | |
|---|---|
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | |
pin_referenced_files
async
¶
把审批参数中引用到的分享文件句柄逐个 pin 缓存;失败只记录,绝不影响审批流程。
源代码位于: feishu/agent/approval.py
handle_card_action
async
¶
处理审批卡片回传:同步 ACK,后台完成决策、工具执行、历史续跑与卡片更新。
源代码位于: feishu/agent/approval.py
load_and_decide
async
¶
load_and_decide(agent: Any, event: Event, approval_id: str, decision: Literal['approve', 'reject'], value: dict[str, Any], card_message_id: str | None) -> None
在卡片回调完成 ACK 之后,于后台加载并校验对应的待处理确认请求。
源代码位于: feishu/agent/approval.py
decide_and_resume
async
¶
decide_and_resume(agent: Any, event: Event, approval: PendingApproval, decision: Literal['approve', 'reject'], value: dict[str, Any], card_message_id: str | None) -> None
后台执行审批决定,并在需要时恢复原模型轮次。
执行身份固定为审批发起人,点击事件只用于 ACK 与定位被点击卡片;续跑事件从原消息重建。
源代码位于: feishu/agent/approval.py
| Python | |
|---|---|
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 | |
default_approval_card
¶
default_approval_card(approval: PendingApproval) -> dict[str, Any]
构造 SDK 默认确认卡片,参数摘要只展示类型/长度/句柄,不暴露敏感原值。
源代码位于: feishu/agent/approval.py
default_decided_card
¶
default_decided_card(approval: PendingApproval, decision: str, outcome: ApprovalOutcome) -> dict[str, Any]
构造 SDK 默认审批结果卡片。
源代码位于: feishu/agent/approval.py
approval_arguments_summary
¶
把工具参数渲染成确认卡可展示的脱敏摘要。
源代码位于: feishu/agent/approval.py
| Python | |
|---|---|