- 人工智能
- AI Agent
- Agent 框架
- 大模型
- 工具调用
- RAG
- 提示工程
- 强化学习
【免费下载链接】agent-core
openJiuwen agent-core可提供AI Agent开发、运行、调优与演进相关的全套SDK能力
本文聚焦 openJiuwen agent-core 框架的统一异常体系:以JiuWenBaseException为起点,深入其底层继承关系、BaseError的模板化消息渲染、错误码(StatusCode)枚举、结构化序列化(to_dict/to_json)以及raise_error等统一抛出入口,并结合源码展示如何在 Agent、工作流、会话等模块中落地这套错误处理机制。
概览:为什么 openJiuwen 需要一套统一异常体系
openJiuwen agent-core 覆盖 AI Agent 的开发、运行、调优与演进全链路,涉及工作流编排、LLM 调用、工具执行、知识检索、多智能体协作、会话与运行时等大量模块。若每个模块各自抛出裸的 Python 异常,错误将难以识别、无法统一序列化、也难以跨 API 边界传递。为此框架定义了以JiuWenBaseException为入口的统一异常类,以及以BaseError为核心的完整异常层级,配合全局StatusCode错误码枚举,形成"错误码 + 模板化消息 + 结构化输出 + 语义化异常类型"的四层体系。
JiuWenBaseException是框架对外文档化的异常类,继承自 Python 内置Exception;而框架内部真正的"统一异常基类"是BaseError。下文将从文档 API 出发,逐层还原其实现。
JiuWenBaseException:框架定义的异常类
构造签名与参数说明
依据 API 文档(exception.md),JiuWenBaseException的构造签名如下:
openjiuwen.core.common.exception.exception.JiuWenBaseException(error_code: int, message: str)参数含义:
- error_code(int):异常的错误码,用于标识异常的类型,可在整个框架的错误码体系中全局定位。
- message(str):异常的错误信息,用于描述异常发生的具体原因。
公开属性
异常对象对外暴露两个只读属性:
| 属性 | 类型 | 说明 |
|---|---|---|
error_code | int | 返回该 openJiuwen 异常对象的错误码 |
message | str | 返回该 openJiuwen 异常对象的错误信息 |
这两个属性分别对应构造时传入的error_code与message,让上层调用方可以精确判断错误类型并读取可展示的错误描述。
使用示例
from openjiuwen.core.common.exception.exception import JiuWenBaseException try: raise JiuWenBaseException(error_code=100005, message="component execute error") except JiuWenBaseException as e: print(e.error_code) # 100005 print(e.message) # component execute error从 JiuWenBaseException 到 BaseError:真正的统一异常基类
从源码结构看,JiuWenBaseException是文档层面向使用者的异常类;而框架内部各模块实际统一继承的基类是BaseError(定义于 openjiuwen/core/common/exception/errors.py)。两者的定位关系可以理解为:
JiuWenBaseException:携带(error_code, message)二元组的框架异常,用于需要显式指定错误码和错误信息的场景;BaseError:携带(status, msg, details, cause, **kwargs)的完整统一基类,直接关联StatusCode枚举,具备模板渲染与序列化能力。
BaseError 的核心设计
BaseError继承自 Python 内置Exception,其设计要点(源码注释原文)是:
- StatusCode 是首要语义标识:每个异常必须绑定一个
StatusCode枚举成员,通过status.code得到整数错误码; - 异常类型表达控制 / 恢复语义:通过不同的子类(如
FrameworkError、ValidationError、ExecutionError)表达"是否致命、是否可重试/重规划"; - 消息渲染基于模板且惰性安全:
_render_message使用_format_template渲染StatusCode.errmsg模板,渲染失败时回退为原始模板,绝不向外抛出格式化异常。
其关键字段如下(errors.py):
class BaseError(Exception): status: StatusCode = StatusCode.ERROR recoverable: bool = False fatal: bool = False def __init__( self, status: StatusCode, *, msg: Optional[str] = None, details: Optional[Any] = None, cause: Optional[BaseException] = None, **kwargs: dict[str, Any], ): self.status = status self.code = self.status.code self.params = kwargs self.details = details self.cause = cause self.__cause__ = cause self._template_message = self._render_message() self.message = msg if msg else self._template_message super().__init__(self._template_message)- status(StatusCode):必填位置参数,标识异常类型,同时作为错误消息模板的来源;
- msg(Optional[str]):自定义错误消息,若提供则覆盖模板渲染结果,默认为
None; - details(Optional[Any]):结构化上下文信息,可为任意类型数据,用于补充错误细节;
- cause(Optional[BaseException]):链式异常,记录导致当前异常的原始异常;
- kwargs(dict[str, Any]):模板参数,用于填充
StatusCode.errmsg模板中的占位符。
语义化异常类型层级
BaseError之下,框架按"错误属于哪类语义"定义了完整的子类层级(同样位于 errors.py):
| 异常类 | 语义 | recoverable | fatal |
|---|---|---|---|
FrameworkError | 基础设施 / 环境 / 依赖失败,必须中止当前执行 | False | True |
ConfigurationError | 框架配置错误(继承自 FrameworkError) | False | True |
ValidationError | 约束 / 校验 / 不支持的能力错误,不应重试或重规划 | False | False |
ExecutionError | 工作流 / Agent / 工具执行期错误,通常可通过重试或重规划恢复 | True | False |
Termination | 非错误的控制流终止(正常停止、取消、完成等) | False | False |
在此基础上,框架按业务域派生出WorkflowError、ComponentError、AgentError、RunnerError、GraphError、ModelError、ToolError、ContextError、SessionError、StoreError、GuardrailError、CryptError等模块级异常。例如GuardrailError用于护栏安全检测拦截场景,携带详细风险信息供日志与上报使用(errors.py)。
错误码到异常类的映射机制
BaseError的STATUS_TO_EXCEPTION全局映射表由build_status_exception_map()构建(status_mapping.py),其规则分为三层:
- 关键字规则(KEYWORD_RULES):按错误码枚举名中的关键词归类。例如名称含
INVALID、PARAM、CONFIG的映射为ValidationError;含INIT、CALL、MODEL、PROVIDER的映射为FrameworkError;含TIMEOUT、EXECUTION、RUNTIME、STREAM的映射为ExecutionError; - 区间规则(RANGE_RULES):按错误码数值区间兜底。例如
100000–119999映射为WorkflowError,120000–129999映射为AgentError,130000–139999映射为RunnerError,140000–149999映射为GraphError,150000–159999映射为ContextError,190000–198999映射为SessionError; - 手动覆盖(MANUAL_OVERRIDES):对特定名称显式指定异常类,例如
CONTROLLER_INVOKE_LLM_FAILED强制为FrameworkError、TOOL_EXECUTION_ERROR强制为ToolError、TOOL_NOT_FOUND_ERROR强制为ValidationError。
这意味着:只需传入一个StatusCode,框架就能自动决定抛出哪种语义的异常类,无需调用方手动选择。
StatusCode:全局错误码枚举与分区规范
错误码枚举定义于 openjiuwen/core/common/exception/codes.py,每个枚举成员是(code, message_template)二元组:
class StatusCode(Enum): SUCCESS = (0, "success") ERROR = (-1, "error") WORKFLOW_COMPONENT_ID_INVALID = ( 100010, "the component id is invalid for component '{comp_id}', reason='{reason}', workflow='{workflow}'") COMPONENT_LLM_INVOKE_CALL_FAILED = (101003, "component llm_invoke call failed, reason: {error_msg}") # ... 更多成员错误码按数值区间划分业务域,涵盖组件、工作流、Agent 编排、运行时、上下文引擎、知识库检索、记忆引擎、优化工具链、公共能力等。完整的"枚举常量 → 错误码 → 描述 → 解决方案"对照表可在 status_code.md 中查阅,例如:
- 组件相关错误(100000–109999):如
COMPONENT_EXECUTE_ERROR(100005)表示工作流中组件执行出现异常;LLM_COMPONENT_INVOKE_LLM_ERROR(101003)表示 LLM 服务调用返回错误,需检查 LLM 服务配置; - 工作流相关错误(110000–119999):如
GRAPH_ADD_NODE_FAILED(110003)、WORKFLOW_COMPONENT_CONFIG_ERROR(110006); - Agent 编排相关错误(120000–129999):如
TOOL_NOT_FOUND_ERROR(120000)、CONTROLLER_INVOKE_LLM_FAILED(123000); - 运行时相关错误(190000–199999):如
RUNTIME_AGENT_GET_FAILED(190051)、STREAM_FRAME_TIMEOUT_FAILED(193003)。
错误码生成规范(面向扩展)
如果需要在框架中新增错误码,可参考 code_template.py 提供的生成规范:
- scope 取值域:
WORKFLOW、COMPONENT、AGENT、TOOL、MODEL、SESSION、GRAPH、CONTROLLER、RUNNER、PROMPT、COMMON、CONTEXT、TOOLCHAIN、MEMORY、RETRIEVAL、SYS_OPERATION; - failure_type 取值域:
INVALID、NOT_FOUND、NOT_SUPPORTED、CONFIG_ERROR、PARAM_ERROR、TYPE_ERROR、INIT_FAILED、CALL_FAILED、EXECUTION_ERROR、RUNTIME_ERROR、PROCESS_ERROR、TIMEOUT、INTERRUPTED; - 每种 failure_type 对应一套消息模板,例如
TIMEOUT会生成"{scope} {subject} timeout ({timeout}s)",并在失败信息末尾追加", reason: {error_msg}"; - 消息渲染采用
str.format_map安全格式化:缺失的占位符会显示为<missing:KEY>而非抛出KeyError(见_SafeDict实现,errors.py)。
异常的结构化输出:to_dict 与 to_json
BaseError提供两个核心序列化方法(errors.py),这也是JiuWenBaseException面向 API / RPC / 日志场景的重要能力来源:
to_dict:面向 API / RPC / 日志的结构化字典
def to_dict(self) -> Dict[str, Any]: return { "code": self.code, "status": self.status.name, "message": self._template_message, "params": self.params, "raw_message": self.message, "details": self.details, }返回字典包含六个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
code | int | 错误码(整数) |
status | str | 状态码枚举名(字符串) |
message | str | 由模板渲染出的消息 |
params | dict | 模板参数 |
raw_message | str | 自定义消息或渲染消息(即实际对外展示的原始消息) |
details | Any | 详细信息 |
to_json:UTF-8 安全的 JSON 序列化
def to_json(self) -> str: return json.dumps(self.to_dict(), ensure_ascii=False)to_json基于to_dict序列化为 JSON 字符串,并指定ensure_ascii=False,保证中文等多语言错误消息以 UTF-8 原文输出而不被转义为\uXXXX。
应用场景
- API 响应:将异常统一序列化为
{code, status, message, ...}结构,客户端可按code精确处理错误分支; - RPC 调用:跨进程传递时使用
to_json得到可传输的字符串; - 日志记录:结构化日志可直接落库
to_dict()结果,便于检索与聚合分析。
统一抛出入口:raise_error 与系列工厂函数
为了统一异常抛出方式,errors.py 还提供了若干工厂函数,它们共同构成框架的"错误入口层":
def build_error(status, *, msg=None, details=None, cause=None, **kwargs) -> BaseError: # 仅构造不抛出,适合延迟抛出或包装场景 exc_cls = STATUS_TO_EXCEPTION.get(status, FrameworkError) return exc_cls(status, msg=msg, details=details, cause=cause, **kwargs) def raise_error(status, *, msg=None, details=None, cause=None, **kwargs) -> None: # 统一错误抛出入口 raise build_error(status, msg=msg, details=details, cause=cause, **kwargs) def system_error(status, *, cause=None, **kwargs) -> None: raise FrameworkError(status, cause=cause, **kwargs) def validate_error(status, *, cause=None, **kwargs) -> None: raise ValidationError(status, cause=cause, **kwargs) def terminate(status, **kwargs) -> None: raise Termination(status, **kwargs)使用方式示例:
from openjiuwen.core.common.exception.codes import StatusCode from openjiuwen.core.common.exception.errors import raise_error, system_error, validate_error # 抛出一个"工作流组件执行错误",并填充模板参数 reason raise_error( StatusCode.COMPONENT_LLM_INVOKE_CALL_FAILED, msg="llm service unavailable", details={"provider": "siliconflow"}, error_msg="connection refused", ) # 系统级错误:框架初始化失败 system_error(StatusCode.COMPONENT_LLM_INIT_FAILED, error_msg="invalid api key") # 校验类错误:参数非法 validate_error(StatusCode.WORKFLOW_COMPONENT_ID_INVALID, comp_id="comp-1", reason="duplicated", workflow="wf-1")其中error_msg、comp_id、reason、workflow等关键字正是对应StatusCode消息模板中的占位符,会被_format_template自动填充。
源码佐证:异常体系在框架各模块中的实际落地
在框架各模块的源码与文档中,可以找到大量使用该异常体系的实例,印证其调用关系与用法:
- 工作流组件:在组件执行失败时抛出带
StatusCode的框架异常,例如 LLM 组件、分支组件、循环组件、子工作流组件各自的错误码均定义在StatusCode中(codes.py); - 会话与调测:
JiuWenBaseException在 Session 调测能力 与 使用预置组件 等文档中被引用,说明会话层的错误处理同样遵循该体系; - 图 / 工作流 API:graph.md 与 components.md 等 API 文档记录了这些模块抛出框架异常时的行为;
- LLM 基础能力:llm.md 中 LLM 组件的调用失败、配置错误等均映射到对应的
StatusCode枚举。
完整异常速查:错误码分区与排查建议
框架错误码按数值区间划分为 17 个业务域(详见 status_code.md),常用分区如下:
| 错误码区间 | 业务域 | 典型错误码示例 |
|---|---|---|
| 100000–109999 | 组件相关 | INTERACTIVE_INVALID_INPUT_ERROR(100000)、LLM_COMPONENT_INVOKE_LLM_ERROR(101003)、BRANCH_COMPONENT_BRANCH_NOT_FOUND_ERROR(101102) |
| 110000–119999 | 工作流相关 | GRAPH_ADD_NODE_FAILED(110003)、WORKFLOW_COMPONENT_CONFIG_ERROR(110006) |
| 120000–129999 | Agent 编排 | TOOL_NOT_FOUND_ERROR(120000)、CONTROLLER_PARSE_TOOL_CALL_ERROR(123005) |
| 130000–139999 | 多智能体 / Runner | AGENT_GROUP_CREATE_FAILED(132001)、AGENT_NOT_FOUND(134002)、TOOL_NOT_FOUND(134005) |
| 140000–149999 | 图执行引擎 | EXPRESSION_CONDITION_SYNTAX_ERROR(140000)、NUMBER_CONDITION_ERROR(140003) |
| 150000–159999 | 上下文 / 检索 / 记忆 | CONTEXT_ENGINE_MESSAGE_PROCESS_ERROR(153000)、EMBEDDING_EMPTY_INPUT_ERROR(155000)、RETRIEVER_TOP_K_INVALID_ERROR(155210)、MEMORY_ADD_MEMORY_EXECUTION_ERROR(158002) |
| 160000–179999 | 优化工具链 | AGENT_BUILDER_AGENT_PARAMS_ERROR(170000)、AGENT_BUILDER_AGENT_TRAINER_TRAIN_ERROR(170040) |
| 180000–189999 | 公共能力 | MODEL_PROVIDER_INVALID_ERROR(181000)、PLUGIN_RESPONSE_TOO_BIG_ERROR(182003)、LOG_PATH_SENSITIVE_ERROR(183000)、JSON_LOADS_ERROR(188002) |
| 190000–199999 | 运行时 / 会话 | RUNTIME_AGENT_GET_FAILED(190051)、STREAM_FIRST_FRAME_TIMEOUT_FAILED(193004)、RUNTIME_CHECKPOINTER_NONE_AGENT_STORE_ERROR(197001) |
每个错误码在 status_code.md 中均配有 DESCRIPTION(错误描述)与 RESOLUTION(解决方案)两列,可直接作为排障手册使用。例如TOOL_NOT_FOUND_ERROR(120000)的排查建议是"根据异常详情检查工具 ID 是否正确,并确认工具已创建且处于正常状态"。
小结:异常处理的推荐实践
基于上述分析,在 openJiuwen 项目中处理异常时推荐以下实践:
- 优先使用
StatusCode+raise_error:不要直接抛出裸Exception,通过raise_error(StatusCode.XXX, **模板参数)让框架自动选择正确的异常类并渲染消息; - 善用结构化输出:面向外部 API 或日志时,统一调用
to_dict()/to_json(),保证错误信息可机器解析; - 区分异常语义:利用
FrameworkError(致命、需中止)、ValidationError(不应重试)、ExecutionError(可重试/重规划)表达错误恢复策略,方便上层编排逻辑做出正确决策; - 链式保留原始异常:构造时传入
cause,保留异常调用链,便于排查根因; - 查阅错误码速查表:遇到具体错误码时,直接对照 status_code.md 中的 RESOLUTION 列进行排障。
相关参考文档与源码:
- exception.md(API 文档:JiuWenBaseException)
- errors.md(API 文档:BaseError)
- status_code.md(API 文档:错误码全量表)
- errors.py(BaseError 与异常层级实现)
- codes.py(StatusCode 枚举实现)
- status_mapping.py(错误码到异常类的映射规则)
- code_template.py(错误码与消息模板生成规范)
- 人工智能
- AI Agent
- Agent 框架
- 大模型
- 工具调用
- RAG
- 提示工程
- 强化学习
【免费下载链接】agent-core
openJiuwen agent-core可提供AI Agent开发、运行、调优与演进相关的全套SDK能力
相关推荐
openJiuwen agent-core 统一异常体系解析:BaseError 与 StatusCode 错误码全解
openJiuwen agent core 统一异常体系解析:BaseError 与 StatusCode 错误码全解 本篇技术指南以 errors.md ht
人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习Moonshine Micro 特征生成模块解析:面向 MCU 的无堆 log-mel 前端(批量 + 流式)
Moonshine Micro 特征生成模块解析:面向 MCU 的无堆 log mel 前端(批量 + 流式) 本指南围绕 micro/feature gene
人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习Faraday 错误处理实战指南:统一异常体系与 raise_error 中间件
Faraday 错误处理实战指南:统一异常体系与 raise_error 中间件 Faraday 是用户与底层 HTTP 库之间的抽象层,为了让上层应用不依赖具
后端网络通信
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考