【从0到1构建一个ClaudeAgent】协作-自主Agent

【从0到1构建一个ClaudeAgent】协作-自主Agent 工作-空闲循环智能体在工作完成时自动进入空闲状态任务自动认领空闲时扫描任务板自动认领无人认领的任务身份重新注入在上下文压缩后重新注入智能体身份信息自动资源管理空闲超时自动关机释放资源关键洞察扫描看板认领任务。队友自己扫描任务板并认领任务无需主 Agent 逐个分配。Java实现代码javapublic class AutonomousAgentsSystem { // --- 新增配置 --- private static final Path TASKS_DIR WORKDIR.resolve(.tasks); // 任务存储目录 private static final int POLL_INTERVAL 5; // 空闲轮询间隔秒 private static final int IDLE_TIMEOUT 60; // 空闲超时秒 private static final Object claimLock new Object(); // 任务认领锁 // --- 新增任务板扫描 --- /** * 扫描无人认领的任务 */ private static ListMapString, Object scanUnclaimedTasks() { try { Files.createDirectories(TASKS_DIR); ListMapString, Object unclaimed new ArrayList(); Files.list(TASKS_DIR) .filter(p - p.getFileName().toString().startsWith(task_)) .filter(p - p.getFileName().toString().endsWith(.json)) .sorted() .forEach(p - { try { String content Files.readString(p); Type type new TypeTokenMapString, Object(){}.getType(); MapString, Object task gson.fromJson(content, type); // 检查是否可认领 String status (String) task.get(status); String owner (String) task.get(owner); SuppressWarnings(unchecked) ListInteger blockedBy (ListInteger) task.get(blockedBy); if (pending.equals(status) (owner null || owner.isEmpty()) (blockedBy null || blockedBy.isEmpty())) { unclaimed.add(task); } // 可认领条件状态为pending、无所有者、无阻塞依赖 // 有序扫描按文件名排序确保公平性 } catch (IOException e) { // 忽略读取错误 } }); return unclaimed; } catch (IOException e) { return new ArrayList(); } } /** * 认领任务 */ private static String claimTask(int taskId, String owner) { synchronized (claimLock) { // 同步锁防止并发认领 Path taskPath TASKS_DIR.resolve(task_ taskId .json); if (!Files.exists(taskPath)) { return Error: Task taskId not found; } try { String content Files.readString(taskPath); Type type new TypeTokenMapString, Object(){}.getType(); MapString, Object task gson.fromJson(content, type); // 更新任务信息 task.put(owner, owner); task.put(status, in_progress); // 原子性更新确保任务不会被多个智能体同时认领 // 状态转换pending → in_progress Files.writeString(taskPath, gson.toJson(task)); return String.format(Claimed task #%d for %s, taskId, owner); } catch (IOException e) { return Error: e.getMessage(); } } } // --- 新增身份重新注入 --- /** * 创建身份块用于上下文压缩后重新注入身份 */ private static MapString, Object makeIdentityBlock(String name, String role, String teamName) { return Map.of( role, user, content, String.format( identityYou are %s, role: %s, team: %s. Continue your work./identity, name, role, teamName ) ); // 身份持久化即使上下文被压缩也能重新注入身份 // 结构化标记identity标签明确标识身份信息 } // --- 新增团队成员工具 --- private String executeTeammateTool(String sender, String toolName, MapString, Object args) { try { switch (toolName) { // ... 原有的工具处理 ... case idle: // idle 工具在工作循环中特殊处理 return Entering idle phase. Will poll for new tasks.; // 主动空闲智能体主动表示完成当前工作 case claim_task: int taskId ((Number) args.get(task_id)).intValue(); return claimTask(taskId, sender); // 主动认领智能体主动认领指定任务 } } catch (Exception e) { return Error: e.getMessage(); } } // --- 新增团队成员工具定义 --- private ListMapString, Object getTeammateTools() { ListMapString, Object tools new ArrayList(); // 新增 idle 工具 tools.add(createToolSpec(idle, Signal that you have no more work. Enters idle polling phase., Map.of(), List.of())); // 无参数工具简单的状态转换工具 // 新增 claim_task 工具 tools.add(createToolSpec(claim_task, Claim a task from the task board by ID., Map.of(task_id, Map.of(type, integer)), List.of(task_id))); // 主动工作智能体可以主动选择任务 return tools; } // --- 新增团队成员主循环工作-空闲循环--- private void teammateLoop(String name, String role, String prompt, AtomicBoolean stopFlag) { SuppressWarnings(unchecked) String teamName (String) TEAM_MANAGER.config.get(team_name); String systemPrompt String.format( You are %s, role: %s, team: %s, at %s. Use idle tool when you have no more work. You will auto-claim new tasks., name, role, teamName, WORKDIR ); // 增强系统提示包含空闲行为和自动认领机制 ListMapString, Object messages new ArrayList(); messages.add(Map.of(role, user, content, prompt)); while (!stopFlag.get()) { // 外层循环支持工作-空闲循环 // --- 工作阶段 --- TEAM_MANAGER.setStatus(name, working); boolean completedWorkPhase false; for (int i 0; i 50 !stopFlag.get(); i) { try { // ... 检查邮箱、调用LLM、执行工具等逻辑 ... boolean idleRequested false; for (MapString, Object block : content) { if (tool_use.equals(block.get(type))) { String toolName (String) block.get(name); if (idle.equals(toolName)) { idleRequested true; // 标记空闲请求 break; } } } if (idleRequested) { completedWorkPhase true; break; // 退出工作阶段进入空闲阶段 } } catch (Exception e) { System.err.printf([%s] Error: %s%n, name, e.getMessage()); break; } } if (!completedWorkPhase) { // 没有明确进入空闲可能是因为错误 TEAM_MANAGER.setStatus(name, idle); return; } // --- 空闲阶段 --- TEAM_MANAGER.setStatus(name, idle); boolean resume false; int maxPolls IDLE_TIMEOUT / Math.max(POLL_INTERVAL, 1); for (int pollCount 0; pollCount maxPolls !stopFlag.get(); pollCount) { try { Thread.sleep(POLL_INTERVAL * 1000L); // 周期性轮询 } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } // 检查邮箱 ListMapString, Object inbox BUS.readInbox(name); if (!inbox.isEmpty()) { for (MapString, Object msg : inbox) { if (shutdown_request.equals(msg.get(type))) { TEAM_MANAGER.setStatus(name, shutdown); return; } messages.add(Map.of(role, user, content, gson.toJson(msg))); } resume true; // 有消息恢复工作 break; } // 扫描无人认领的任务 ListMapString, Object unclaimed scanUnclaimedTasks(); if (!unclaimed.isEmpty()) { MapString, Object task unclaimed.get(0); int taskId ((Number) task.get(id)).intValue(); // 自动认领任务 claimTask(taskId, name); // 创建任务提示 String taskSubject (String) task.get(subject); String taskDesc (String) task.get(description); if (taskDesc null) taskDesc ; String taskPrompt String.format( auto-claimedTask #%d: %s%n%s/auto-claimed, taskId, taskSubject, taskDesc ); // 如果消息历史太短重新注入身份 if (messages.size() 3) { messages.add(0, makeIdentityBlock(name, role, teamName)); messages.add(1, Map.of(role, assistant, content, I am name . Continuing.)); // 身份恢复确保智能体知道自己的身份 } messages.add(Map.of(role, user, content, taskPrompt)); messages.add(Map.of(role, assistant, content, Claimed task # taskId . Working on it.)); // 自动对话模拟智能体认领任务并开始工作 resume true; // 有任务恢复工作 break; } } if (!resume) { // 空闲超时自动关机 TEAM_MANAGER.setStatus(name, shutdown); return; } // 重新进入工作阶段 } } // --- 新增主程序的特殊命令 --- public static void main(String[] args) { // ... 初始化代码 ... while (true) { System.out.print(\n\033[36ms11 \033[0m); String userInput scanner.nextLine().trim(); if (userInput.isEmpty() || exit.equalsIgnoreCase(userInput) || q.equalsIgnoreCase(userInput)) { break; } // 特殊命令 if (/team.equals(userInput)) { System.out.println(\n TEAM_MANAGER.listAll()); continue; } if (/inbox.equals(userInput)) { ListMapString, Object inbox BUS.readInbox(lead); if (inbox.isEmpty()) { System.out.println(\nLeaders inbox is empty.); } else { System.out.println(\nLeaders inbox:); System.out.println(gson.toJson(inbox)); } continue; } if (/tasks.equals(userInput)) { try { Files.createDirectories(TASKS_DIR); Files.list(TASKS_DIR) .filter(p - p.getFileName().toString().startsWith(task_)) .filter(p - p.getFileName().toString().endsWith(.json)) .sorted() .forEach(p - { try { String content Files.readString(p); Type type new TypeTokenMapString, Object(){}.getType(); MapString, Object task gson.fromJson(content, type);