先从基础 Agent 开始。本系列以招聘为例,逐步实现简历生成、筛选与优化。示例改编自 LangChain4j 官方示例,并参考 Anthropic 的工作流与 Agent 模式说明。
如果还不熟悉模型接入和工具调用,可以先阅读 LangChain4j 基础系列。
先准备招聘示例的输入材料:
- 假设一家公司正在招聘,希望通过 Agent 完成简历生成、筛选与优化。
- 候选人的个人资料保存在
user_life_stody.txt中。
John Doe 现居比利时安特卫普(Rue des Carmes 12, 2000 Antwerp),联系方式为 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活跃。
- 2020 年完成夜间 Java 集训营(2019–2020)后从机械工程领域转型至软件开发。
- 拥有 4 年软件开发经验,其中最近 2 年专注于 Java 后端开发(Spring Boot、PostgreSQL、Kafka 基础)。
- 开发了一款内部报价工具,将报价周转时间缩短约 35%。
- 领导 3 人专项小组,将遗留 SOAP 服务迁移至 REST 架构。
- 熟悉 Docker 与 CI 流水线(GitHub Actions)。
- 具备 React 使用经验,曾开发内部管理面板(非核心优势)。
- 重视代码整洁与可维护性,乐于指导实习生。
- 偏好产品开发而非外包项目;不喜冗长会议,注重交付实际价值。
- 语言:荷兰语(母语)、英语(C1)、法语(B1)。
- 教育背景:机械工程学士(2016 年),Java 集训营(2019–2020)。
- 个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。
一、定义Agent接口
public interface CvGenerator {
@UserMessage("""
以下是我的个人生活和职业经历信息,
请将其整理成一份清晰、完整的简历。
注意事项:
1. 不要编造任何事实
2. 不要遗漏任何技能或经历
3. 这份简历后续会进一步优化,请确保内容完整
我的个人经历:{{lifeStory}}
""")
@Agent("基于用户提供的信息生成规范的简历")
String generateCv(@V("lifeStory") String userInfo);
}
这里使用 AIService 接口形式,并通过 @Agent 标记智能体。需要添加以下依赖:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic</artifactId>
<version>1.10.0-beta18</version>
</dependency>
二、最基础的Agent示例
/**
该示例演示了如何实现一个基础Agent(改编自<a href="https://github.com/langchain4j/langchain4j-examples">langchain4j官网示例</a>)
注意:Agent只有与其他Agent结合使用时才更有用,后续步骤中将展示这一点。
如果只有一个Agent,使用 AiService 会是更好的选择。
这个基础Agent将用户的个人简介转换成一个简洁而完整的简历。
注意:运行此程序可能需要一些时间,因为输出的简历会相当长,LLM也需要一些时间处理。
@author 菩提树下的杨过(yjmyzz.cnblogs.com)
@see <a href="https://github.com/langchain4j/langchain4j-examples/blob/main/agentic-tutorial/src/main/java/_1_basic_agent/_1a_Basic_Agent_Example.java">_1a_Basic_Agent_Example</a>
*/
@SpringBootApplication
public class _1a_Basic_Agent_Example {
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args);
ChatModel model = context.getBean("ollamaChatModel", ChatModel.class);
CvGenerator cvGenerator = AgenticServices
.agentBuilder(CvGenerator.class)
.chatModel(model)
//定义输出对象的键
.outputKey("masterCv")
.build();
// 加载个人介绍
String lifeStory = StringLoader.loadFromResource("/documents/user_life_story.txt");
// 让 agent 生成简历
String cv = cvGenerator.generateCv(lifeStory);
// 打印简历
System.out.println("=== 简历 ===");
System.out.println(cv);
}
}
时序图(简化版,原文标注为 AI 生成)

原文配图:基础 Agent 与结构化输出:简化时序图。
时序图(详细版,原文标注为 AI 生成)

原文配图:基础 Agent 与结构化输出:详细时序图。
运行结果:
展开原文日志或请求/响应(未复测)
2026-01-11T19:36:17.012+08:00 INFO 16080 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
- method: POST
- url: http://localhost:11434/api/chat
- headers: [Content-Type: application/json]
- body: {
"model" : "deepseek-v3.1:671b-cloud",
"messages" : [ {
"role" : "user",
"content" : "以下是我的个人生活和职业经历信息,\n请将其整理成一份清晰、完整的简历。\n\n注意事项:\n1. 不要编造任何事实\n2. 不要遗漏任何技能或经历\n3. 这份简历后续会进一步优化,请确保内容完整\n\n我的个人经历:John Doe 现居比利时安特卫普(Rue des Carmes 12, 2000 Antwerp),联系方式为 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活跃。\r\n\r\n- 2020 年完成夜间 Java 集训营(2019–2020)后从机械工程领域转型至软件开发。\r\n- 拥有 4 年软件开发经验,其中最近 2 年专注于 Java 后端开发(Spring Boot、PostgreSQL、Kafka 基础)。\r\n- 开发了一款内部报价工具,将报价周转时间缩短约 35%。\r\n- 领导 3 人专项小组,将遗留 SOAP 服务迁移至 REST 架构。\r\n- 熟悉 Docker 与 CI 流水线(GitHub Actions)。\r\n- 具备 React 使用经验,曾开发内部管理面板(非核心优势)。\r\n- 重视代码整洁与可维护性,乐于指导实习生。\r\n- 偏好产品开发而非外包项目;不喜冗长会议,注重交付实际价值。\r\n- 语言:荷兰语(母语)、英语(C1)、法语(B1)。\r\n- 教育背景:机械工程学士(2016 年),Java 集训营(2019–2020)。\r\n- 个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。\n"
} ],
"options" : {
"stop" : [ ]
},
"stream" : false,
"tools" : [ ]
}
2026-01-11T19:36:24.079+08:00 INFO 16080 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
- status code: 200
- headers: [content-type: application/json; charset=utf-8], [date: Sun, 11 Jan 2026 11:36:24 GMT], [transfer-encoding: chunked]
- body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-11T11:36:23.745953889Z","message":{"role":"assistant","content":"# John Doe - 简历\n\n**地址** \nRue des Carmes 12, 2000 Antwerp, Belgium \n**邮箱** \njohn.doe.dev@protonmail.com \n**电话** \n+32 495 67 89 23 \n**在线资料** \nLinkedIn | GitHub \n\n---\n\n## 职业摘要\n拥有4年软件开发经验的Java后端开发者,其中最近2年专注于Java生态系统(Spring Boot、PostgreSQL、Kafka)。具备从机械工程成功转型至软件开发的背景,擅长构建可维护的代码、优化流程,并乐于指导团队成员。注重产品价值交付,偏好产品导向的开发环境。\n\n---\n\n## 技能专长\n- **后端开发**: Java, Spring Boot, REST API, PostgreSQL, Kafka (基础)\n- **工具与流程**: Docker, CI/CD (GitHub Actions), Git\n- **前端经验**: React (内部工具开发), Vue.js (个人项目)\n- **软技能**: 代码整洁与可维护性、团队协作、指导实习生、问题解决\n- **语言**: 荷兰语 (母语), 英语 (C1), 法语 (B1)\n\n---\n\n## 职业经历\n**软件开发工程师** \n*2020年至今* \n- 开发内部报价工具,将报价周转时间缩短约35%。\n- 领导3人专项小组,完成遗留SOAP服务至REST架构的迁移。\n- 使用Spring Boot和PostgreSQL构建后端服务,并集成Kafka进行事件驱动通信。\n- 通过Docker容器化应用,利用GitHub Actions设置CI流水线以提高部署效率。\n- 曾开发React内部管理面板以支持业务运营(非核心职责)。\n- 积极指导实习生,提倡代码可读性与系统可维护性。\n\n---\n\n## 教育背景\n- **Java 夜间集训营** \n *2019–2020* \n 集中学习Java编程、数据结构、Web开发与团队项目协作。\n\n- **机械工程学士** \n *2016年毕业* \n 具备工程问题分析与系统化解决能力。\n\n---\n\n## 个人项目\n- **预算管理应用** \n 使用Spring Boot与Vue.js构建的个人预算跟踪工具,支持支出分类与可视化报表。\n \n- **家庭物联网系统** \n 基于ESP32微控制器与MQTT协议搭建的自动化家居监控系统,实现传感器数据采集与远程控制。\n\n---\n\n## 备注\n- 偏好产品导向的开发环境,注重交付实际价值而非冗长会议。\n- 对技术充满热情,持续通过个人项目与实践深化全栈技能。\n\n---\n*简历内容基于提供的经历信息整理,未添加任何编造内容,可随时进一步优化格式与重点。*"},"done":true,"done_reason":"stop","total_duration":6020764924,"prompt_eval_count":387,"eval_count":566}
=== 简历 ===
# John Doe - 简历
**地址**
Rue des Carmes 12, 2000 Antwerp, Belgium
**邮箱**
john.doe.dev@protonmail.com
**电话**
+32 495 67 89 23
**在线资料**
LinkedIn | GitHub
---
## 职业摘要
拥有4年软件开发经验的Java后端开发者,其中最近2年专注于Java生态系统(Spring Boot、PostgreSQL、Kafka)。具备从机械工程成功转型至软件开发的背景,擅长构建可维护的代码、优化流程,并乐于指导团队成员。注重产品价值交付,偏好产品导向的开发环境。
---
## 技能专长
- **后端开发**: Java, Spring Boot, REST API, PostgreSQL, Kafka (基础)
- **工具与流程**: Docker, CI/CD (GitHub Actions), Git
- **前端经验**: React (内部工具开发), Vue.js (个人项目)
- **软技能**: 代码整洁与可维护性、团队协作、指导实习生、问题解决
- **语言**: 荷兰语 (母语), 英语 (C1), 法语 (B1)
---
## 职业经历
**软件开发工程师**
*2020年至今*
- 开发内部报价工具,将报价周转时间缩短约35%。
- 领导3人专项小组,完成遗留SOAP服务至REST架构的迁移。
- 使用Spring Boot和PostgreSQL构建后端服务,并集成Kafka进行事件驱动通信。
- 通过Docker容器化应用,利用GitHub Actions设置CI流水线以提高部署效率。
- 曾开发React内部管理面板以支持业务运营(非核心职责)。
- 积极指导实习生,提倡代码可读性与系统可维护性。
---
## 教育背景
- **Java 夜间集训营**
*2019–2020*
集中学习Java编程、数据结构、Web开发与团队项目协作。
- **机械工程学士**
*2016年毕业*
具备工程问题分析与系统化解决能力。
---
## 个人项目
- **预算管理应用**
使用Spring Boot与Vue.js构建的个人预算跟踪工具,支持支出分类与可视化报表。
- **家庭物联网系统**
基于ESP32微控制器与MQTT协议搭建的自动化家居监控系统,实现传感器数据采集与远程控制。
---
## 备注
- 偏好产品导向的开发环境,注重交付实际价值而非冗长会议。
- 对技术充满热情,持续通过个人项目与实践深化全栈技能。
---
*简历内容基于提供的经历信息整理,未添加任何编造内容,可随时进一步优化格式与重点。*
24-82行,就是基于“个人资料”生成的简历。
三、结构化输出
如果希望生成的简历,以结构化输出(即:直接输出POJO对象实例),可以稍微改进:
3.1 定义简历POJO类Cv
/**
* 简历类
*/
public class Cv {
@Description("候选人的专业技能,逗号串接")
private String skills;
@Description("候选人的专业经历")
private String professionalExperience;
@Description("候选人的教育背景")
private String studies;
@Override
public String toString() {
return "CV:\n" +
"专业技能 = \"" + skills + "\"\n" +
"专业经历 = \"" + professionalExperience + "\"\n" +
"教育背景 = \"" + studies + "\"\n";
}
}
3.2 定义结构化Agent接口
public interface CvGeneratorStructuredOutput {
@UserMessage("""
以下是我的个人生活和职业经历信息,
请将其整理成一份清晰、完整的简历。
注意事项:
1. 不要编造任何事实
2. 不要遗漏任何技能或经历
3. 这份简历后续会进一步优化,请确保内容完整
我的个人经历:{{lifeStory}}
""")
@Agent("基于用户提供的信息生成规范的简历")
Cv generateCv(@V("lifeStory") String userInfo);
}
3.3 结构化输出Agent
public class _1b_Basic_Agent_Example_Structured {
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args);
ChatModel model = context.getBean("ollamaChatModel", ChatModel.class);
CvGeneratorStructuredOutput cvGenerator = AgenticServices
.agentBuilder(CvGeneratorStructuredOutput.class)
.chatModel(model)
.build();
// 加载个人介绍
String lifeStory = StringLoader.loadFromResource("/documents/user_life_story.txt");
// 让 agent 生成简历
Cv cvStructured = cvGenerator.generateCv(lifeStory);
// 打印简历
System.out.println("=== 简历 ===");
System.out.println(cvStructured);
}
}
输出:
展开原文日志或请求/响应(未复测)
2026-01-11T19:58:32.855+08:00 INFO 16512 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
- method: POST
- url: http://localhost:11434/api/chat
- headers: [Content-Type: application/json]
- body: {
"model" : "deepseek-v3.1:671b-cloud",
"messages" : [ {
"role" : "user",
"content" : "以下是我的个人生活和职业经历信息,\n请将其整理成一份清晰、完整的简历。\n\n注意事项:\n1. 不要编造任何事实\n2. 不要遗漏任何技能或经历\n3. 这份简历后续会进一步优化,请确保内容完整\n\n我的个人经历:John Doe 现居比利时安特卫普(Rue des Carmes 12, 2000 Antwerp),联系方式为 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活跃。\r\n\r\n- 2020 年完成夜间 Java 集训营(2019–2020)后从机械工程领域转型至软件开发。\r\n- 拥有 4 年软件开发经验,其中最近 2 年专注于 Java 后端开发(Spring Boot、PostgreSQL、Kafka 基础)。\r\n- 开发了一款内部报价工具,将报价周转时间缩短约 35%。\r\n- 领导 3 人专项小组,将遗留 SOAP 服务迁移至 REST 架构。\r\n- 熟悉 Docker 与 CI 流水线(GitHub Actions)。\r\n- 具备 React 使用经验,曾开发内部管理面板(非核心优势)。\r\n- 重视代码整洁与可维护性,乐于指导实习生。\r\n- 偏好产品开发而非外包项目;不喜冗长会议,注重交付实际价值。\r\n- 语言:荷兰语(母语)、英语(C1)、法语(B1)。\r\n- 教育背景:机械工程学士(2016 年),Java 集训营(2019–2020)。\r\n- 个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。\n\nYou must answer strictly in the following JSON format: {\n\"skills\": (候选人的专业技能,逗号串接; type: string),\n\"professionalExperience\": (候选人的专业经历; type: string),\n\"studies\": (候选人的教育背景; type: string)\n}"
} ],
"options" : {
"stop" : [ ]
},
"stream" : false,
"tools" : [ ]
}
2026-01-11T19:58:36.010+08:00 INFO 16512 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
- status code: 200
- headers: [content-type: application/json; charset=utf-8], [date: Sun, 11 Jan 2026 11:58:35 GMT], [transfer-encoding: chunked]
- body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-11T11:58:35.375858113Z","message":{"role":"assistant","content":"{\n\"skills\": \"Java, Spring Boot, PostgreSQL, Kafka, REST API, Docker, CI/CD (GitHub Actions), React, 代码整洁与可维护性, 指导与协作, 荷兰语(母语), 英语(C1), 法语(B1)\",\n\"professionalExperience\": \"拥有4年软件开发经验,其中最近2年专注于Java后端开发。开发了一款内部报价工具,将报价周转时间缩短约35%。领导一个3人专项小组,成功将遗留SOAP服务迁移至REST架构。具备Docker与CI流水线(GitHub Actions)实践经验。有React使用经验,曾开发内部管理面板。重视代码质量,乐于指导实习生。偏好产品开发,注重交付实际价值。个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。\",\n\"studies\": \"机械工程学士(2016年毕业),Java集训营(2019-2020年)\"\n}"},"done":true,"done_reason":"stop","total_duration":1828432886,"prompt_eval_count":444,"eval_count":212}
=== 简历 ===
CV:
专业技能 = "Java, Spring Boot, PostgreSQL, Kafka, REST API, Docker, CI/CD (GitHub Actions), React, 代码整洁与可维护性, 指导与协作, 荷兰语(母语), 英语(C1), 法语(B1)"
专业经历 = "拥有4年软件开发经验,其中最近2年专注于Java后端开发。开发了一款内部报价工具,将报价周转时间缩短约35%。领导一个3人专项小组,成功将遗留SOAP服务迁移至REST架构。具备Docker与CI流水线(GitHub Actions)实践经验。有React使用经验,曾开发内部管理面板。重视代码质量,乐于指导实习生。偏好产品开发,注重交付实际价值。个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。"
教育背景 = "机械工程学士(2016年毕业),Java集训营(2019-2020年)"
24-28行输出,即为Cv实例的toString结果。
小结
本讲用 AgenticServices 和 @Agent 创建基础 Agent。单个 Agent 的例子尚不能充分体现编排的作用,下一讲会把多个 Agent 串成工作流。