共计 2434 个字符,预计需要花费 7 分钟才能阅读完成。
1. 背景与痛点
当我们开发 Agent 调用工具时,输出的描述信息往往容易被忽视,导致后期维护和调试困难。以下是新手常见的几个问题:

- 格式混乱 :不同工具或模块输出的描述格式不一致,有的用 JSON,有的用纯文本,甚至同一工具在不同情况下输出格式也不同。
- 缺乏上下文 :当出现错误时,仅返回简单的错误代码,没有说明具体是哪个步骤出了问题,或者缺少必要的环境信息。
- 错误信息不明确 :错误描述过于技术化或过于简单,既不利于开发者调试,也不利于终端用户理解。
这些问题的根源在于缺乏统一的输出规范和设计原则。下面我们就来探讨如何解决这些问题。
2. 技术方案:结构化输出设计
好的输出描述应该遵循以下结构化设计原则:
- 基础元数据 :
- 时间戳(timestamp):记录操作发生的时间
- 请求 ID(request_id):唯一标识每次调用
-
状态码(status_code):标准化的操作结果状态
-
核心内容 :
- 操作描述(description):人类可读的操作说明
- 业务数据(data):返回的具体业务内容
-
执行详情(details):详细的执行过程记录
-
扩展信息 :
- 执行耗时(duration):操作执行时间
- 环境信息(environment):运行环境标识
- 版本信息(version):接口或工具版本
3. 代码示例:Python 实现
下面是一个 Python 实现的标准化响应对象示例:
import time
import uuid
from datetime import datetime
from typing import Any, Dict, Optional
class StandardResponse:
"""标准化响应对象"""
def __init__(self):
self.timestamp = datetime.utcnow().isoformat() + 'Z'
self.request_id = str(uuid.uuid4())
self.status = "success" # or "error"
self.code = 200 # HTTP 状态码
self.message = "" # 人类可读的消息
self.data = None # 返回的业务数据
self.details = [] # 执行详情
self.duration = 0 # 执行耗时 (毫秒)
def set_error(self, code: int, message: str):
"""设置错误响应"""
self.status = "error"
self.code = code
self.message = message
return self
def add_detail(self, detail: str):
"""添加执行详情"""
self.details.append(detail)
return self
def set_data(self, data: Any):
"""设置返回数据"""
self.data = data
return self
def to_dict(self) -> Dict:
"""转换为字典格式"""
return {
"timestamp": self.timestamp,
"request_id": self.request_id,
"status": self.status,
"code": self.code,
"message": self.message,
"data": self.data,
"details": self.details,
"duration": self.duration
}
# 使用示例
def process_data(input_data):
"""处理数据示例函数"""
response = StandardResponse()
start_time = time.time()
try:
# 记录处理步骤
response.add_detail("开始验证输入数据")
if not input_data:
raise ValueError("输入数据不能为空")
response.add_detail("数据验证通过")
# 模拟业务处理
processed_data = {"result": len(input_data)}
response.set_data(processed_data)
except Exception as e:
response.set_error(400, str(e))
response.add_detail(f"处理失败: {str(e)}")
finally:
response.duration = int((time.time() - start_time) * 1000)
return response.to_dict()
4. 错误处理最佳实践
良好的错误处理应该:
-
捕获特定异常 :不要简单地捕获所有 Exception,而应该针对不同异常类型提供不同的处理逻辑。
-
记录完整上下文 :错误信息应该包含足够的问题定位信息,包括:
- 错误发生时的输入参数
- 错误发生的具体步骤
-
相关系统状态
-
分层错误处理 :
- 底层错误:记录技术细节(如数据库错误)
- 业务错误:转换为业务术语(如 ” 用户不存在 ”)
- 用户错误:提供友好的指导(如 ” 请输入有效邮箱 ”)
5. 性能考量
输出描述虽然重要,但也需要考虑性能影响:
-
减少不必要的数据 :只包含真正有用的信息,避免过度记录。
-
异步记录日志 :对于非关键路径的详细日志,可以采用异步方式记录。
-
控制详情级别 :根据运行环境(开发 / 生产)动态调整日志详细程度。
-
优化序列化 :对于高频调用的接口,考虑使用更高效的序列化方式(如 MessagePack)。
6. 最佳实践总结
-
保持一致性 :所有接口 / 工具使用相同的输出结构和命名规范。
-
包含足够上下文 :确保每条记录都能独立定位问题。
-
分层信息展示 :根据查看者角色提供不同级别的信息。
-
避免敏感信息 :不要在日志中记录密码、密钥等敏感数据。
-
考虑国际化 :用户可见的消息应该支持多语言。
思考题
- 在您的项目中,现有的输出描述存在哪些可以改进的地方?
- 如何设计一个既能满足开发调试需求,又不会泄露敏感信息的输出方案?
- 当系统规模扩大后,如何确保不同团队开发的组件仍然保持一致的输出规范?
正文完
