【从0到1构建一个ClaudeAgent】协作-Agent团队 Java实现代码javapublic class AgentTeamsSystem { // --- 配置 --- private static final Path WORKDIR Paths.get(System.getProperty(user.dir)); private static final Path TEAM_DIR WORKDIR.resolve(.team); private static final Path INBOX_DIR TEAM_DIR.resolve(inbox); private static final Gson gson new GsonBuilder().setPrettyPrinting().create(); // 有效消息类型 private static final SetString VALID_MSG_TYPES Set.of( message, broadcast, shutdown_request, shutdown_response, plan_approval_response ); // --- 消息系统MessageBus--- static class MessageBus { private final Path inboxDir; public MessageBus(Path inboxDir) { this.inboxDir inboxDir; try { Files.createDirectories(inboxDir); } catch (IOException e) { throw new RuntimeException(Failed to create inbox directory, e); } } /** * 发送消息到指定智能体 */ public String send(String sender, String to, String content, String msgType, MapString, Object extra) { if (!VALID_MSG_TYPES.contains(msgType)) { return String.format(Error: Invalid type %s. Valid: %s, msgType, String.join(, , VALID_MSG_TYPES)); } MapString, Object message new LinkedHashMap(); message.put(type, msgType); message.put(from, sender); message.put(content, content); message.put(timestamp, System.currentTimeMillis() / 1000.0); if (extra ! null) { message.putAll(extra); } Path inboxPath inboxDir.resolve(to .jsonl); try { String jsonLine gson.toJson(message) \n; Files.writeString(inboxPath, jsonLine, StandardOpenOption.CREATE, StandardOpenOption.APPEND); return String.format(Sent %s to %s, msgType, to); } catch (IOException e) { return Error: e.getMessage(); } } /** * 读取并清空邮箱 */ public ListMapString, Object readInbox(String name) { Path inboxPath inboxDir.resolve(name .jsonl); if (!Files.exists(inboxPath)) { return new ArrayList(); } try { ListMapString, Object messages new ArrayList(); ListString lines Files.readAllLines(inboxPath); for (String line : lines) { if (!line.trim().isEmpty()) { Type type new TypeTokenMapString, Object(){}.getType(); MapString, Object message gson.fromJson(line, type); messages.add(message); } } // 清空邮箱消费模式 Files.writeString(inboxPath, ); return messages; } catch (IOException e) { return new ArrayList(); } } /** * 广播消息到所有队友 */ public String broadcast(String sender, String content, ListString teammates) { int count 0; for (String name : teammates) { if (!name.equals(sender)) { send(sender, name, content, broadcast); count; } } return String.format(Broadcast to %d teammates, count); } } // 初始化消息总线 private static final MessageBus BUS new MessageBus(INBOX_DIR); // --- 智能体管理器TeammateManager--- static class TeammateManager { private final Path teamDir; private final Path configPath; private MapString, Object config; private final MapString, Thread threads new ConcurrentHashMap(); private final MapString, AtomicBoolean stopFlags new ConcurrentHashMap(); public TeammateManager(Path teamDir) { this.teamDir teamDir; this.configPath teamDir.resolve(config.json); loadConfig(); } SuppressWarnings(unchecked) private void loadConfig() { try { if (Files.exists(configPath)) { String content Files.readString(configPath); Type type new TypeTokenMapString, Object(){}.getType(); this.config gson.fromJson(content, type); } else { this.config new HashMap(); config.put(team_name, default); config.put(members, new ArrayListMapString, Object()); saveConfig(); } } catch (IOException e) { throw new RuntimeException(Failed to load team config, e); } } SuppressWarnings(unchecked) public String spawn(String name, String role, String prompt) { MapString, Object member findMember(name); if (member ! null) { String status (String) member.get(status); if (!idle.equals(status) !shutdown.equals(status)) { return String.format(Error: %s is currently %s, name, status); } member.put(status, working); member.put(role, role); } else { member new LinkedHashMap(); member.put(name, name); member.put(role, role); member.put(status, working); ((ListMapString, Object) config.get(members)).add(member); } saveConfig(); // 停止之前的线程如果存在 if (threads.containsKey(name)) { stopFlags.get(name).set(true); try { threads.get(name).join(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } // 创建新的停止标志 AtomicBoolean stopFlag new AtomicBoolean(false); stopFlags.put(name, stopFlag); // 创建并启动新线程 Thread thread new Thread(() - teammateLoop(name, role, prompt, stopFlag), Teammate- name); thread.setDaemon(true); threads.put(name, thread); thread.start(); return String.format(Spawned %s (role: %s), name, role); } private void teammateLoop(String name, String role, String prompt, AtomicBoolean stopFlag) { String systemPrompt String.format( You are %s, role: %s, at %s. Use send_message to communicate. Complete your task., name, role, WORKDIR ); ListMapString, Object messages new ArrayList(); messages.add(Map.of(role, user, content, prompt)); // 最大迭代次数限制 for (int i 0; i 50 !stopFlag.get(); i) { try { // 检查邮箱 ListMapString, Object inbox BUS.readInbox(name); for (MapString, Object msg : inbox) { messages.add(Map.of(role, user, content, gson.toJson(msg))); } // 模拟调用 LLM MapString, Object response simulateTeammateLLMCall(systemPrompt, messages, name); if (response null || end_turn.equals(response.get(stop_reason))) { break; } // ... 执行工具调用 // 短暂休眠避免 CPU 过度使用 Thread.sleep(100); } catch (Exception e) { System.err.printf([%s] Error: %s%n, name, e.getMessage()); break; } } // 更新状态 SuppressWarnings(unchecked) MapString, Object member findMember(name); if (member ! null !shutdown.equals(member.get(status))) { member.put(status, idle); saveConfig(); } threads.remove(name); stopFlags.remove(name); } SuppressWarnings(unchecked) public String listAll() { ListMapString, Object members (ListMapString, Object) config.get(members); if (members.isEmpty()) { return No teammates.; } StringBuilder sb new StringBuilder(); sb.append(Team: ).append(config.get(team_name)).append(\n); for (MapString, Object member : members) { sb.append(String.format( %s (%s): %s%n, member.get(name), member.get(role), member.get(status) )); } return sb.toString().trim(); } SuppressWarnings(unchecked) public ListString memberNames() { ListMapString, Object members (ListMapString, Object) config.get(members); return members.stream() .map(m - (String) m.get(name)) .collect(Collectors.toList()); } /** * 获取活动成员数量 */ SuppressWarnings(unchecked) public int getActiveCount() { ListMapString, Object members (ListMapString, Object) config.get(members); int count 0; for (MapString, Object member : members) { if (working.equals(member.get(status))) { count; } } return count; } } // 初始化智能体管理器 private static final TeammateManager TEAM_MANAGER new TeammateManager(TEAM_DIR); // --- 工具枚举 --- public enum ToolType { BASH(bash, Run a shell command.), READ_FILE(read_file, Read file contents.), WRITE_FILE(write_file, Write content to file.), EDIT_FILE(edit_file, Replace exact text in file.), SPAWN_TEAMMATE(spawn_teammate, Spawn a persistent teammate that runs in its own thread.), // 新增 LIST_TEAMMATES(list_teammates, List all teammates with name, role, status.), // 新增 SEND_MESSAGE(send_message, Send a message to a teammates inbox.), // 新增 READ_INBOX(read_inbox, Read and drain the leads inbox.), // 新增 BROADCAST(broadcast, Send a message to all teammates.); // 新增 public final String name; public final String description; ToolType(String name, String description) { this.name name; this.description description; } } // --- 工具处理器映射 --- private static final MapString, ToolExecutor TOOL_HANDLERS new HashMap(); static { // ... 省略基础工具注册 // 团队管理工具 TOOL_HANDLERS.put(ToolType.SPAWN_TEAMMATE.name, args - { String name (String) args.get(name); String role (String) args.get(role); String prompt (String) args.get(prompt); return TEAM_MANAGER.spawn(name, role, prompt); }); TOOL_HANDLERS.put(ToolType.LIST_TEAMMATES.name, args - { return TEAM_MANAGER.listAll(); }); TOOL_HANDLERS.put(ToolType.SEND_MESSAGE.name, args - { String to (String) args.get(to); String content (String) args.get(content); String msgType (String) args.get(msg_type); if (msgType null) msgType message; return BUS.send(lead, to, content, msgType); }); TOOL_HANDLERS.put(ToolType.READ_INBOX.name, args - { ListMapString, Object inbox BUS.readInbox(lead); return gson.toJson(inbox); }); TOOL_HANDLERS.put(ToolType.BROADCAST.name, args - {