人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习【免费下载链接】agent-core-javaopenJiuwen agent core Java是 openJiuwen Core的 Java版本提供AI Agent开发、运行、调优与演进相关的全套SDK能力。项目地址https://gitcode.com/openJiuwen/agent-core-java点击查看免费下载导读在 openJiuwen agent-core-javaopenJiuwen Core 的 Java 版本中控制器Controller负责把用户输入拆解为一个个可调度、可执行、可追踪的任务Task。而com.openjiuwen.core.common.constants.TaskType正是任务路由中用于标识任务类型的核心枚举它定义了PLUGIN插件任务、WORKFLOW工作流任务、MCPMCP 任务与UNDEFINED未知回退值四种类型并配套getValue()与fromValue()两个方法。本文将以 TaskType.java 为骨架结合 TaskScheduler、TaskExecutorRegistry、MessageHandlerUtils 等源码实现与测试用例系统讲解 TaskType 的枚举定义、字符串线格式wire format、解析语义以及它在任务创建、路由、执行器注册和调度执行全链路中的实际作用帮助你准确使用该类型并理解控制器任务模型的底层原理。一、TaskType 枚举定义1.1 类位置与定位TaskType位于core/src/main/java/com/openjiuwen/core/common/constants/TaskType.java它是com.openjiuwen.core.common.constants包下的一个普通 Java 枚举其 Javadoc 明确指出该枚举是对 Python 版 openjiuwen Core 中openjiuwen/core/common/constants/enums.py的TaskType的镜像实现Mirrors PythonsTaskType。这意味着Java 版与 Python 版的枚举值、字符串值保持一一对应跨语言、跨进程例如经由消息队列或序列化数据交互时任务类型标识可以互通该枚举属于common.constants层是任务模型、控制器、调度器等模块共用的公共契约而不是某个业务模块的私有类型。1.2 枚举值一览依据 TaskType.md 与源码枚举共包含 4 个值枚举值字符串值说明PLUGINplugin插件任务。WORKFLOWworkflow工作流任务。MCPmcpMCP 任务。UNDEFINEDundefined未知输入的回退值。对应源码实现如下TaskType.javapublic enum TaskType { PLUGIN(plugin), WORKFLOW(workflow), MCP(mcp), UNDEFINED(undefined); private final String value; TaskType(String value) { this.value value; } public String getValue() { return value; } public static TaskType fromValue(String value) { for (TaskType type : values()) { if (type.value.equals(value)) { return type; } } return UNDEFINED; } }1.3 为什么字符串值用小写PLUGIN、WORKFLOW、MCP、UNDEFINED是 Java 枚举常量的命名大写下划线风格而getValue()返回的plugin、workflow、mcp、undefined是实际参与序列化、存储与跨模块传递的字符串值。从源码中的序列化逻辑可以确认任务持久化与跨模块传输使用的是小写字符串值例如controller/schema/Task.java 的toMap()将task_type字段以原始字符串写入 MapLlmEventHandler.java 在序列化任务列表时直接输出task.getTaskType()即plugin/workflow/mcp/undefined。因此凡是需要与外部系统、存储或 Python 版 Core 对齐的字符串必须使用getValue()的小写值而不能直接使用 Java 枚举名。二、两个方法的语义与解析规则2.1 getValue()返回字符串值public String getValue()返回当前枚举实例对应的字符串值。常见用法是构造任务时直接传入Task task new Task(session.getSessionId(), randomWorkflowTaskId(), TaskType.WORKFLOW.getValue());这段代码正是 WorkflowEventHandler.java 在路由新建工作流任务时的真实写法。2.2 fromValue()宽松解析失败回退 UNDEFINEDpublic static TaskType fromValue(String value)遍历全部枚举值若某枚举的value与入参完全相等equals匹配大小写敏感则返回对应枚举若没有任何匹配包括传入null或空字符串不会抛异常而是统一返回UNDEFINED。这一宽容回退的设计非常关键它是任务模型中未知输入的兜底标识避免了解析异常导致链路中断。与之形成对照的是 DependencyType后者在fromValue无匹配时抛出IllegalArgumentException——两者对比可见 TaskType 的设计意图是尽量不失败、让未知类型走 UNDEFINED 分支。三、TaskType 在任务模型中的角色3.1 新控制器模型字符串字段承载类型在新版控制器数据模型 controller/schema/Task.java 中taskType被定义为普通字符串字段JsonProperty(task_type)构造时直接接受TaskType.getValue()的产物public Task(String sessionId, String taskId, String taskType) { ... }对应的测试 TaskSchemaTest.java 验证了getTaskType()返回原始字符串WorkflowEventHandlerTest.java 则断言任务类型等于workflow。3.2 旧控制器模型直接以枚举类型存储在旧版legacy任务模型 controller/legacy/task/Task.java 中taskType字段的类型就是TaskType且默认值为UNDEFINEDprivate TaskType taskType TaskType.UNDEFINED;TaskTypesTest.java 断言新建任务的默认taskType为TaskType.UNDEFINED这印证了未知/未指定时回退 UNDEFINED的默认语义。四、任务类型是如何产生的从 LLM 工具调用到 TaskType 映射任务类型不是凭空而来的而是在意图识别 / 规划阶段根据用户配置与 LLM 输出生成的。核心实现在 MessageHandlerUtils.java4.1 determineTaskType按工具名匹配public static TaskType determineTaskType(String toolName, AgentConfigView config) { for (WorkflowView workflow : safeWorkflows(config)) { if (workflow ! null Objects.equals(toolName, workflow.name())) { return TaskType.WORKFLOW; } } for (PluginView plugin : safePlugins(config)) { if (plugin ! null Objects.equals(toolName, plugin.name())) { return TaskType.PLUGIN; } } throw ErrorHelper.buildError( StatusCode.AGENT_TOOL_NOT_FOUND, error_msg, not find tool call type: toolName ); }逻辑要点若工具名与某个已配置工作流WorkflowView的名字相等 →WORKFLOW否则若与某个插件PluginView的名字相等 →PLUGIN都匹配不到则抛出AGENT_TOOL_NOT_FOUND错误。4.2 createTasksFromToolCalls同时命中则生成两类任务for (WorkflowView workflow : safeWorkflows(config)) { if (workflow ! null Objects.equals(workflow.name(), toolName)) { TaskInput taskInput new TaskInput( workflow.id() _ workflow.version(), toolName, parseToolArguments(toolCall, toolName, workflow)); result.add(createTask(toolCall.getId(), TaskType.WORKFLOW, taskInput)); break; } } for (PluginView plugin : safePlugins(config)) { if (plugin ! null Objects.equals(plugin.name(), toolName)) { TaskInput taskInput new TaskInput(, toolName, parseToolArguments(toolCall, toolName, plugin)); result.add(createTask(toolCall.getId(), TaskType.PLUGIN, taskInput)); break; } }值得注意的是当同一个工具名同时匹配工作流与插件时会同时生成一个WORKFLOW任务和一个PLUGIN任务测试 MessageHandlerUtilsTest.java 验证了这一点由后续调度器按序执行。若一个工具名都没匹配上则抛出AGENT_TOOL_NOT_FOUND。4.3 工作流智能体场景路由阶段直接落 WORKFLOW在 WorkflowEventHandler.java 中routeNewTask/routeResume均以TaskType.WORKFLOW.getValue()构造任务并置为SUBMITTED状态后交给 TaskManager例如Task task new Task(session.getSessionId(), randomWorkflowTaskId(), TaskType.WORKFLOW.getValue()); task.setDescription(taskData.targetName()); task.setStatus(TaskStatus.SUBMITTED); requireTaskManager().addTask(task);对应测试 WorkflowControllerTest.java 断言intent.getTask().getTaskType()为TaskType.WORKFLOW。4.4 UNDEFINED 的典型使用默认规划器兜底旧版默认规划器 DefaultPlanner.java 在为每条消息创建默认任务时直接将taskType置为UNDEFINEDTask task new Task(); task.setTaskType(TaskType.UNDEFINED); task.setDescription(desc); task.setStatus(TaskStatus.PENDING);PlannerTest.java 断言该任务类型为TaskType.UNDEFINED。这说明UNDEFINED不仅用于解析失败的回退值也被用作尚未由意图识别结果决定类型的占位值。五、从 taskType 到执行器TaskExecutorRegistry 分发机制任务创建后调度器依据taskType字符串从执行器注册表中找到对应的TaskExecutor。这是 TaskType 在运行期最核心的作用。5.1 注册表按字符串键存储TaskExecutorRegistry.java 内部使用ConcurrentHashMapString, FunctionTaskExecutorDependencies, TaskExecutor以任务类型字符串为键public void addTaskExecutor(String taskType, FunctionTaskExecutorDependencies, TaskExecutor taskExecutorBuilder) { taskExecutorBuilders.put(taskType, taskExecutorBuilder); } public TaskExecutor getTaskExecutor(String taskType, TaskExecutorDependencies dependencies) { FunctionTaskExecutorDependencies, TaskExecutor builder taskExecutorBuilders.get(taskType); if (builder null) { throw ErrorHelper.buildError(StatusCode.AGENT_CONTROLLER_TASK_EXECUTION_ERROR, error_msg, task executor not found for type: taskType); } return builder.apply(dependencies); }注册键就是TaskType.getValue()的字符串值如workflow、plugin、mcp查找不到对应执行器时抛出AGENT_CONTROLLER_TASK_EXECUTION_ERROR提示 task executor not found for type: xxx。5.2 执行时按类型取执行器TaskScheduler.java 的executeTask中Task task tasks.get(0); Loggers.CONTROLLER.info(Executing task {} (type: {}), taskId, task.getTaskType()); // 2. Create TaskExecutor TaskExecutorDependencies dependencies new TaskExecutorDependencies( config, executorAbilityManager, contextEngine, taskManager, eventQueue); TaskExecutor executor taskExecutorRegistry.getTaskExecutor(task.getTaskType(), dependencies);随后调度器将任务状态更新为WORKING通过executor.executeAbility(taskId, session)迭代产出ControllerOutputChunk并按输出类型TASK_COMPLETION/TASK_INTERACTION/TASK_FAILED更新任务状态。5.3 自定义执行器的注册入口Controller提供了链式 API 注册自定义任务执行器Controller.javapublic Controller addTaskExecutor( String taskType, FunctionTaskExecutorDependencies, TaskExecutor taskExecutorBuilder ) { taskScheduler.getTaskExecutorRegistry().addTaskExecutor(taskType, taskExecutorBuilder); return this; }实际案例Deep AgentTask Loop在初始化任务循环运行时时注册了类型为deep_agent_task的自定义执行器DeepAgent.javataskScheduler .getTaskExecutorRegistry() .addTaskExecutor(TaskLoopEventExecutor.DEEP_TASK_TYPE, dependencies - new CoreTaskLoopEventExecutor(dependencies, this, this::invokeInnerRound));其中DEEP_TASK_TYPE deep_agent_taskTaskLoopEventExecutor.java而 TaskLoopEventHandler.java 创建任务时也使用同一字符串常量。测试 TaskLoopEventHandlerTest.java 对此进行了断言。这说明TaskType 只是框架内置的四种标准类型任务系统本身是开放可扩展的——任何自定义任务类型字符串都可以通过addTaskExecutor注册对应执行器并接入调度链路。六、TaskType 在序列化与跨系统交互中的注意点字符串大小写敏感fromValue(Workflow)、fromValue(WORKFLOW)均不匹配返回UNDEFINED。请始终使用getValue()的小写值序列化字段名为task_type在 controller/schema/Task.java 中通过JsonProperty(task_type)绑定与 Python 版数据模型保持一致回退语义UNDEFINED是未知输入的合法回退值不会被当作错误抛出但若一个已提交任务带着UNDEFINED进入调度且未注册对应执行器TaskExecutorRegistry会抛出AGENT_CONTROLLER_TASK_EXECUTION_ERROR跨语言对齐枚举值是 Python 版enums.py的镜像凡涉及与 Python 端、外部系统交换任务数据务必使用相同的字符串值。七、小结与速查你想做的事推荐做法参考构造一个工作流任务new Task(sessionId, taskId, TaskType.WORKFLOW.getValue())WorkflowEventHandler.java解析外部传入的类型字符串TaskType.fromValue(str)无匹配自动得UNDEFINEDTaskType.java判断类型是否未知与TaskType.UNDEFINED比较DefaultPlanner.java注册自定义任务类型执行器controller.addTaskExecutor(type, deps - executor)Controller.java、DeepAgent.java从 LLM 工具调用生成任务类型使用MessageHandlerUtils.determineTaskType/createTasksFromToolCallsMessageHandlerUtils.javaTaskType虽是一个只有四个枚举值的小类但它贯穿了 openJiuwen agent-core-java 控制器从意图识别 → 任务创建 → 类型标注 → 执行器分发 → 调度执行的完整链路并与 Python 版 Core 保持严格对齐。理解它的字符串契约与回退语义是正确使用控制器任务模型、以及扩展自定义任务类型的第一步。赞分享人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习【免费下载链接】agent-core-javaopenJiuwen agent core Java是 openJiuwen Core的 Java版本提供AI Agent开发、运行、调优与演进相关的全套SDK能力。项目地址https://gitcode.com/openJiuwen/agent-core-java点击查看免费下载相关推荐openJiuwen agent-core-java 控制器意图分类枚举 IntentType 全解9 类任务意图、LLM 识别与事件路由机制openJiuwen agent core java 控制器意图分类枚举 IntentType 全解9 类任务意图、LLM 识别与事件路由机制 导读 Inte人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习drawio-desktop 完整上手指南免费打开 Visio VSDX 文件的跨平台桌面工具drawio desktop 完整上手指南免费打开 Visio VSDX 文件的跨平台桌面工具 同事用 Visio 画好的流程图发过来是 .vsdx 格式人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习openJiuwen agent-core-java 控制器Controller机制详解从事件分发、任务调度到意图识别openJiuwen agent core java 控制器Controller机制详解从事件分发、任务调度到意图识别 com.openjiuwen.co人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习上一篇QIE-2511-Cinematic-FlatLog-Control部署指南本地与云端环境配置下一篇Nikto数据库迁移服务专业的Web安全规则转移解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?