【从0到1构建一个ClaudeAgent】协作-Agent团队
·
Java实现代码
java
public 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 Set<String> 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, Map<String, Object> extra) {
if (!VALID_MSG_TYPES.contains(msgType)) {
return String.format("Error: Invalid type '%s'. Valid: %s",
msgType, String.join(", ", VALID_MSG_TYPES));
}
Map<String, 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 List<Map<String, Object>> readInbox(String name) {
Path inboxPath = inboxDir.resolve(name + ".jsonl");
if (!Files.exists(inboxPath)) {
return new ArrayList<>();
}
try {
List<Map<String, Object>> messages = new ArrayList<>();
List<String> lines = Files.readAllLines(inboxPath);
for (String line : lines) {
if (!line.trim().isEmpty()) {
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, 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, List<String> 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 Map<String, Object> config;
private final Map<String, Thread> threads = new ConcurrentHashMap<>();
private final Map<String, 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 TypeToken<Map<String, Object>>(){}.getType();
this.config = gson.fromJson(content, type);
} else {
this.config = new HashMap<>();
config.put("team_name", "default");
config.put("members", new ArrayList<Map<String, 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) {
Map<String, 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");
((List<Map<String, 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
);
List<Map<String, Object>> messages = new ArrayList<>();
messages.add(Map.of("role", "user", "content", prompt));
// 最大迭代次数限制
for (int i = 0; i < 50 && !stopFlag.get(); i++) {
try {
// 检查邮箱
List<Map<String, Object>> inbox = BUS.readInbox(name);
for (Map<String, Object> msg : inbox) {
messages.add(Map.of("role", "user", "content", gson.toJson(msg)));
}
// 模拟调用 LLM
Map<String, 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")
Map<String, 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() {
List<Map<String, Object>> members = (List<Map<String, 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 (Map<String, 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 List<String> memberNames() {
List<Map<String, Object>> members = (List<Map<String, Object>>) config.get("members");
return members.stream()
.map(m -> (String) m.get("name"))
.collect(Collectors.toList());
}
/**
* 获取活动成员数量
*/
@SuppressWarnings("unchecked")
public int getActiveCount() {
List<Map<String, Object>> members = (List<Map<String, Object>>) config.get("members");
int count = 0;
for (Map<String, 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 teammate's inbox."), // 新增
READ_INBOX("read_inbox", "Read and drain the lead's 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 Map<String, 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 -> {
List<Map<String, Object>> inbox = BUS.readInbox("lead");
return gson.toJson(inbox);
});
TOOL_HANDLERS.put(ToolType.BROADCAST.name, args -> {更多推荐


所有评论(0)