书接上回,简历评估完后,根据评估结果,如果合格,公司就该通知面试,否则回邮件拒绝。也就是今天要演示的“条件工作流”。下面定义这2个分支对应的Agent:
一、定义不同分支的Agent
1.1 EmailAssistant (发邮件拒绝候选人Agent)
1 public interface EmailAssistant {
2
3 @Agent("向未通过筛选的候选人发送拒绝邮件,返回已发送邮件的ID,若无法发送则返回0")
4 @SystemMessage("""
5 您需要向未通过第一轮评审的求职候选人发送一封友好的邮件。
6 同时,您需要将申请状态更新为“已拒绝”。
7 您应返回已发送邮件的ID。
8 """)
9 @UserMessage("""
10 被拒候选人:{{candidateContact}}
11
12 申请职位:{{jobDescription}}
13 """)
14 int send(@V("candidateContact") String candidateContact, @V("jobDescription") String jobDescription);
15 }发送邮件时,需要候选人的联系信息,运行时我们用 candidate_contact.txt 做为输入:
1 候选人联系卡片:
2 姓名:John Doe
3 地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)
4 邮箱:john.doe.dev@protonmail.com
5 电话:+32 495 67 89 231.2 InterviewOrganizer (组织面试Agent)
1 public interface InterviewOrganizer {
2
3 @Agent("为申请人安排现场面试")
4 @SystemMessage("""
5 您通过向所有相关员工发送日历邀请来安排现场会议,
6 时间定在从当前日期起一周后的上午,时长为3小时。
7 这是相关的职位空缺:{{jobDescription}}
8 您还需通过祝贺邮件邀请候选人,告知面试详情,
9 以及他/她来现场前需要注意的事项。
10 最后,您需要将申请状态更新为“已邀请现场面试”。
11 """)
12 @UserMessage("""
13 为此候选人安排现场面试会议(需遵守外部访客政策):{{candidateContact}}
14 """)
15 String organize(@V("candidateContact") String candidateContact, @V("jobDescription") String jobDescription);
16 }二、(可选)定义工具
不管是拒绝还是安排面试,处理过程中都有一些业务逻辑,比如:
拒绝流程:要先调用一些业务工具,发送拒绝邮件,更新简历申请状态
安排面试流程:要先调用一些业务工具,获取当前日期(LLM的知识截止于厂商的发布日期,不识别今天)、获取面试相关的公司员工列表(比如:面试官)、在公司议程表上发起面试日程、发送面试通知邮件、更新简历申请状态
为此,我们需要定义这一系列工具(注:工具的实现,本例都用mock实现,仅为演示效果)
2.1 OrganizingTools
1 public class OrganizingTools {
2
3 @Tool
4 public Date getCurrentDate(){
5 return new Date();
6 }
7
8 @Tool("根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名")
9 public List<String> getInvolvedEmployeesForInterview(@P("职位描述ID") String jobDescriptionId){
10 // 演示用虚拟实现
11 return new ArrayList<>(List.of(
12 "Anna Bolena: hiring.manager@company.com",
13 "Chris Durue: near.colleague@company.com",
14 "Esther Finnigan: vp@company.com"));
15 }
16
17 @Tool("根据电子邮件地址为员工创建日程条目")
18 public void createCalendarEntry(@P("员工电子邮件地址列表") List<String> emailAddress, @P("会议主题") String topic, @P("开始日期和时间,格式为yyyy-mm-dd hh:mm") String start, @P("结束日期和时间,格式为yyyy-mm-dd hh:mm") String end){
19 // 演示用虚拟实现
20 System.out.println("*** 已创建日程条目 ***");
21 System.out.println("主题:" + topic);
22 System.out.println("开始时间:" + start);
23 System.out.println("结束时间:" + end);
24 }
25
26 @Tool
27 public int sendEmail(@P("收件人电子邮件地址列表") List<String> to, @P("抄送电子邮件地址列表") List<String> cc, @P("邮件主题") String subject, @P("正文") String body){
28 // 演示用虚拟实现
29 System.out.println("*** 已发送邮件 ***");
30 System.out.println("收件人:" + to);
31 System.out.println("抄送:" + cc);
32 System.out.println("主题:" + subject);
33 System.out.println("正文:" + body);
34 return 1234; // 虚拟邮件ID
35 }
36
37 @Tool
38 public void updateApplicationStatus(@P("职位描述ID") String jobDescriptionId, @P("候选人(名,姓)") String candidateName, @P("新的申请状态") String newStatus){
39 // 演示用虚拟实现
40 System.out.println("*** 已更新申请状态 ***");
41 System.out.println("职位描述ID:" + jobDescriptionId);
42 System.out.println("候选人姓名:" + candidateName);
43 System.out.println("新状态:" + newStatus);
44 }
45 }2.2 RAG工具
通常每个公司都有一些自己的访客制度,比如:车应该停在哪,衣冠必须端正,来面试时必须前台登记等等。这些LLM显然不知道,需要借助RAG工具
1 @Component("ragProvider")
2 public class RagProvider {
3
4 @Autowired
5 @Qualifier("ollamaEmbeddingModel")
6 OllamaEmbeddingModel ollamaEmbeddingModel;
7
8 public ContentRetriever loadHouseRulesRetriever() {
9 Document doc = loadDocument(toPath("documents/house_rules.txt"));
10 InMemoryEmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
11
12 EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
13 .documentSplitter(DocumentSplitters.recursive(200, 10))
14 .embeddingModel(ollamaEmbeddingModel)
15 .embeddingStore(store)
16 .build();
17
18 ingestor.ingest(List.of(doc));
19
20 return EmbeddingStoreContentRetriever.builder()
21 .embeddingStore(store)
22 .embeddingModel(ollamaEmbeddingModel)
23 .maxResults(2)
24 .minScore(0.8)
25 .build();
26 }
27
28 public static Path toPath(String relativePath) {
29 try {
30 URL fileUrl = Utils.class.getClassLoader().getResource(relativePath);
31 return Paths.get(fileUrl.toURI());
32 } catch (URISyntaxException e) {
33 throw new RuntimeException(e);
34 }
35 }
36 }house_rules.txt内容如下:
1 1.仅允许在停车场后方指定户外区域吸烟。
2 2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。
3 3.员工须至少提前24小时通过内部日历预订会议室。
4 4.自行车必须停放在主楼外侧的专用自行车停放区。
5 5.所有外部访客须凭有效身份证件在前台登记方可进入。
6 6.外部访客均须佩戴临时访客证,并确保证件清晰可见。三、条件工作流示例
1 /**
2 * 此示例演示了条件式智能体工作流。
3 * 基于评分和候选人资料,我们将执行以下操作之一:
4 * - 调用一个智能体,为该候选人的现场面试做好一切准备
5 * - 调用一个智能体,发送一封友好的邮件,告知我们不会推进该候选人的申请
6 * by 菩提树下的杨过(yjmyzz.cnblogs.com)
7 */
8 @SpringBootApplication
9 public class _5a_Conditional_Workflow_Example {
10
11 public static void main(String[] args) throws IOException {
12 ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args);
13 ChatModel model = context.getBean("ollamaChatModel", ChatModel.class);
14 RagProvider ragProvider = context.getBean("ragProvider", RagProvider.class);
15
16 // 2. 在此包中定义两个子智能体:
17 // - EmailAssistant.java
18 // - InterviewOrganizer.java
19
20 // 3. 使用AgenticServices创建所有智能体
21 EmailAssistant emailAssistant = AgenticServices.agentBuilder(EmailAssistant.class)
22 .chatModel(model)
23 .tools(new OrganizingTools()) // 该智能体可以使用那里定义的所有工具
24 .build();
25 InterviewOrganizer interviewOrganizer = AgenticServices.agentBuilder(InterviewOrganizer.class)
26 .chatModel(model)
27 .tools(new OrganizingTools())
28 .contentRetriever(ragProvider.loadHouseRulesRetriever()) // 这是如何为智能体添加RAG的方式
29 .build();
30
31 // 4. 构建条件式工作流
32 UntypedAgent candidateResponder = AgenticServices // 使用UntypedAgent,除非您定义了合成的智能体,请参见_2_Sequential_Agent_Example
33 .conditionalBuilder()
34 .subAgents(agenticScope -> ((CvReview) agenticScope.readState("cvReview")).score >= 0.8, interviewOrganizer)
35 .subAgents(agenticScope -> ((CvReview) agenticScope.readState("cvReview")).score < 0.8, emailAssistant)
36 .build();
37 // 重要提示:当定义了多个条件时,它们会按顺序执行。
38 // 如果您想在这里并行执行,请使用异步智能体,如_5b_Conditional_Workflow_Example_Async中所示
39
40 // 5. 从resources/documents/中的文本文件加载参数
41 String candidateCv = StringLoader.loadFromResource("/documents/tailored_cv.txt");
42 String candidateContact = StringLoader.loadFromResource("/documents/candidate_contact.txt");
43 String jobDescription = StringLoader.loadFromResource("/documents/job_description_backend.txt");
44 CvReview cvReviewFail = new CvReview(0.6, "简历不错,但缺少一些与后端职位相关的技术细节。");
45 CvReview cvReviewPass = new CvReview(0.9, "简历非常出色,符合后端职位的所有要求。");
46
47 // 5. 因为我们使用了无类型智能体,所以需要传递所有输入参数的映射
48 Map<String, Object> arguments = Map.of(
49 "candidateCv", candidateCv,
50 "candidateContact", candidateContact,
51 "jobDescription", jobDescription,
52 "cvReview", cvReviewPass // 更改为cvReviewFail以查看另一个分支
53 );
54
55 // 5. 调用条件式智能体,根据评审结果对候选人做出回应
56 candidateResponder.invoke(arguments);
57
58 }
59 }注:注意52行,这里我们输入的cvReview为0.9分的实例,即评估合格,可以安排面试。有兴趣的朋友们,可以换成cvReviewFail实例,观察下另1个分支的结果。
时序图(简化版)-AI生成

时序图(详细版)-AI生成

运行结果:
1 2026-01-17T16:53:37.524+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
2 - method: POST
3 - url: http://localhost:11434/api/embed
4 - headers: [Content-Type: application/json]
5 - body: {
6 "model" : "nomic-embed-text:latest",
7 "input" : [ "1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。" ]
8 }
9
10 2026-01-17T16:53:42.826+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
11 - status code: 200
12 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:53:42 GMT], [transfer-encoding: chunked]
13 - body: {"model":"nomic-embed-text:latest","embeddings":[[0.028599557,0.057497256,...-0.054139506]],"total_duration":5262584300,"load_duration":5247416900,"prompt_eval_count":161}
14
15 2026-01-17T16:53:42.871+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
16 - method: POST
17 - url: http://localhost:11434/api/embed
18 - headers: [Content-Type: application/json]
19 - body: {
20 "model" : "nomic-embed-text:latest",
21 "input" : [ "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n" ]
22 }
23
24 2026-01-17T16:53:42.895+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
25 - status code: 200
26 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:53:42 GMT], [transfer-encoding: chunked]
27 - body: {"model":"nomic-embed-text:latest","embeddings":[[0.018723998,0.067336,...-0.042845238]],"total_duration":22005300,"load_duration":12774100,"prompt_eval_count":88}
28
29 2026-01-17T16:53:42.939+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
30 - method: POST
31 - url: http://localhost:11434/api/chat
32 - headers: [Content-Type: application/json]
33 - body: {
34 "model" : "deepseek-v3.1:671b-cloud",
35 "messages" : [ {
36 "role" : "system",
37 "content" : "您通过向所有相关员工发送日历邀请来安排现场会议,\n时间定在从当前日期起一周后的上午,时长为3小时。\n这是相关的职位空缺:职位描述 ID: 123A\r\n后端工程师(金融科技,安特卫普)\r\n------------------------------------------------------------\r\n我们正在招聘一位**后端工程师**,协助我们构建并完善支付与对账服务。您将主要使用 **Java (Spring Boot)**,并与产品及运营团队紧密合作,确保金融交易系统的可靠性和可扩展性。\r\n\r\n**职责:**\r\n* 设计、实现并维护能够处理大规模支付与对账业务的后端服务。\r\n* 在云原生环境中使用 **PostgreSQL**、**Kafka**、**Docker** 和 **Kubernetes**。\r\n* 专注于构建可靠、幂等的系统,并具备强大的可观测性。\r\n* 支持将遗留服务迁移至现代的 REST API。\r\n\r\n**要求:**\r\n* 具备 Java 和 Spring Boot 后端开发的职业经验。\r\n* 深入理解关系型数据库和事件驱动架构。\r\n* 熟悉容器化技术和部署流程。\r\n* 有金融或定价系统相关经验者优先。\r\n* 要求英语流利,会荷兰语者更佳。\n您还需通过祝贺邮件邀请候选人,告知面试详情,\n以及他/她来现场前需要注意的事项。\n最后,您需要将申请状态更新为“已邀请现场面试”。\n"
38 }, {
39 "role" : "user",
40 "content" : "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n\n\nAnswer using the following information:\n1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。"
41 } ],
42 "options" : {
43 "stop" : [ ]
44 },
45 "stream" : false,
46 "tools" : [ {
47 "type" : "function",
48 "function" : {
49 "name" : "getInvolvedEmployeesForInterview",
50 "description" : "根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名",
51 "parameters" : {
52 ...
53 }
54 }
55 }, {
56 "type" : "function",
57 "function" : {
58 "name" : "createCalendarEntry",
59 "description" : "根据电子邮件地址为员工创建日程条目",
60 "parameters" : {
61 ...
62 }
63 }
64 }, {
65 "type" : "function",
66 "function" : {
67 "name" : "getCurrentDate"
68 }
69 }, {
70 "type" : "function",
71 "function" : {
72 "name" : "updateApplicationStatus",
73 "parameters" : {
74 ...
75 }
76 }
77 }, {
78 "type" : "function",
79 "function" : {
80 "name" : "sendEmail",
81 "parameters" : {
82 ...
83 }
84 }
85 } ]
86 }
87
88 2026-01-17T16:53:45.099+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
89 - status code: 200
90 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:53:45 GMT], [transfer-encoding: chunked]
91 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-17T08:53:44.795645806Z","message":{"role":"assistant","content":"我将为您安排John Doe的现场面试。首先让我获取当前日期,然后找到需要参加面试的相关员工,并安排会议。","tool_calls":[{"id":"call_che9srkc","function":{"index":0,"name":"getCurrentDate","arguments":{}}}]},"done":true,"done_reason":"stop","total_duration":766029891,"prompt_eval_count":991,"eval_count":37}
92
93
94 2026-01-17T16:53:45.113+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
95 - method: POST
96 - url: http://localhost:11434/api/chat
97 - headers: [Content-Type: application/json]
98 - body: {
99 "model" : "deepseek-v3.1:671b-cloud",
100 "messages" : [ {
101 "role" : "system",
102 "content" : "您通过向所有相关员工发送日历邀请来安排现场会议,\n时间定在从当前日期起一周后的上午,时长为3小时。\n这是相关的职位空缺:职位描述 ID: 123A\r\n后端工程师(金融科技,安特卫普)\r\n------------------------------------------------------------\r\n我们正在招聘一位**后端工程师**,协助我们构建并完善支付与对账服务。您将主要使用 **Java (Spring Boot)**,并与产品及运营团队紧密合作,确保金融交易系统的可靠性和可扩展性。\r\n\r\n**职责:**\r\n* 设计、实现并维护能够处理大规模支付与对账业务的后端服务。\r\n* 在云原生环境中使用 **PostgreSQL**、**Kafka**、**Docker** 和 **Kubernetes**。\r\n* 专注于构建可靠、幂等的系统,并具备强大的可观测性。\r\n* 支持将遗留服务迁移至现代的 REST API。\r\n\r\n**要求:**\r\n* 具备 Java 和 Spring Boot 后端开发的职业经验。\r\n* 深入理解关系型数据库和事件驱动架构。\r\n* 熟悉容器化技术和部署流程。\r\n* 有金融或定价系统相关经验者优先。\r\n* 要求英语流利,会荷兰语者更佳。\n您还需通过祝贺邮件邀请候选人,告知面试详情,\n以及他/她来现场前需要注意的事项。\n最后,您需要将申请状态更新为“已邀请现场面试”。\n"
103 }, {
104 "role" : "user",
105 "content" : "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n\n\nAnswer using the following information:\n1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。"
106 }, {
107 "role" : "assistant",
108 "content" : "我将为您安排John Doe的现场面试。首先让我获取当前日期,然后找到需要参加面试的相关员工,并安排会议。",
109 "tool_calls" : [ {
110 "function" : {
111 "name" : "getCurrentDate",
112 "arguments" : { }
113 }
114 } ]
115 }, {
116 "role" : "tool",
117 "content" : "1768640025109"
118 } ],
119 "options" : {
120 "stop" : [ ]
121 },
122 "stream" : false,
123 "tools" : [ {
124 "type" : "function",
125 "function" : {
126 "name" : "getInvolvedEmployeesForInterview",
127 "description" : "根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名",
128 "parameters" : {
129 ...
130 }
131 }
132 }, {
133 "type" : "function",
134 "function" : {
135 "name" : "createCalendarEntry",
136 "description" : "根据电子邮件地址为员工创建日程条目",
137 "parameters" : {
138 ...
139 }
140 }
141 }, {
142 "type" : "function",
143 "function" : {
144 "name" : "getCurrentDate"
145 }
146 }, {
147 "type" : "function",
148 "function" : {
149 "name" : "updateApplicationStatus",
150 "parameters" : {
151 ...
152 }
153 }
154 }, {
155 "type" : "function",
156 "function" : {
157 "name" : "sendEmail",
158 "parameters" : {
159 ...
160 },
161 "required" : [ "to", "cc", "subject", "body" ]
162 }
163 }
164 } ]
165 }
166
167 2026-01-17T16:53:46.607+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
168 - status code: 200
169 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:53:46 GMT], [transfer-encoding: chunked]
170 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-17T08:53:45.888540222Z","message":{"role":"assistant","content":"","tool_calls":[{"id":"call_pb0rggf6","function":{"index":0,"name":"getInvolvedEmployeesForInterview","arguments":{"jobDescriptionId":"123A"}}}]},"done":true,"done_reason":"stop","total_duration":645456006,"prompt_eval_count":1035,"eval_count":21}
171
172
173 2026-01-17T16:53:46.609+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
174 - method: POST
175 - url: http://localhost:11434/api/chat
176 - headers: [Content-Type: application/json]
177 - body: {
178 "model" : "deepseek-v3.1:671b-cloud",
179 "messages" : [ {
180 "role" : "system",
181 "content" : "您通过向所有相关员工发送日历邀请来安排现场会议,\n时间定在从当前日期起一周后的上午,时长为3小时。\n这是相关的职位空缺:职位描述 ID: 123A\r\n后端工程师(金融科技,安特卫普)\r\n------------------------------------------------------------\r\n我们正在招聘一位**后端工程师**,协助我们构建并完善支付与对账服务。您将主要使用 **Java (Spring Boot)**,并与产品及运营团队紧密合作,确保金融交易系统的可靠性和可扩展性。\r\n\r\n**职责:**\r\n* 设计、实现并维护能够处理大规模支付与对账业务的后端服务。\r\n* 在云原生环境中使用 **PostgreSQL**、**Kafka**、**Docker** 和 **Kubernetes**。\r\n* 专注于构建可靠、幂等的系统,并具备强大的可观测性。\r\n* 支持将遗留服务迁移至现代的 REST API。\r\n\r\n**要求:**\r\n* 具备 Java 和 Spring Boot 后端开发的职业经验。\r\n* 深入理解关系型数据库和事件驱动架构。\r\n* 熟悉容器化技术和部署流程。\r\n* 有金融或定价系统相关经验者优先。\r\n* 要求英语流利,会荷兰语者更佳。\n您还需通过祝贺邮件邀请候选人,告知面试详情,\n以及他/她来现场前需要注意的事项。\n最后,您需要将申请状态更新为“已邀请现场面试”。\n"
182 }, {
183 "role" : "user",
184 "content" : "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n\n\nAnswer using the following information:\n1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。"
185 }, {
186 "role" : "assistant",
187 "content" : "我将为您安排John Doe的现场面试。首先让我获取当前日期,然后找到需要参加面试的相关员工,并安排会议。",
188 "tool_calls" : [ {
189 "function" : {
190 "name" : "getCurrentDate",
191 "arguments" : { }
192 }
193 } ]
194 }, {
195 "role" : "tool",
196 "content" : "1768640025109"
197 }, {
198 "role" : "assistant",
199 "tool_calls" : [ {
200 "function" : {
201 "name" : "getInvolvedEmployeesForInterview",
202 "arguments" : {
203 "jobDescriptionId" : "123A"
204 }
205 }
206 } ]
207 }, {
208 "role" : "tool",
209 "content" : "[ \"Anna Bolena: hiring.manager@company.com\", \"Chris Durue: near.colleague@company.com\", \"Esther Finnigan: vp@company.com\" ]"
210 } ],
211 "options" : {
212 "stop" : [ ]
213 },
214 "stream" : false,
215 "tools" : [ {
216 "type" : "function",
217 "function" : {
218 "name" : "getInvolvedEmployeesForInterview",
219 "description" : "根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名",
220 "parameters" : {
221 ...
222 }
223 }
224 }, {
225 "type" : "function",
226 "function" : {
227 "name" : "createCalendarEntry",
228 "description" : "根据电子邮件地址为员工创建日程条目",
229 "parameters" : {
230 ...
231 }
232 }
233 }, {
234 "type" : "function",
235 "function" : {
236 "name" : "getCurrentDate"
237 }
238 }, {
239 "type" : "function",
240 "function" : {
241 "name" : "updateApplicationStatus",
242 "parameters" : {
243 ...
244 }
245 }
246 }, {
247 "type" : "function",
248 "function" : {
249 "name" : "sendEmail",
250 "parameters" : {
251 ...
252 }
253 }
254 } ]
255 }
256
257 2026-01-17T16:53:50.266+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
258 - status code: 200
259 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:53:50 GMT], [transfer-encoding: chunked]
260 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-17T08:53:48.769553461Z","message":{"role":"assistant","content":"现在我已经获取了需要参加面试的员工信息。让我创建面试会议日程:","tool_calls":[{"id":"call_qzbeevl7","function":{"index":0,"name":"createCalendarEntry","arguments":{"emailAddress":["hiring.manager@company.com","near.colleague@company.com","vp@company.com"],"end":"2025-11–21 12:00","start":"2025-11–21 09:00","topic":"后端工程师职位现场面试 - John Doe"}}}]},"done":true,"done_reason":"stop","total_duration":2032866290,"prompt_eval_count":1095,"eval_count":88}
261
262
263 *** 已创建日程条目 ***
264 主题:后端工程师职位现场面试 - John Doe
265 开始时间:2025-11–21 09:00
266 结束时间:2025-11–21 12:00
267 2026-01-17T16:53:50.272+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
268 - method: POST
269 - url: http://localhost:11434/api/chat
270 - headers: [Content-Type: application/json]
271 - body: {
272 "model" : "deepseek-v3.1:671b-cloud",
273 "messages" : [ {
274 "role" : "system",
275 "content" : "您通过向所有相关员工发送日历邀请来安排现场会议,\n时间定在从当前日期起一周后的上午,时长为3小时。\n这是相关的职位空缺:职位描述 ID: 123A\r\n后端工程师(金融科技,安特卫普)\r\n------------------------------------------------------------\r\n我们正在招聘一位**后端工程师**,协助我们构建并完善支付与对账服务。您将主要使用 **Java (Spring Boot)**,并与产品及运营团队紧密合作,确保金融交易系统的可靠性和可扩展性。\r\n\r\n**职责:**\r\n* 设计、实现并维护能够处理大规模支付与对账业务的后端服务。\r\n* 在云原生环境中使用 **PostgreSQL**、**Kafka**、**Docker** 和 **Kubernetes**。\r\n* 专注于构建可靠、幂等的系统,并具备强大的可观测性。\r\n* 支持将遗留服务迁移至现代的 REST API。\r\n\r\n**要求:**\r\n* 具备 Java 和 Spring Boot 后端开发的职业经验。\r\n* 深入理解关系型数据库和事件驱动架构。\r\n* 熟悉容器化技术和部署流程。\r\n* 有金融或定价系统相关经验者优先。\r\n* 要求英语流利,会荷兰语者更佳。\n您还需通过祝贺邮件邀请候选人,告知面试详情,\n以及他/她来现场前需要注意的事项。\n最后,您需要将申请状态更新为“已邀请现场面试”。\n"
276 }, {
277 "role" : "user",
278 "content" : "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n\n\nAnswer using the following information:\n1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。"
279 }, {
280 "role" : "assistant",
281 "content" : "我将为您安排John Doe的现场面试。首先让我获取当前日期,然后找到需要参加面试的相关员工,并安排会议。",
282 "tool_calls" : [ {
283 "function" : {
284 "name" : "getCurrentDate",
285 "arguments" : { }
286 }
287 } ]
288 }, {
289 "role" : "tool",
290 "content" : "1768640025109"
291 }, {
292 "role" : "assistant",
293 "tool_calls" : [ {
294 "function" : {
295 "name" : "getInvolvedEmployeesForInterview",
296 "arguments" : {
297 "jobDescriptionId" : "123A"
298 }
299 }
300 } ]
301 }, {
302 "role" : "tool",
303 "content" : "[ \"Anna Bolena: hiring.manager@company.com\", \"Chris Durue: near.colleague@company.com\", \"Esther Finnigan: vp@company.com\" ]"
304 }, {
305 "role" : "assistant",
306 "content" : "现在我已经获取了需要参加面试的员工信息。让我创建面试会议日程:",
307 "tool_calls" : [ {
308 "function" : {
309 "name" : "createCalendarEntry",
310 "arguments" : {
311 "emailAddress" : [ "hiring.manager@company.com", "near.colleague@company.com", "vp@company.com" ],
312 "start" : "2025-11–21 09:00",
313 "topic" : "后端工程师职位现场面试 - John Doe",
314 "end" : "2025-11–21 12:00"
315 }
316 }
317 } ]
318 }, {
319 "role" : "tool",
320 "content" : "Success"
321 } ],
322 "options" : {
323 "stop" : [ ]
324 },
325 "stream" : false,
326 "tools" : [ {
327 "type" : "function",
328 "function" : {
329 "name" : "getInvolvedEmployeesForInterview",
330 "description" : "根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名",
331 "parameters" : {
332 ...
333 }
334 }
335 }, {
336 "type" : "function",
337 "function" : {
338 "name" : "createCalendarEntry",
339 "description" : "根据电子邮件地址为员工创建日程条目",
340 "parameters" : {
341 ...
342 }
343 }
344 }, {
345 "type" : "function",
346 "function" : {
347 "name" : "getCurrentDate"
348 }
349 }, {
350 "type" : "function",
351 "function" : {
352 "name" : "updateApplicationStatus",
353 "parameters" : {
354 ...
355 }
356 }
357 }, {
358 "type" : "function",
359 "function" : {
360 "name" : "sendEmail",
361 "parameters" : {
362 ...
363 }
364 }
365 } ]
366 }
367
368 2026-01-17T16:54:10.480+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
369 - status code: 200
370 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:54:10 GMT], [transfer-encoding: chunked]
371 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-17T08:54:09.753507501Z","message":{"role":"assistant","content":"现在我将发送祝贺邮件给候选人John Doe,并告知面试详情:","tool_calls":[{"id":"call_eudsd6uf","function":{"index":0,"name":"sendEmail","arguments":{"body":"尊敬的John Doe先生/女士:\n\n恭喜您!您已成功通过我们后端工程师职位的初步筛选。我们诚挚邀请您参加现场面试。\n\n面试详情:\n- 日期:从当前日期起一周后(2025年11月21日)\n- 时间:上午9:00 - 12:00(时长3小时)\n- 地点:Rue des Carmes 12, 2000 Antwerp, Belgium\n\n现场面试注意事项:\n\n重要访客政策提醒:\n1. 所有外部访客须凭有效身份证件在前台登记方可进入\n2. 您将被授予临时访客证,请确保佩戴在显眼位置\n3. 仅允许在停车场后方指定户外区域吸烟\n4. 办公区安静时段为下午2点至4点,请避免在开放空间大声交谈\n5. 如有自行车,请停放在主楼外侧的专用自行车停放区\n\n我们期待与您见面,讨论您在金融科技后端开发方面的经验与潜力。\n\n祝好,\n招聘团队","cc":["hiring.manager@company.com"],"subject":"祝贺!后端工程师职位现场面试邀请","to":["john.doe.dev@protonmail.com"]}}}]},"done":true,"done_reason":"stop","total_duration":19351550481,"prompt_eval_count":1186,"eval_count":301}
372
373
374 *** 已发送邮件 ***
375 收件人:[john.doe.dev@protonmail.com]
376 抄送:[hiring.manager@company.com]
377 主题:祝贺!后端工程师职位现场面试邀请
378 正文:尊敬的John Doe先生/女士:
379
380 恭喜您!您已成功通过我们后端工程师职位的初步筛选。我们诚挚邀请您参加现场面试。
381
382 面试详情:
383 - 日期:从当前日期起一周后(2025年11月21日)
384 - 时间:上午9:00 - 12:00(时长3小时)
385 - 地点:Rue des Carmes 12, 2000 Antwerp, Belgium
386
387 现场面试注意事项:
388
389 重要访客政策提醒:
390 1. 所有外部访客须凭有效身份证件在前台登记方可进入
391 2. 您将被授予临时访客证,请确保佩戴在显眼位置
392 3. 仅允许在停车场后方指定户外区域吸烟
393 4. 办公区安静时段为下午2点至4点,请避免在开放空间大声交谈
394 5. 如有自行车,请停放在主楼外侧的专用自行车停放区
395
396 我们期待与您见面,讨论您在金融科技后端开发方面的经验与潜力。
397
398 祝好,
399 招聘团队
400 2026-01-17T16:54:10.484+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
401 - method: POST
402 - url: http://localhost:11434/api/chat
403 - headers: [Content-Type: application/json]
404 - body: {
405 "model" : "deepseek-v3.1:671b-cloud",
406 "messages" : [ {
407 "role" : "system",
408 "content" : "您通过向所有相关员工发送日历邀请来安排现场会议,\n时间定在从当前日期起一周后的上午,时长为3小时。\n这是相关的职位空缺:职位描述 ID: 123A\r\n后端工程师(金融科技,安特卫普)\r\n------------------------------------------------------------\r\n我们正在招聘一位**后端工程师**,协助我们构建并完善支付与对账服务。您将主要使用 **Java (Spring Boot)**,并与产品及运营团队紧密合作,确保金融交易系统的可靠性和可扩展性。\r\n\r\n**职责:**\r\n* 设计、实现并维护能够处理大规模支付与对账业务的后端服务。\r\n* 在云原生环境中使用 **PostgreSQL**、**Kafka**、**Docker** 和 **Kubernetes**。\r\n* 专注于构建可靠、幂等的系统,并具备强大的可观测性。\r\n* 支持将遗留服务迁移至现代的 REST API。\r\n\r\n**要求:**\r\n* 具备 Java 和 Spring Boot 后端开发的职业经验。\r\n* 深入理解关系型数据库和事件驱动架构。\r\n* 熟悉容器化技术和部署流程。\r\n* 有金融或定价系统相关经验者优先。\r\n* 要求英语流利,会荷兰语者更佳。\n您还需通过祝贺邮件邀请候选人,告知面试详情,\n以及他/她来现场前需要注意的事项。\n最后,您需要将申请状态更新为“已邀请现场面试”。\n"
409 }, {
410 "role" : "user",
411 "content" : "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n\n\nAnswer using the following information:\n1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。"
412 }, {
413 "role" : "assistant",
414 "content" : "我将为您安排John Doe的现场面试。首先让我获取当前日期,然后找到需要参加面试的相关员工,并安排会议。",
415 "tool_calls" : [ {
416 "function" : {
417 "name" : "getCurrentDate",
418 "arguments" : { }
419 }
420 } ]
421 }, {
422 "role" : "tool",
423 "content" : "1768640025109"
424 }, {
425 "role" : "assistant",
426 "tool_calls" : [ {
427 "function" : {
428 "name" : "getInvolvedEmployeesForInterview",
429 "arguments" : {
430 "jobDescriptionId" : "123A"
431 }
432 }
433 } ]
434 }, {
435 "role" : "tool",
436 "content" : "[ \"Anna Bolena: hiring.manager@company.com\", \"Chris Durue: near.colleague@company.com\", \"Esther Finnigan: vp@company.com\" ]"
437 }, {
438 "role" : "assistant",
439 "content" : "现在我已经获取了需要参加面试的员工信息。让我创建面试会议日程:",
440 "tool_calls" : [ {
441 "function" : {
442 "name" : "createCalendarEntry",
443 "arguments" : {
444 "emailAddress" : [ "hiring.manager@company.com", "near.colleague@company.com", "vp@company.com" ],
445 "start" : "2025-11–21 09:00",
446 "topic" : "后端工程师职位现场面试 - John Doe",
447 "end" : "2025-11–21 12:00"
448 }
449 }
450 } ]
451 }, {
452 "role" : "tool",
453 "content" : "Success"
454 }, {
455 "role" : "assistant",
456 "content" : "现在我将发送祝贺邮件给候选人John Doe,并告知面试详情:",
457 "tool_calls" : [ {
458 "function" : {
459 "name" : "sendEmail",
460 "arguments" : {
461 "cc" : [ "hiring.manager@company.com" ],
462 "subject" : "祝贺!后端工程师职位现场面试邀请",
463 "to" : [ "john.doe.dev@protonmail.com" ],
464 "body" : "尊敬的John Doe先生/女士:\n\n恭喜您!您已成功通过我们后端工程师职位的初步筛选。我们诚挚邀请您参加现场面试。\n\n面试详情:\n- 日期:从当前日期起一周后(2025年11月21日)\n- 时间:上午9:00 - 12:00(时长3小时)\n- 地点:Rue des Carmes 12, 2000 Antwerp, Belgium\n\n现场面试注意事项:\n\n重要访客政策提醒:\n1. 所有外部访客须凭有效身份证件在前台登记方可进入\n2. 您将被授予临时访客证,请确保佩戴在显眼位置\n3. 仅允许在停车场后方指定户外区域吸烟\n4. 办公区安静时段为下午2点至4点,请避免在开放空间大声交谈\n5. 如有自行车,请停放在主楼外侧的专用自行车停放区\n\n我们期待与您见面,讨论您在金融科技后端开发方面的经验与潜力。\n\n祝好,\n招聘团队"
465 }
466 }
467 } ]
468 }, {
469 "role" : "tool",
470 "content" : "1234"
471 } ],
472 "options" : {
473 "stop" : [ ]
474 },
475 "stream" : false,
476 "tools" : [ {
477 "type" : "function",
478 "function" : {
479 "name" : "getInvolvedEmployeesForInterview",
480 "description" : "根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名",
481 "parameters" : {
482 ...
483 }
484 }
485 }, {
486 "type" : "function",
487 "function" : {
488 "name" : "createCalendarEntry",
489 "description" : "根据电子邮件地址为员工创建日程条目",
490 "parameters" : {
491 ...
492 }
493 }
494 }, {
495 "type" : "function",
496 "function" : {
497 "name" : "getCurrentDate"
498 }
499 }, {
500 "type" : "function",
501 "function" : {
502 "name" : "updateApplicationStatus",
503 "parameters" : {
504 ...
505 }
506 }
507 }, {
508 "type" : "function",
509 "function" : {
510 "name" : "sendEmail",
511 "parameters" : {
512 ...
513 }
514 }
515 } ]
516 }
517
518 2026-01-17T16:54:12.455+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
519 - status code: 200
520 - headers: [content-type: application/json; charset=utf-8], [date: Sat, 17 Jan 2026 08:54:12 GMT], [transfer-encoding: chunked]
521 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-17T08:54:11.733376347Z","message":{"role":"assistant","content":"最后,我将更新申请状态:","tool_calls":[{"id":"call_rmbx9gyb","function":{"index":0,"name":"updateApplicationStatus","arguments":{"candidateName":"John Doe","jobDescriptionId":"123A","newStatus":"已邀请现场面试"}}}]},"done":true,"done_reason":"stop","total_duration":1119737172,"prompt_eval_count":1491,"eval_count":39}
522
523
524 *** 已更新申请状态 ***
525 职位描述ID:123A
526 候选人姓名:John Doe
527 新状态:已邀请现场面试
528 2026-01-17T16:54:12.458+08:00 INFO 15192 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
529 - method: POST
530 - url: http://localhost:11434/api/chat
531 - headers: [Content-Type: application/json]
532 - body: {
533 "model" : "deepseek-v3.1:671b-cloud",
534 "messages" : [ {
535 "role" : "system",
536 "content" : "您通过向所有相关员工发送日历邀请来安排现场会议,\n时间定在从当前日期起一周后的上午,时长为3小时。\n这是相关的职位空缺:职位描述 ID: 123A\r\n后端工程师(金融科技,安特卫普)\r\n------------------------------------------------------------\r\n我们正在招聘一位**后端工程师**,协助我们构建并完善支付与对账服务。您将主要使用 **Java (Spring Boot)**,并与产品及运营团队紧密合作,确保金融交易系统的可靠性和可扩展性。\r\n\r\n**职责:**\r\n* 设计、实现并维护能够处理大规模支付与对账业务的后端服务。\r\n* 在云原生环境中使用 **PostgreSQL**、**Kafka**、**Docker** 和 **Kubernetes**。\r\n* 专注于构建可靠、幂等的系统,并具备强大的可观测性。\r\n* 支持将遗留服务迁移至现代的 REST API。\r\n\r\n**要求:**\r\n* 具备 Java 和 Spring Boot 后端开发的职业经验。\r\n* 深入理解关系型数据库和事件驱动架构。\r\n* 熟悉容器化技术和部署流程。\r\n* 有金融或定价系统相关经验者优先。\r\n* 要求英语流利,会荷兰语者更佳。\n您还需通过祝贺邮件邀请候选人,告知面试详情,\n以及他/她来现场前需要注意的事项。\n最后,您需要将申请状态更新为“已邀请现场面试”。\n"
537 }, {
538 "role" : "user",
539 "content" : "为此候选人安排现场面试会议(需遵守外部访客政策):候选人联系卡片:\r\n姓名:John Doe\r\n地址:Rue des Carmes 12, 2000 Antwerp, Belgium(比利时安特卫普)\r\n邮箱:john.doe.dev@protonmail.com\r\n电话:+32 495 67 89 23\n\n\nAnswer using the following information:\n1.仅允许在停车场后方指定户外区域吸烟。\r\n2.办公区安静时段为下午2点至4点,请避免在开放空间大声交谈。\r\n3.员工须至少提前24小时通过内部日历预订会议室。\r\n4.自行车必须停放在主楼外侧的专用自行车停放区。\r\n5.所有外部访客须凭有效身份证件在前台登记方可进入。\r\n6.外部访客均须佩戴临时访客证,并确保证件清晰可见。"
540 }, {
541 "role" : "assistant",
542 "content" : "我将为您安排John Doe的现场面试。首先让我获取当前日期,然后找到需要参加面试的相关员工,并安排会议。",
543 "tool_calls" : [ {
544 "function" : {
545 "name" : "getCurrentDate",
546 "arguments" : { }
547 }
548 } ]
549 }, {
550 "role" : "tool",
551 "content" : "1768640025109"
552 }, {
553 "role" : "assistant",
554 "tool_calls" : [ {
555 "function" : {
556 "name" : "getInvolvedEmployeesForInterview",
557 "arguments" : {
558 "jobDescriptionId" : "123A"
559 }
560 }
561 } ]
562 }, {
563 "role" : "tool",
564 "content" : "[ \"Anna Bolena: hiring.manager@company.com\", \"Chris Durue: near.colleague@company.com\", \"Esther Finnigan: vp@company.com\" ]"
565 }, {
566 "role" : "assistant",
567 "content" : "现在我已经获取了需要参加面试的员工信息。让我创建面试会议日程:",
568 "tool_calls" : [ {
569 "function" : {
570 "name" : "createCalendarEntry",
571 "arguments" : {
572 "emailAddress" : [ "hiring.manager@company.com", "near.colleague@company.com", "vp@company.com" ],
573 "start" : "2025-11–21 09:00",
574 "topic" : "后端工程师职位现场面试 - John Doe",
575 "end" : "2025-11–21 12:00"
576 }
577 }
578 } ]
579 }, {
580 "role" : "tool",
581 "content" : "Success"
582 }, {
583 "role" : "assistant",
584 "content" : "现在我将发送祝贺邮件给候选人John Doe,并告知面试详情:",
585 "tool_calls" : [ {
586 "function" : {
587 "name" : "sendEmail",
588 "arguments" : {
589 "cc" : [ "hiring.manager@company.com" ],
590 "subject" : "祝贺!后端工程师职位现场面试邀请",
591 "to" : [ "john.doe.dev@protonmail.com" ],
592 "body" : "尊敬的John Doe先生/女士:\n\n恭喜您!您已成功通过我们后端工程师职位的初步筛选。我们诚挚邀请您参加现场面试。\n\n面试详情:\n- 日期:从当前日期起一周后(2025年11月21日)\n- 时间:上午9:00 - 12:00(时长3小时)\n- 地点:Rue des Carmes 12, 2000 Antwerp, Belgium\n\n现场面试注意事项:\n\n重要访客政策提醒:\n1. 所有外部访客须凭有效身份证件在前台登记方可进入\n2. 您将被授予临时访客证,请确保佩戴在显眼位置\n3. 仅允许在停车场后方指定户外区域吸烟\n4. 办公区安静时段为下午2点至4点,请避免在开放空间大声交谈\n5. 如有自行车,请停放在主楼外侧的专用自行车停放区\n\n我们期待与您见面,讨论您在金融科技后端开发方面的经验与潜力。\n\n祝好,\n招聘团队"
593 }
594 }
595 } ]
596 }, {
597 "role" : "tool",
598 "content" : "1234"
599 }, {
600 "role" : "assistant",
601 "content" : "最后,我将更新申请状态:",
602 "tool_calls" : [ {
603 "function" : {
604 "name" : "updateApplicationStatus",
605 "arguments" : {
606 "candidateName" : "John Doe",
607 "newStatus" : "已邀请现场面试",
608 "jobDescriptionId" : "123A"
609 }
610 }
611 } ]
612 }, {
613 "role" : "tool",
614 "content" : "Success"
615 } ],
616 "options" : {
617 "stop" : [ ]
618 },
619 "stream" : false,
620 "tools" : [ {
621 "type" : "function",
622 "function" : {
623 "name" : "getInvolvedEmployeesForInterview",
624 "description" : "根据给定的职位描述ID,查找需要参加现场面试的人员的电子邮件地址和姓名",
625 "parameters" : {
626 ...
627 }
628 }
629 }, {
630 "type" : "function",
631 "function" : {
632 "name" : "createCalendarEntry",
633 "description" : "根据电子邮件地址为员工创建日程条目",
634 "parameters" : {
635 ...
636 }
637 }
638 }, {
639 "type" : "function",
640 "function" : {
641 "name" : "getCurrentDate"
642 }
643 }, {
644 "type" : "function",
645 "function" : {
646 "name" : "updateApplicationStatus",
647 "parameters" : {
648 ...
649 }
650 }
651 }, {
652 "type" : "function",
653 "function" : {
654 "name" : "sendEmail",
655 "parameters" : {
656 ...
657 }
658 }
659 } ]
660 }输出内容比较长,解释一下:


这里将InterviewOrganizer实例附加了RAG工具后,RAG会将对应Agent中的用户Prompt自动向量化,即:

文中示例代码:
https://github.com/yjmyzz/agentic_turoial_with_langchain4j
参考:
Building Effective AI Agents \ Anthropic
[译] AI Workflow & AI Agent:架构、模式与工程建议(Anthropic,2024)