制:空閑輪詢、任務(wù)自動認(rèn)領(lǐng)與身份重注入的完整實(shí)現(xiàn)解析)
learn-claude-code 自主 Agent 機(jī)制空閑輪詢、任務(wù)自動認(rèn)領(lǐng)與身份重注入的完整實(shí)現(xiàn)解析【免費(fèi)下載鏈接】learn-claude-codeBash is all you need - A nano claude code–like 「agent harness」, built from 0 to 1項(xiàng)目地址: https://gitcode.com/GitHub_Trending/an/learn-claude-code在 learn-claude-code 的課程體系中s11Legacy 12 課時軌道解決一個多智能體協(xié)作中的規(guī)?;款i讓 teammate 不再等待 lead 逐個分派工作而是自己掃描任務(wù)板、認(rèn)領(lǐng)無主任務(wù)、做完后繼續(xù)尋找下一份工作。本文基于 docs/en/s11-autonomous-agents.md 與可運(yùn)行實(shí)現(xiàn) agents/s11_autonomous_agents.py完整講清 WORK/IDLE 雙階段生命周期、空閑輪詢參數(shù)、原子任務(wù)認(rèn)領(lǐng)與上下文壓縮后的身份重注入并結(jié)合當(dāng)前 17 課時軌道 s13_agent_teams/code.py 中的演進(jìn)實(shí)現(xiàn)幫助讀者掌握一套可直接落地的自治 Agent運(yùn)行時設(shè)計。問題Lead 逐一分派工作無法規(guī)模化在 s09–s10 的實(shí)現(xiàn)中teammate 只有被明確指派時才工作lead 必須為每個 teammate 生成一個帶具體 prompt 的 spawn 調(diào)用。假設(shè)任務(wù)板上有 10 個無主任務(wù)lead 就要手動逐一分派——這在多 Agent 場景下不可擴(kuò)展。s11 引入的真自治模式是teammate 主動掃描任務(wù)板task board認(rèn)領(lǐng)無主unclaimed任務(wù)處理完后繼續(xù)尋找下一份任務(wù)而不是直接退出一個微妙問題經(jīng)歷上下文壓縮s06 課程的主題后agent 可能忘記自己是誰。s11 用**身份重注入identity re-injection**修復(fù)這一點(diǎn)。解決方案帶空閑周期的 teammate 生命周期文檔給出的核心生命周期是一個 spawn → WORK → IDLE →循環(huán)回 WORK 或 SHUTDOWN的狀態(tài)機(jī)Teammate lifecycle with idle cycle: ------- | spawn | ------ | v ------- tool_use ------- | WORK | ------------- | LLM | ------ ------- | | stop_reason ! tool_use (or idle tool called) v -------- | IDLE | poll every 5s for up to 60s ------- | --- check inbox -- message? ---------- WORK | --- scan .tasks/ -- unclaimed? ------- claim - WORK | --- 60s timeout ---------------------- SHUTDOWN Identity re-injection after compression: if len(messages) 3: messages.insert(0, identity_block)狀態(tài)機(jī)的四個關(guān)鍵轉(zhuǎn)移條件WORK → IDLELLM 的stop_reason ! tool_use自然停止或 teammate 顯式調(diào)用idle工具IDLE → WORK消息恢復(fù)輪詢期間發(fā)現(xiàn)收件箱inbox有消息IDLE → WORK自動認(rèn)領(lǐng)掃描.tasks/發(fā)現(xiàn)無主任務(wù)認(rèn)領(lǐng)后進(jìn)入工作IDLE → SHUTDOWN60 秒超時期間既無消息也無任務(wù)。兩個可調(diào)參數(shù)在源碼中定義于 agents/s11_autonomous_agents.pyPOLL_INTERVAL 5 # 空閑輪詢間隔秒 IDLE_TIMEOUT 60 # 空閑超時秒超時后自動 shutdown輪詢次數(shù)由IDLE_TIMEOUT // POLL_INTERVAL計算即 60s / 5s 12 次輪詢機(jī)會。工作機(jī)制一雙階段 teammate 主循環(huán)源碼中 teammate 的循環(huán)TeammateManager._loop嚴(yán)格對應(yīng)文檔描述的兩個階段見 agents/s11_autonomous_agents.pydef _loop(self, name, role, prompt): while True: # -- WORK PHASE -- messages [{role: user, content: prompt}] for _ in range(50): response client.messages.create(...) if response.stop_reason ! tool_use: break # execute tools... if idle_requested: break # -- IDLE PHASE -- self._set_status(name, idle) resume self._idle_poll(name, messages) if not resume: self._set_status(name, shutdown) return self._set_status(name, working)實(shí)現(xiàn)上有幾個值得注意的工程細(xì)節(jié)對照 源碼 L224-L302WORK 階段每次迭代都先排空收件箱調(diào)用 LLM 前先執(zhí)行BUS.read_inbox(name)若發(fā)現(xiàn)shutdown_request消息則立即置為shutdown狀態(tài)并返回保證關(guān)閉握手s10 引入的協(xié)議在忙碌時也能被及時響應(yīng)idle工具的特殊處理idle不是一個真實(shí)執(zhí)行的工具而是在工具分發(fā)時設(shè)置idle_requested True標(biāo)志并返回固定文本Entering idle phase. Will poll for new tasks.L251-L253異常降級LLM 調(diào)用拋異常時teammate 被置為idle并安全返回而不是讓整個團(tuán)隊(duì)進(jìn)程崩潰L241-L243WORK 階段有 50 輪工具調(diào)用上限防止單任務(wù)無限循環(huán)燒 token。teammate 的系統(tǒng)提示詞L217-L220明確告訴模型自治行為契約sys_prompt ( fYou are {name}, role: {role}, team: {team_name}, at {WORKDIR}. fUse idle tool when you have no more work. You will auto-claim new tasks. )工作機(jī)制二空閑輪詢 inbox 與任務(wù)板IDLE 階段的輪詢邏輯對應(yīng)文檔第 2 點(diǎn)的_idle_poll實(shí)現(xiàn)見 源碼 L266-L301def _idle_poll(self, name, messages): for _ in range(IDLE_TIMEOUT // POLL_INTERVAL): # 60s / 5s 12 time.sleep(POLL_INTERVAL) inbox BUS.read_inbox(name) if inbox: messages.append({role: user, content: finbox{inbox}/inbox}) return True unclaimed scan_unclaimed_tasks() if unclaimed: claim_task(unclaimed[0][id], name) messages.append({role: user, content: fauto-claimedTask #{unclaimed[0][id]}: f{unclaimed[0][subject]}/auto-claimed}) return True return False # timeout - shutdown從源碼實(shí)現(xiàn)看輪詢順序是先 inbox、后任務(wù)板消息來自 lead 或隊(duì)友的協(xié)作信息優(yōu)先級高于自取任務(wù)且每次輪詢失敗認(rèn)領(lǐng)沖突等會continue繼續(xù)下一輪直到 12 輪耗盡才真正 shutdown。inbox 的底層存儲是 MessageBusL81-L121每個 teammate 對應(yīng).team/inbox/{name}.jsonl一個 JSONL 文件send追加一行、read_inbox讀取后清空drain 語義合法消息類型包括message、broadcast、shutdown_request、shutdown_response、plan_approval_responseL65-L71。這種基于文件郵箱的異步通信是 s09/s10 建立的協(xié)議層在 s11 中的直接復(fù)用。工作機(jī)制三任務(wù)板掃描與原子認(rèn)領(lǐng)任務(wù)板以.tasks/task_*.json文件為持久化載體。掃描函數(shù)返回滿足三個條件的任務(wù)L128-L137def scan_unclaimed_tasks() - list: unclaimed [] for f in sorted(TASKS_DIR.glob(task_*.json)): task json.loads(f.read_text()) if (task.get(status) pending and not task.get(owner) and not task.get(blockedBy)): unclaimed.append(task) return unclaimed三個條件分別保證任務(wù)未開始pending、無主owner為空、且沒有被依賴任務(wù)阻塞blockedBy為空——這意味著 teammate 會自動尊重任務(wù) DAG 的依賴順序這是文檔Try It第 3 條創(chuàng)建帶依賴的任務(wù)觀察 teammate 遵守阻塞順序的行為來源。認(rèn)領(lǐng)函數(shù)claim_task則通過全局_claim_lock線程鎖實(shí)現(xiàn)臨界區(qū)保護(hù)L140-L155def claim_task(task_id: int, owner: str) - str: with _claim_lock: path TASKS_DIR / ftask_{task_id}.json if not path.exists(): return fError: Task {task_id} not found task json.loads(path.read_text()) if existing_owner : task.get(owner): return fError: Task {task_id} has already been claimed by {existing_owner} if (status : task.get(status)) ! pending: return fError: Task {task_id} cannot be claimed because its status is {status} if task.get(blockedBy): return fError: Task {task_id} is blocked by other task(s) and cannot be claimed yet task[owner] owner task[status] in_progress path.write_text(json.dumps(task, indent2)) return fClaimed task #{task_id} for {owner}注意它是讀—校驗(yàn)—寫在同一把鎖內(nèi)完成多個 teammate 同時輪詢到同一個無主任務(wù)時只有第一個寫入owner的成功其余拿到 already been claimed by ... 錯誤。IDLE 輪詢中若認(rèn)領(lǐng)返回Error:前綴會continue重試下一輪L284-L286從而平滑處理認(rèn)領(lǐng)競爭。這個原子性契約在當(dāng)前軌道的測試套件 tests/test_agent_teams_runtime.py 中有專門驗(yàn)證例如并發(fā)認(rèn)領(lǐng)同一任務(wù)時只有一個 owner 成功test_inbox_delivery_is_runtime_owned、claim_task相關(guān)斷言。工作機(jī)制四上下文壓縮后的身份重注入這是 s11 獨(dú)有的一個防御性機(jī)制。當(dāng)上下文壓縮發(fā)生后messages列表會縮短teammate 可能丟失我是誰、我的角色是什么的認(rèn)知。s11 的判據(jù)非常樸素消息數(shù)小于等于 3 條即認(rèn)為發(fā)生過壓縮此時在消息列表頭部插入身份塊if len(messages) 3: messages.insert(0, identity_block)身份塊構(gòu)造邏輯見 make_identity_blockL159-L163def make_identity_block(name: str, role: str, team_name: str) - dict: return { role: user, content: fidentityYou are {name}, role: {role}, team: {team_name}. Continue your work./identity, }在實(shí)際調(diào)用點(diǎn)自動認(rèn)領(lǐng)任務(wù)恢復(fù) WORK 時L291-L295注入的是一問一答兩條消息讓角色設(shè)定以對話形式成立messages.insert(0, make_identity_block(name, role, team_name)) messages.insert(1, {role: assistant, content: fI am {name}. Continuing.})這個手法可以推廣為通用經(jīng)驗(yàn)長生命周期 agent 的關(guān)鍵狀態(tài)身份、角色約束不應(yīng)只存在于 system prompt 或?qū)υ掗_頭而應(yīng)在上下文被重寫后主動重新錨定。相對 s10 的變更清單文檔中的對照表完整如下是理解 s11 增量邊界的最快方式ComponentBefore (s10)After (s11)Tools1214 (idle, claim_task)AutonomyLead-directedSelf-organizingIdle phaseNonePoll inbox task boardTask claimingManual onlyAuto-claim unclaimed tasksIdentitySystem prompt re-injection after compressTimeoutNone60s idle - auto shutdown工具增量在源碼中可精確核對teammate 側(cè)工具池_teammate_toolsL342-L365在 s02 的四個基礎(chǔ)文件/終端工具bash、read_file、write_file、edit_file與 s09/s10 的協(xié)作工具send_message、read_inbox、shutdown_response、plan_approval之上新增idle與claim_task兩個工具lead 側(cè)分發(fā)表TOOL_HANDLERSL469-L484共 14 個條目其中 lead 調(diào)用idle會返回 Lead does not idle.lead 常駐不空閑lead 調(diào)用claim_task則把自己當(dāng)作 owner 認(rèn)領(lǐng)。新增工具輸入?yún)?shù)語義idle無聲明我手頭沒有工作了觸發(fā)進(jìn)入 IDLE 輪詢階段claim_tasktask_id: integer必填按 ID 原子認(rèn)領(lǐng)任務(wù)板上的任務(wù)運(yùn)行與驗(yàn)證運(yùn)行方式需先配置MODEL_ID等環(huán)境變量參見 requirements.txt 與 README 的 Quick Startcd learn-claude-code python agents/s11_autonomous_agents.py進(jìn)入交互 REPL 后文檔給出的 5 條驗(yàn)證路徑Create 3 tasks on the board, then spawn alice and bob. Watch them auto-claim.—— 驗(yàn)證空閑輪詢 自動認(rèn)領(lǐng)Spawn a coder teammate and let it find work from the task board itself—— 驗(yàn)證 spawn 時只給角色、不給具體任務(wù)Create tasks with dependencies. Watch teammates respect the blocked order.—— 驗(yàn)證blockedBy過濾輸入/tasks查看任務(wù)板含 owner 標(biāo)記輸入/team監(jiān)控各 teammate 處于 working 還是 idle。兩個斜杠命令的實(shí)現(xiàn)可直接閱讀/team打印TEAM.list_all()團(tuán)隊(duì)名 每個成員的名字/角色/狀態(tài)L564-L566/tasks遍歷.tasks/task_*.json用[ ]/[]/[x]標(biāo)記 pending/in_progress/completed 并附帶ownerL570-L577。團(tuán)隊(duì)狀態(tài)持久化在.team/config.json_set_status每次狀態(tài)遷移都會落盤因此進(jìn)程外也能觀察 teammate 生命周期。演進(jìn)視角當(dāng)前 17 課時軌道中的自治認(rèn)領(lǐng)需要說明的適用前提README 指出本倉庫存在兩條軌道——docs/與agents/是保留舊鏈接的Legacy 12 課時軌道根級s01_*–s17_*目錄是當(dāng)前軌道。按 Legacy-to-Current 映射表舊 s11 的autonomous task claiming并入新s13 Agent Teams。當(dāng)前實(shí)現(xiàn) s13_agent_teams/code.py 將同樣的 WORK/IDLE 思想工程化得更完整可作為進(jìn)階參照空閑掃描間隔縮短為IDLE_SCAN_INTERVAL 2.0秒L1053wait_for_work用阻塞式BUS.wait_for_messages等待消息無消息時調(diào)用claim_next_task原子認(rèn)領(lǐng)L1252-L1276認(rèn)領(lǐng)成功即以[Auto-claimed task ...]消息注入對話并附帶該任務(wù)綁定的工作目錄claim_next_task在task_lock下額外保證一個 teammate同時只持有一個任務(wù)teammate_assignments已有分配則直接返回 NoneL1070-L1079并疊加了can_start依賴檢查與 worktree 可用性校驗(yàn)L1056-L1067。從源碼結(jié)構(gòu)看兩條軌道共享同一套核心契約——scan_unclaimed_taskspending、無主、未阻塞 鎖保護(hù)的claim_task 空閑輪詢恢復(fù)——差異主要在超時策略s11 硬編碼 60s 后 shutdown新軌道把生命周期交給 lead/用戶管理和并發(fā)語義的加固。設(shè)計要點(diǎn)回顧自治不來自新工具來自循環(huán)結(jié)構(gòu)idle和claim_task只是兩個小工具真正的機(jī)制是 IDLE 階段的輪詢 → 恢復(fù)/超時狀態(tài)機(jī)文件即協(xié)調(diào)介質(zhì).tasks/*.json與.team/inbox/*.jsonl讓多個線程未來甚至多進(jìn)程通過共享磁盤狀態(tài)協(xié)作_claim_lock保證單進(jìn)程內(nèi)原子性認(rèn)領(lǐng)必須冪等且可失敗認(rèn)領(lǐng)函數(shù)返回Error:前綴的軟錯誤輪詢方以continue消化競爭失敗而不是拋異常身份是需要在壓縮后重新注入的狀態(tài)len(messages) 3是一個低成本、可解釋的壓縮探測啟發(fā)式。延伸閱讀前序文檔 s10 團(tuán)隊(duì)協(xié)議 解釋了 shutdown/plan 兩種 request-response 握手s11 的 IDLE 輪詢中同樣會響應(yīng)shutdown_request以及 s09 Agent Teams 中 MessageBus 與 teammate 持久化的基礎(chǔ)設(shè)計?!久赓M(fèi)下載鏈接】learn-claude-codeBash is all you need - A nano claude code–like 「agent harness」, built from 0 to 1項(xiàng)目地址: https://gitcode.com/GitHub_Trending/an/learn-claude-code創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考