资讯动态

LangChain4j用Agent拼工作流

发布时间:2026/10/2 6:22:45 来源:尧图企业网站定制
LangChain4j Agentic用 Agent 与 sequence/parallel 拼工作流多步 LLM 任务常被拆成「写草稿 → 改受众 → 改文风」或「并行问两个专家再合并」。LangChain4j 把这类编排收进独立模块langchain4j-agentic用带Agent的接口描述一步再用sequenceBuilder/parallelBuilder等拼成工作流步骤之间靠AgenticScope共享变量。这里基于官方 Agents 教程与 Get Started只讲非 Spring 的纯 Java 用法。整模块标注为 experimental未来可能变更适合试验与原型上线前请按发布说明回归。这里不绑 Spring Boot只看 Java 侧的 Agent 接口与 deterministic workflow。一、版本、依赖与 experimental 边界Get Started 要求JDK ≥ 17。文档示例版本dev.langchain4j:langchain4j1.20.2dev.langchain4j:langchain4j-open-ai1.20.2dev.langchain4j:langchain4j-bom1.20.2Get Started 页同时提醒bom 版本虽是1.20.2但许多模块的版本仍是1.20.2-beta30这些模块以后可能有 breaking changes。Agents 教程页顶部的提示写明整个langchain4j-agentic模块都应视为 experimental后续版本可能变更。依赖建议可以写成三条团队约定用langchain4j-bom统一管理版本避免各模块手填不一致核心 / OpenAI 按文档写1.20.2langchain4j-agentic经 bom 引入bom 里它跟随 beta 版本号1.20.2-beta30官方文档页把整个模块标为 experimental以 bom / Maven Central 为准。Agents 教程页本身不给依赖坐标Get Started 页只说许多模块是1.20.2-beta30。Maven Central 上langchain4j-agentic目前最新是1.20.2-beta302026-09-28 发布同系列还有 1.20.0-beta30、1.20.1-beta30而langchain4j、langchain4j-open-ai、langchain4j-bom最新是1.20.2。二者版本号不同不要把 agentic 写成稳定的 1.20.2。源码细节随版本变化以所用版本为准。聊天模型可先按文档最小示例跑通与 agentic 无关也能单独用langchain4j-open-ai提供OpenAiChatModel。下面的 Maven 依赖在 JDK 21 下编译通过后文三段 Java 代码都能用它dependencyManagementdependenciesdependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-bom/artifactIdversion1.20.2/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementdependenciesdependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-open-ai/artifactId/dependencydependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-agentic/artifactId/dependency/dependencies最小聊天示例importdev.langchain4j.model.openai.OpenAiChatModel;publicclassChatSmokeTest{publicstaticvoidmain(String[]args){StringapiKeySystem.getenv(OPENAI_API_KEY);OpenAiChatModelmodelOpenAiChatModel.builder().apiKey(apiKey).modelName(gpt-4o-mini).build();Stringanswermodel.chat(Say Hello World);System.out.println(answer);}}这一步先确认 API Key、模型名、依赖坐标没问题再叠加 agentic。把「模型调不通」和「编排 API 用错」混在一次排障里会非常耗时。密钥用环境变量注入不要写进仓库。agentic 与核心库版本线不一致时稳定号 vs beta 号更要把「能编译」和「行为与教程一致」分成两道检查。二、一个 Agent接口 Agent outputKeyAgents 教程里Agent 很像 AI Service接口 单方法再加Agent。可选描述尤其给 supervisor 等「纯智能体」模式看能力、可选名称默认取方法名。与普通 AI Service 的关键差异是outputKey把本次结果写入AgenticScope的共享变量供后续 Agent 读取。outputKey也可以写在Agent注解上与 builder 二选一风格保持团队一致即可。importdev.langchain4j.agentic.Agent;importdev.langchain4j.agentic.AgenticServices;importdev.langchain4j.model.chat.ChatModel;importdev.langchain4j.model.openai.OpenAiChatModel;importdev.langchain4j.service.UserMessage;importdev.langchain4j.service.V;publicclassCreativeWriterDemo{publicinterfaceCreativeWriter{UserMessage( You are a creative writer. Generate a draft of a story no more than 3 sentences long around the given topic. Return only the story and nothing else. The topic is {{topic}}. )Agent(Generates a story based on the given topic)StringgenerateStory(V(topic)Stringtopic);}publicstaticCreativeWriterbuild(ChatModelmodel){returnAgenticServices.agentBuilder(CreativeWriter.class).chatModel(model).outputKey(story).build();}publicstaticvoidmain(String[]args){// 只构建 Agent不调用模型没设置 OPENAI_API_KEY 时用占位值StringapiKeySystem.getenv().getOrDefault(OPENAI_API_KEY,demo);ChatModelmodelOpenAiChatModel.builder().apiKey(apiKey).modelName(gpt-4o-mini).build();CreativeWriterwriterbuild(model);System.out.println(agent built: (writer!null));}}AgenticScope在调用顶层 Agent 时自动创建存放共享变量并记录调用序列。子 Agent 的参数用V(story)这类名字从 Scope 取值若编译时打开-parameters保留参数名教程说明部分场景可省略V。缺必需参数默认会让整个系统失败也可以把某步标成 optional缺参则跳过该步适合「有受众就改受众、没有就跳过」这类软依赖。从工程分层看还可以把 agentic 理解成「提示词工程」与「工作流引擎」之间的薄胶合层它不替代你的领域服务也不替你保证模型输出合法它只保证步骤怎么串、状态怎么传、失败怎么冒泡有统一说法。域校验、幂等、审计日志仍然要写在你自己的代码里这和用不用 LLM 无关。分层上底层仍是「提示词 ChatModel」Agent 多了一层命名输出工作流再多一层谁先谁后、谁读谁写。团队协作时先把 Scope 键表topic/story/audience/style…当契约评审比先纠结用哪种 Builder 更有用。三、sequence把写稿与编辑串起来顺序工作流是最常见的 deterministic 模式CreativeWriter写出story再交给受众编辑、文风编辑后者继续读写同一个story键。教程用sequenceBuilder组装可得到UntypedAgentinvoke(Map)或强类型接口。下面用教程里的CreativeWriter、AudienceEditor、StyleEditor三步演示sequenceBuilder接口名与提示词沿用教程示例仅作教学main只构建工作流不发起模型调用importdev.langchain4j.agentic.Agent;importdev.langchain4j.agentic.AgenticServices;importdev.langchain4j.agentic.UntypedAgent;importdev.langchain4j.model.chat.ChatModel;importdev.langchain4j.model.openai.OpenAiChatModel;importdev.langchain4j.service.UserMessage;importdev.langchain4j.service.V;importjava.util.Map;publicclassNovelSequenceDemo{publicinterfaceCreativeWriter{UserMessage( You are a creative writer. Generate a draft of a story no more than 3 sentences long around the given topic. Return only the story and nothing else. The topic is {{topic}}. )Agent(Generates a story based on the given topic)StringgenerateStory(V(topic)Stringtopic);}publicinterfaceAudienceEditor{UserMessage( You are a professional editor. Analyze and rewrite the following story to better align with the target audience of {{audience}}. Return only the story and nothing else. The story is {{story}}. )Agent(Edits a story to better fit a given audience)StringeditStory(V(story)Stringstory,V(audience)Stringaudience);}publicinterfaceStyleEditor{UserMessage( You are a professional editor. Analyze and rewrite the following story to better fit and be more coherent with the {{style}} style. Return only the story and nothing else. The story is {{story}}. )Agent(Edits a story to better fit a given style)StringeditStory(V(story)Stringstory,V(style)Stringstyle);}publicstaticUntypedAgentbuild(ChatModelmodel){CreativeWriterwriterAgenticServices.agentBuilder(CreativeWriter.class).chatModel(model).outputKey(story).build();AudienceEditoraudienceEditorAgenticServices.agentBuilder(AudienceEditor.class).chatModel(model).outputKey(story).build();StyleEditorstyleEditorAgenticServices.agentBuilder(StyleEditor.class).chatModel(model).outputKey(story).build();returnAgenticServices.sequenceBuilder().subAgents(writer,audienceEditor,styleEditor).outputKey(story).build();}// 会发起真实模型请求下面的 main 不调用它publicstaticStringrun(ChatModelmodel){MapString,ObjectinputMap.of(topic,dragons and wizards,audience,young adults,style,fantasy);return(String)build(model).invoke(input);}publicstaticvoidmain(String[]args){// 只构建工作流不调用模型没设置 OPENAI_API_KEY 时用占位值StringapiKeySystem.getenv().getOrDefault(OPENAI_API_KEY,demo);ChatModelmodelOpenAiChatModel.builder().apiKey(apiKey).modelName(gpt-4o-mini).build();UntypedAgentnovelCreatorbuild(model);System.out.println(workflow built: (novelCreator!null));}}输入 Map 会拷进AgenticScope最终返回值取自outputKey这里是story。也可以sequenceBuilder(NovelCreator.class)用强类型方法替代invoke(Map)调用处更干净教程里的接口形如String createNovel(V(topic) String topic, V(audience) String audience, V(style) String style)。单测时对 Untyped 路径喂 Map、对强类型路径喂参数两种都可以关键是断言 Scope 键是否按预期被覆盖。编辑类 Agent 多次写同一story键时尤其如此。需要「写完后按分数反复改」时教程提供loopBuilder()maxIterations默认几乎没有上限建议显式设置、exitCondition读 Scope 里的score等状态还可testExitAtLoopEnd(true)控制是每步都测退出还是整圈末再测。loop 本身又可当作一个 subAgent 塞进外层 sequence官方 StyledWriter 就是「生成 style review loop」。这比一上来上 supervisor 更可控退出条件在你手里别完全交给模型临场发挥。四、parallel 与其它模式怎么选并行适合彼此独立的专家教程里的FoodExpert/MovieExpert同时根据mood出列表再用parallelBuilder的output(...)把meals与movies拼成计划可选executor(Executors.newFixedThreadPool(2))不设则用内部默认线程池文档称 cached thread pool具体实现以所用版本为准。合并逻辑写在output回调里从 ScopereadState取两边结果。output(...)在任何 workflow 里都能用parallel 里尤其常用因为并行分支的结果最终要在这里汇合executor(...)则只有 parallel和 parallelMapper的 builder 才有sequenceBuilder没有。按官方能力做选型即可不必一次用满Builder用途文档描述sequenceBuilder固定顺序输出接力loopBuilder迭代直到 exitCondition 或达 maxIterationsparallelBuilder并行子 Agent再自定义合并conditionalBuilder按 Scope 状态激活不同专家supervisorBuilderLLM 规划下一步更「纯 agent」conditionalBuilder适合先分类再路由教程里的 legal/medical/technical 专家教程该处没写分类 Agent 的outputKey(category)照抄时要自己补上否则条件读不到分类。我用桩模型本地实测不设这个 key 时整条路由返回 nullsupervisorBuilder适合步骤顺序事先说不清、要由模型选子 Agent 的场景并可配置响应策略SupervisorResponseStrategyLAST为默认另有SUMMARY、SCORED等。对多数后台批处理与内容流水线先 sequence / parallel 就够可观测性与回放也更简单。实践上建议「模式渐进」先用 sequence 固定三到五步某一步需要打磨质量再包成 loop出现明显独立扇出再拆 parallel分类路由才上 conditional只有编排顺序本身也要模型决定时才考虑 supervisor。这样回滚也容易出问题知道撤的是哪一层 Builder不用动整棵「智能体大杂烩」。教程后半还有监听器、AgentMonitor、声明式注解 API 等属于增强项等主路径稳定再加避免实验模块上同时叠太多抽象。错误处理方面教程提供errorHandler函数接收ErrorContext返回ErrorRecoveryResult。throwException()把异常传播出去默认retry()重试该 Agentresult(Object)直接给一个兜底结果。重试没有内置的次数或退避配置要在 handler 里自己计数避免死循环。涉及工具副作用时还有 compensation 能力builder 上设compensateOnError(true)配合工具方法上的CompensateFor失败时按逆序补偿。引入 experimental 模块时建议单独做失败演练别默认打开所有开关。异步 Agentasync(true)与 streaming 也在文档中有专节并行语义、以及只有最后一个被调用的 streaming Agent 才能把流推到整个系统外其余的表现得像 async Agent等约束用之前先读对应小节勿凭直觉套线程模型。五、落地时注意什么先承认 experimental接口、Builder、默认行为都可能变锁定 bom升级读 changelog原型与生产依赖策略分开。Scope 键名即契约outputKey/V拼错会在运行期以缺参等形式爆掉维护「键 → 含义 → 谁写谁读」比复制粘贴示例更重要。与 Spring 集成分开选型这里不绑 Spring Boot若要用 Boot 自动配置走官方 Spring 集成文档不要和 agentic 教程混成「必须上 Boot」。模型与密钥OpenAiChatModel示例用环境变量OPENAI_API_KEY换模型只换ChatModel实现Agent 接口可复用。别指望它保证指标Agentic 解决的是编排与共享状态并不保证准确率或时延评测集与人工抽检仍要自己建。和手写编排比的是清晰度若三步流水线用普通方法调用已经够清楚不必为了「上 Agent」而上当步骤增多、要插入 loop/conditional、或希望统一监听调用树时模块价值才明显。别照搬教学示例教程中的 CreativeWriter / FoodExpert 等只是教学示例不要把「写小说」「规划晚餐」直接当成业务模板换成你的领域接口名、提示词与键名即可Builder 用法不变。评测时用固定温度与固定用例才能看出是编排改坏了还是模型漂移。六、最小可行工作流怎么验收在实验模块上做验收别盯准确率百分比先确认编排契约稳定键契约给定输入 Map跑完后story或你的业务键是否按预期被最后一步写回中间键是否被误覆盖。失败路径故意少传一个必填键是否按预期失败若配置了errorHandler/ optional行为是否与文档一致。并行汇合parallel 场景下两边列表长度不一致时你的output合并逻辑是否安全教程示例用循环下限保护。升级策略bom 或 agentic 坐标变动时先跑同一组契约测试再扩功能。把这四条写成自动化比贴一张「我们上了 Agentic」的架构幻灯片有用。experimental 模块尤其如此。API 可能变但你的业务键与验收用例可以先稳下来。等模块声明更稳定再考虑 supervisor、声明式注解、监控报表等增强面。若团队同时在看其它语言的 agent 框架比较时可以看这几点有没有显式共享状态、顺序/并行是否一等公民、是否标明稳定级别。LangChain4j 这条线的特点是 Java 接口 Scope 键 Builder 组合它不是 Spring 专属也不要求你先上 Boot。选它该看编排模型合不合适别因为「Java 生态必须有一个 agent 二字」。小结把每步收成Agent用AgenticScope传字段用sequenceBuilder/parallelBuilder表达确定流程这就是langchain4j-agentic当前教程的主路径。模块还在实验线适合先在非关键路径验证工作流是否比手写编排清晰再决定是否扩大范围。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑