- 人工智能
- AI Agent
- Agent 框架
- 工具调用
- Agent 工作流
- RAG
- MCP Clients
- 强化学习
【免费下载链接】agent-core-java
openJiuwen agent core Java是 openJiuwen Core的 Java版本,提供AI Agent开发、运行、调优与演进相关的全套SDK能力。
本文围绕 openJiuwen agent-core-java(com.openjiuwen.core.controller.legacy.task.Task)旧版控制器兼容任务模型展开:它既是旧版意图检测控制器(IntentDetectionController)与 reasoner/planner 协作的载体,也是理解旧版控制器如何描述"执行什么、依赖什么、执行到哪一步"的核心数据对象。读完本文,你将掌握Task的 13 个字段的语义与默认值、TaskStatus/TaskType/DependencyType三类枚举的取值与序列化规则、TaskInput/TaskResult/TaskDependency三个嵌套类型的设计,以及Task在"新建任务→执行→中断→恢复→取消"整条流转链路中的真实用法。
一、Task 在旧版控制器中的定位
Task是旧版(legacy)控制器体系的兼容任务模型,用于记录任务的标识、状态、输入输出与依赖关系。它在源码中位于 core/src/main/java/com/openjiuwen/core/controller/legacy/task/Task.java,与TaskStatus、TaskInput、TaskResult、TaskDependency、DependencyType同属com.openjiuwen.core.controller.legacy.task包。
根据 controller/legacy.README.md 的说明,com.openjiuwen.core.controller.legacy保留了早期 Controller 体系的兼容 API,包括基于内存消息队列的控制器基类、意图检测控制器、旧版 reasoner、事件模型、任务模型和工具函数。该子树主要用于兼容旧代码路径,新控制器能力应优先参考com.openjiuwen.core.controller、modules和schema包。
从源码结构看,Task类注释明确声明它是对 Python 版本openjiuwen/core/controller/legacy/task/task.py中Task的镜像(Mirrors),因此在 Java 端负责承载与 Python 旧版控制器相同的任务语义,保证跨语言行为一致性。
类声明本身非常简洁:
@Data @NoArgsConstructor @JsonInclude(JsonInclude.Include.NON_NULL) public class Task { // 13 个业务字段,见下文 }@Data:Lombok 生成 getter、setter、equals/hashCode/toString,这与文档中"依赖 Lombok 生成访问器"的描述一致;@NoArgsConstructor:提供无参构造,便于反序列化与默认创建;@JsonInclude(JsonInclude.Include.NON_NULL):Jackson 序列化时跳过null字段,避免空字段污染检查点或消息体。
值得注意的细节是:虽然文档提及"使用 Lombok builder 管理任务标识、状态、输入输出和依赖关系",但当前Task类实际只标注了@Data与@NoArgsConstructor,并未标注@Builder;真正提供显式构造的是嵌套类型TaskDependency(提供TaskDependency(String dependencyId)与全参构造)和TaskInput(提供TaskInput(String targetId, String targetName, Object arguments))、TaskResult(提供TaskResult(TaskStatus, Object, String, Map))。Task自身主要依赖无参构造加 setter 完成组装,这一点从DefaultPlanner与测试代码中new Task()加逐字段 setter 的用法可以得到印证。
二、核心字段表:语义、类型与默认值
原文档的字段表是理解Task的入口。结合源码,各字段的完整语义如下:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
agentId | String | null | 任务所属 agent,序列化字段名为agent_id |
taskId | String | ""(空字符串) | 任务 ID,序列化字段名为task_id |
taskType | TaskType | TaskType.UNDEFINED | 任务类型,序列化字段名为task_type |
description | String | null | 任务描述 |
status | TaskStatus | TaskStatus.PENDING | 任务当前状态 |
metadata | Map<String, Object> | 空LinkedHashMap | 附加元数据 |
input | TaskInput | 新TaskInput实例 | 任务输入 |
result | TaskResult | null | 任务结果 |
dependencies | List<TaskDependency> | 空ArrayList | 该任务的依赖列表 |
dependents | Set<String> | 空LinkedHashSet | 依赖本任务的哪些任务 |
parentTaskId | String | null | 父任务 ID,序列化字段名为parent_task_id |
childTaskIds | Set<String> | 空LinkedHashSet | 子任务 ID 集合,序列化字段名为child_task_ids |
groupId | String | null | 所属 group,序列化字段名为group_id |
level | int | 0 | 层级深度 |
与原文档字段表相比,源码补充了三个关键信息:
JSON 字段名:
agentId、taskId、taskType、parentTaskId、childTaskIds、groupId均通过@JsonProperty映射为下划线风格的 wire 名(agent_id、task_id、task_type、parent_task_id、child_task_ids、group_id),而description、status、metadata、input、result、dependencies、dependents、level未加注解,序列化时直接使用字段名。这与 Python 端任务模型的 JSON 表示保持一致。集合默认值:
metadata、dependencies、dependents、childTaskIds分别初始化为LinkedHashMap/ArrayList/LinkedHashSet,保证无参构造后即可安全遍历,避免 NPE。setter 空值归一化:
Task重写了setAgentId、setMetadata、setInput、setDependencies、setDependents、setChildTaskIds这几个 setter,将传入的null统一替换为对应的空集合/新实例。例如传入null的input会被重置为new TaskInput(),传入null的dependencies会被替换为空ArrayList。这意味着调用方"先置空再赋值"也能得到健壮的任务对象。
level字段用于标记任务在分解树中的层级深度(默认0,表示顶层任务),配合parentTaskId/childTaskIds可以还原出任务分解(decomposition)的树状结构;groupId则用于把一组相关任务归入同一个执行组,便于批量管理与编排。
三、任务分类:TaskType 枚举
taskType字段的类型是com.openjiuwen.core.common.constants.TaskType(见 core/src/main/java/com/openjiuwen/core/common/constants/TaskType.java),它定义了任务的执行形态:
| 枚举值 | wire 值 | 含义 |
|---|---|---|
PLUGIN | plugin | 插件类任务 |
WORKFLOW | workflow | 工作流任务 |
MCP | mcp | MCP 工具类任务 |
UNDEFINED | undefined | 未定义类型(默认值) |
TaskType.fromValue(String)采用宽容解析:能匹配到对应 wire 值就返回该类型,否则统一回退为UNDEFINED,不会抛异常。测试 core/src/test/java/com/openjiuwen/core/application/workflow_agent/WorkflowControllerTest.java 中,意图检测识别到工作流后生成的Task其taskType即被设置为TaskType.WORKFLOW(见singleWorkflowCreatesNewTaskWithFilteredInputs用例),说明taskType是控制器选择执行路径的依据之一。
四、任务状态机:TaskStatus 枚举
status字段使用TaskStatus枚举(core/src/main/java/com/openjiuwen/core/controller/legacy/task/TaskStatus.java),它是任务生命周期状态机:
| 枚举值 | wire 值 | 含义 |
|---|---|---|
PENDING | pending | 待执行(默认值) |
RUNNING | running | 运行中 |
SUCCESS | success | 成功 |
FAILED | failed | 失败 |
CANCELLED | cancelled | 已取消 |
INTERRUPTED | interrupted | 已中断(等待用户补充输入) |
INPUT_REQUIRED | input-required | 需要输入补充 |
原文档描述"覆盖待执行、运行中、成功、失败、已取消和已中断",源码在此基础上还增加了INPUT_REQUIRED,用于显式表达"任务等待用户输入"的中间态。
两个与序列化直接相关的实现细节:
@JsonValue:枚举序列化时输出的是 wire 小写字符串(如"pending"),而非 Java 枚举名;@JsonCreator fromValue(String):反序列化时同时接受wire 值与枚举名(status.value.equals(value) || status.name().equals(value)),因此从检查点(checkpoint)或 JSON 中恢复状态时,无论存的是"running"还是"RUNNING"都能正确解析;对于空白或未知字符串,则安全回退为PENDING,避免旧数据损坏后直接抛异常。
五、任务输入与输出:TaskInput 与 TaskResult
5.1 TaskInput:描述"执行什么"
TaskInput(core/src/main/java/com/openjiuwen/core/controller/legacy/task/TaskInput.java)描述任务的目标与参数:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
targetId | String | "" | 目标标识(如工作流weather_1.0),序列化字段名target_id |
targetName | String | "" | 目标名称,序列化字段名target_name |
arguments | Object | 空LinkedHashMap | 任务参数(实际往往为Map<String, Object>) |
targetId通常形如<workflow>_<version>。测试中生成的Task其input.targetId为"weather_1.0",arguments为经过筛选后的参数字典(例如只保留工作流 schema 中声明的city、unit,丢弃无关的ignored扩展字段),说明TaskInput承担了"把用户查询转成结构化目标调用参数"的职责。setArguments同样做了 null 归一化,传入null会重置为空LinkedHashMap。
5.2 TaskResult:描述"执行得怎样"
TaskResult(core/src/main/java/com/openjiuwen/core/controller/legacy/task/TaskResult.java)描述任务执行结果:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
status | TaskStatus | null | 结果状态 |
output | Object | null | 任务输出 |
error | String | null | 错误信息 |
metadata | Map<String, Object> | 空LinkedHashMap | 结果元数据 |
output使用Object类型,可以承载字符串、结构化 Map 或任意业务对象;error记录失败原因;metadata可附加执行统计等辅助信息。setMetadata同样把null归一化为空映射。
六、任务依赖模型:TaskDependency 与 DependencyType
6.1 依赖关系四分类
DependencyType(core/src/main/java/com/openjiuwen/core/controller/legacy/task/DependencyType.java)定义任务间的依赖关系类型,原文档概括为"顺序、并行、条件和数据依赖":
| 枚举值 | wire 值 | 含义 |
|---|---|---|
SEQUENTIAL | sequential | 顺序依赖:前序任务完成后才能执行 |
PARALLEL | parallel | 并行依赖:可与依赖任务并行执行 |
CONDITIONAL | conditional | 条件依赖:满足condition才触发 |
DATA | data | 数据依赖:需要依赖任务的数据产出 |
与TaskStatus不同,DependencyType.fromValue(String)是严格解析:未知值会抛出IllegalArgumentException("Unknown dependency type: ..."),null则返回null。这说明依赖类型一旦写入持久化数据就应当保持合法值,容错性低于状态字段。
6.2 单条依赖的描述:TaskDependency
TaskDependency(core/src/main/java/com/openjiuwen/core/controller/legacy/task/TaskDependency.java)描述"依赖哪个任务、怎么依赖、何时触发、数据如何流转":
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
dependencyId | String | null | 被依赖任务的 ID,序列化字段名dependency_id |
dependencyType | DependencyType | SEQUENTIAL | 依赖类型,序列化字段名dependency_type |
condition | String | null | 触发条件(条件依赖时使用) |
dataMapping | Map<String, String> | 空LinkedHashMap | 数据映射(上游输出字段 → 本任务输入字段),序列化字段名data_mapping |
required | boolean | true | 该依赖是否必需 |
TaskDependency提供两个构造器:TaskDependency(String dependencyId)便捷构造,以及包含全部字段的全参构造;setDependencyType与setDataMapping同样做 null 归一化(分别回退到SEQUENTIAL与空映射)。
6.3 正向依赖与反向依赖
Task通过两组字段双向表达任务图:
- 正向:
dependencies(List<TaskDependency>)——本任务依赖谁,携带依赖类型、条件与数据映射; - 反向:
dependents(Set<String>)——谁依赖本任务(被依赖者视角的任务 ID 集合)。
配合parentTaskId(父任务 ID)与childTaskIds(子任务 ID 集合),可以同时还原"任务分解树"(父-子)与"任务依赖图"(依赖-被依赖)两层结构。level字段则标记任务在分解树中的深度。
七、Task 在 IntentDetectionController 中的执行流转
原文档明确指出:"IntentDetectionController和旧版 reasoner/planner 主要围绕这一任务模型协作"。以 core/src/main/java/com/openjiuwen/core/controller/legacy/IntentDetectionController.java 为参照,Task是意图检测结果(Intent)与任务执行之间的"交接单":
Intent类(IntentDetectionController.Intent)持有Task task字段,并由IntentType决定后续动作:
| IntentType | wire 值 | 对 Task 的处理 |
|---|---|---|
EXEC_NEW_TASK | exec_new_task | handleNewTask:取intent.getTask(),置status = PENDING后调用execTask执行 |
RESUME_TASK | resume_task | handleResume:校验任务为INTERRUPTED状态,从会话状态workflow_controller.interrupted_tasks中还原被中断的组件,把用户输入重映射进task.getInput().setArguments(...)后重新execTask |
CANCEL_TASK | cancel_task | handleCancel:置status = CANCELLED,返回取消结果 |
DEFAULT_RESPONSE | default_response | 走默认回复,不触碰任务 |
UNKNOWN | unknown | 走未知意图兜底 |
关键源码片段(handleNewTask):
protected Map<String, Object> handleNewTask(Event event, Intent intent, Object session) { Task task = intent.getTask(); if (task == null) { return Map.of("status", "error", "message", "Task not found in intent"); } task.setStatus(TaskStatus.PENDING); LOG.info("Handling new task: task_id={}", task.getTaskId()); return execTask(event == null ? null : event.getContent(), task, session); }handleResume的细节值得展开:当任务因人机交互中断后,会话状态中保存了interrupted_tasks,键为workflowId.replace('.', '_')(如flow_1_2),值包含task与component_id。恢复时控制器会从会话状态读出被中断的组件 ID,将用户输入映射到该组件所需的InteractiveInput,再写回task.input.arguments并重新执行——这正是Task承担"可中断、可恢复"状态载体的体现。status从INTERRUPTED恢复为执行态,贯穿整个生命周期。
此外,控制器内维护了TaskQueue(含RunningTaskInfo,记录task、Future<?>、targetId、startTime),通过registerTask(conversationId, task, future, targetId)把运行中的任务与异步执行句柄关联起来,为并发任务跟踪提供支撑。
八、旧版 reasoner/planner 与 Task 的协作
旧版 reasoner 体系由IntentDetector(意图检测)与Planner(任务规划)组合而成(见 core/src/main/java/com/openjiuwen/core/controller/legacy/reasoner/AgentReasoner.java),两者都以Task为产出物:
AgentReasoner.detect(Event, AgentSessionApi)通过intentDetector.processMessage(event)检测意图;AgentReasoner.plan(Intent, AgentSessionApi)通过planner.processMessage(...)产出List<Task>。
DefaultPlanner(core/src/main/java/com/openjiuwen/core/controller/legacy/reasoner/DefaultPlanner.java)展示了最基础的任务创建范式——createDefaultTask用new Task()无参构造后逐字段 setter 组装:
Map<String, Object> meta = new LinkedHashMap<>(); meta.put("original_message_id", event.getEventId()); meta.put("task_source", "planner"); Task task = new Task(); task.setTaskType(TaskType.UNDEFINED); task.setDescription(desc); task.setStatus(TaskStatus.PENDING); task.setMetadata(meta);可以看到:新建任务显式置PENDING状态、在metadata中记录消息来源与原始消息 ID,为后续执行与追踪提供线索。这印证了metadata字段在旧版链路中用于携带任务溯源信息。
九、测试验证与新旧模型对照
9.1 测试对 Task 行为的验证
测试 core/src/test/java/com/openjiuwen/core/application/workflow_agent/WorkflowControllerTest.java 直接覆盖了Task的关键行为:
singleWorkflowCreatesNewTaskWithFilteredInputs:验证意图检测后生成的Task——taskId为"workflow_EVT"、taskType为TaskType.WORKFLOW、status为TaskStatus.PENDING、input.targetId为"weather_1.0"、arguments仅含 schema 声明字段;interruptedStructuredValueReturnsInterruptionAgain:通过会话状态预置interrupted_tasks(包含task与component_id)验证中断任务的恢复路径;- 其余用例验证了未配置工作流时意图检测抛
IllegalArgumentException、多工作流回退默认回复等行为。
这些测试同时可作为Task组装与状态流转的"可运行示例"参考。
9.2 与 schema 版 Task 的区别
仓库中还存在新控制器体系的任务模型 controller/schema/Task.md(源码位于com.openjiuwen.core.controller.schema),两者定位不同:
| 维度 | legacyTask | schemaTask |
|---|---|---|
| 定位 | 旧版控制器兼容任务模型,配合意图检测与 reasoner/planner | 控制器内部任务模型,配合TaskManager执行管理 |
| 状态 | TaskStatus(PENDING/RUNNING/SUCCESS/FAILED/CANCELLED/INTERRUPTED/INPUT_REQUIRED) | TaskStatus(含 SUBMITTED/COMPLETED/TIMEOUT 等,见 core/src/test/java/com/openjiuwen/core/common/task_manager/TaskStatusTest.java) |
| 输入 | 单个TaskInput(targetId/targetName/arguments) | List<Object> inputs输入对象列表 |
| 输出 | 单个TaskResult | List<ControllerOutputChunk> outputs输出块列表 |
| 特有能力 | 依赖模型(dependencies/dependents+DependencyType)、level层级 | 优先级priority、validate()校验、copy()深拷贝、toMap()/fromMap()持久化 |
简言之:legacyTask面向"意图→规划→执行"的旧版协作链路,schemaTask面向新控制器的执行管理与持久化。选型时新项目应优先使用 schema 体系,legacyTask仅用于兼容旧代码路径。
十、总结
com.openjiuwen.core.controller.legacy.task.Task是旧版控制器兼容体系中"任务即数据"的集中体现:
- 标识与归属:
taskId/taskType/agentId/groupId/level定义了任务的身份、分类与层级; - 生命周期:
TaskStatus状态机(含INPUT_REQUIRED)配合TaskInput/TaskResult记录任务从待执行到成功/失败/取消/中断的全过程; - 编排结构:
dependencies/dependents/parentTaskId/childTaskIds双向描述任务分解树与依赖图,TaskDependency+DependencyType表达顺序、并行、条件与数据四类关系; - 协作链路:
IntentDetectionController负责按IntentType驱动任务流转,reasoner/planner 负责产出任务,metadata承担溯源与附加信息。
它保留了 Python 端任务模型的字段与 JSON 语义(snake_case wire 名、宽容的状态反序列化、严格的依赖类型解析),是理解旧版控制器架构、迁移遗留代码、以及对照 schema 版任务模型时必读的类型。相关源码与测试可进一步参阅 legacy/task 包、IntentDetectionController.java 与 WorkflowControllerTest.java。
- 人工智能
- AI Agent
- Agent 框架
- 工具调用
- Agent 工作流
- RAG
- MCP Clients
- 强化学习
【免费下载链接】agent-core-java
openJiuwen agent core Java是 openJiuwen Core的 Java版本,提供AI Agent开发、运行、调优与演进相关的全套SDK能力。
相关推荐
从VSCode到Neovim:Claude Code跨编辑器无缝迁移指南
从VSCode到Neovim:Claude Code跨编辑器无缝迁移指南 为什么选择Claude Code Neovim插件? 对于习惯了VSCode的开发者来
AI 应用开发工具Semantic Router 的项目目标:为 LLM 系统构建系统级集体智能(Mixture-of-Models)
Semantic Router 的项目目标:为 LLM 系统构建系统级集体智能(Mixture of Models) 本文以 Semantic Router 项
后端API网关模型推理服务AI AgentInvokeAI关系服务:模型依赖关系与兼容性管理
InvokeAI关系服务:模型依赖关系与兼容性管理 在AI视觉创作领域,你是否曾遇到过精心挑选的LoRA模型无法与基础模型协同工作?或者因模型版本不兼容导致生成
人工智能大模型媒体生成后端前端流程编排
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考