Skill 执行出错时,错误信息如何暴露?既要方便调试,又不能泄露系统内部敏感信息。

“这是安全与可维护性之间最典型的矛盾。我的核心原则是:对内透明,对外脱敏;分层暴露,按角色裁剪。 绝不让最终用户看到堆栈轨迹或数据库连接串,但要让开发者能在 5 分钟内定位问题。

我设计了一套三层错误信息模型,每层看到的内容完全不一样。


第一层:用户层错误 —— 只暴露安全、可行动的信息

用户层是 Agent 最终展示给用户的错误提示。设计规则:

  • 不说技术细节:绝不出现“NullPointerException”、“Connection refused”、“SQL syntax error”这类内部错误信息,因为攻击者可以通过这些细节推断系统架构。

  • 不说敏感数据:不暴露字段名、表名、主机地址、账号密码片段、文件路径等。

  • 只说三件事:出了什么问题(用户能理解的)、我该怎么办(用户可操作的下一步)、如何求助(补充渠道)。

例如,机票预订 Skill 因航空公司接口超时失败。用户看到的错误是:

😕 机票预订暂时失败

我们无法连接到航空公司系统获取实时票价,这通常是由于网络波动引起的。
您可以:
• 稍等 30 秒后重试
• 尝试其他出行方式(如火车)
• 联系人工客服并提供引用码:ERR-BOOK-2406-001

这条消息中,ERR-BOOK-2406-001 是一个错误引用码,它是一把钥匙——用户可以凭它找客服,客服可以在内部系统快速定位到完整错误链,但用户自己无法从引用码中反推出任何系统信息。

错误引用码的设计:

  • 格式:ERR-{Skill缩写}-{日期}-{序号}

  • 后端将其映射到唯一的错误事件 ID,关联完整的内部错误日志。

  • 可设置有效期(如 72 小时),过期后引用码失效,防止被长期滥用。


第二层:开发者 / 运维层错误 —— 完整但受控的调试信息

这一层是给内部开发者或经过认证的运维人员看的,通过后台日志系统或管理控制台访问。它包含:

  • 错误类型与堆栈:完整的异常栈,但自动脱敏。日志系统在记录前,用正则或插桩方式过滤掉敏感数据:密码、Token、身份证号、手机号、邮箱、密钥等,替换为 REDACTED

  • 调用链上下文:当前任务的 DAG 执行图、失败节点的输入参数(同样脱敏)、上游 Skill 的输出摘要、会话 ID、用户 ID(用于重现问题,但需权限审计)。

  • 环境元数据:Skill 版本、沙箱类型、执行耗时、分配的内存/CPU 配额、最近的部署记录。

  • 相关联的审计事件:最近 5 分钟内与该 Skill 相关的其他异常或关键操作。

这一层的访问权限必须走 RBAC 和审批流程,所有查看行为本身也计入审计日志,防止内部人员滥用。


第三层:自动化诊断与告警 —— 让机器先读懂错误

在人工介入之前,系统自身应该先做第一轮分析。我设计了一个错误诊断引擎,它在 Skill 出错时自动执行:

  1. 模式匹配与自动分类:根据异常类型和堆栈模式,将错误归类为“外部依赖超时”、“参数校验失败”、“沙箱资源耗尽”、“未授权访问尝试”等预定义类别。

  2. 自动建议:匹配到已知模式后,引擎自动给出调试建议(如“检查第三方 API 密钥是否过期”、“该 Skill 内存配额可能不足,建议从 64MB 调整到 128MB”),写入开发者的错误详情页。

  3. 严重性评估:根据错误类别和频率判断严重级别。单次参数校验失败是 INFO;连续 5 次外部依赖超时是 WARN;越权尝试是 CRITICAL,立刻告警。

  4. 自动执行检查:如果是外部依赖超时,引擎自动 ping 对应域名并记录结果,帮助开发者区分“是我们网络问题还是对端挂了”。

这样,当开发者打开一个错误事件时,看到的不是冰冷的堆栈,而是一份带有初步诊断和检查结果的“半成品报告”,大大缩短了定位时间。