12 KiB
多主 agent 與背景委派
瀏覽器工作面更新:預設改為 Docker 共用 Chromium;以下 owner-local profile 說明僅適用
LAZYBOY_BROWSER_SURFACE=local。目前路由與差異見 SURFACES.md。
這個模式把長期 agent 身分和一次工作 task 分開。A 可以請 B 處理工作,B 也可以另外開臨時 worker;B 原有的聊天和其他任務持續運作。主 agent 保留前景聊天,實際工具工作在背景 task 執行。
啟動與使用
先設定原本的模型環境變數,編譯後在專案目錄執行:
cargo build -p lazyboy
./target/debug/lazyboy serve
serve 是前景執行的常駐服務,請保留這個終端機(或自行交給程序管理器);聊天 CLI 斷線不會停止它。這版不安裝登入自啟服務。服務使用啟動時的模型/金鑰設定。
另一個終端機建立 agent。建立當下的工作目錄是該 agent 發起根任務的預設工作區:
./target/debug/lazyboy agents create daily
./target/debug/lazyboy agents create researcher
./target/debug/lazyboy agents list
./target/debug/lazyboy agent --name daily
再開一個終端機:
./target/debug/lazyboy agent --name researcher
名字只是識別,不會自動指定角色。透過各自聊天累積記憶與專長,例如長期在 researcher 討論資料整理。主 agent 能搜尋其他 agent 的公開專長簡介,選擇既有 agent 接單或建立臨時 worker;也可以明確說「把這件事交給 researcher」。任務內容須包含必要背景、限制與交付要求。
| 聊天內操作 | 行為 |
|---|---|
| 普通文字 | 新聊天,不會默默改掉背景工作 |
/tasks |
查看自己發起或接到的任務 |
/task <id> |
查看狀態、計畫、結果與待回答問題 |
/task <id> say <內容> |
補充這份工作;有待回答問題時,回答該問題 |
/task <id> stop |
停止這份工作及其後代 |
/task <id> resume |
明確恢復已停止任務,先觀察中斷後的狀態;沿用剩餘預算 |
/memory [查詢] |
搜尋自己的記憶,空查詢列出最近筆記 |
/memory forget <id> |
刪除指定筆記並清除衍生專長簡介;不是刪除原始聊天 |
/expertise [新簡介] |
查看或修正自己的公開專長 |
| Ctrl-C | 要求取消目前回覆;3 秒內再按一次強制離開 CLI,即使服務無回應也有效。背景 task 繼續 |
/exit、EOF |
關閉聊天連線,背景 task 繼續 |
服務未啟動時,CLI 顯示 lazyboy serve 提示。舊的 lazyboy agent、run、chat 不變,舊 session 不會自動匯入新身分。服務本身收到 Ctrl-C 時會停止工作並清理工具程序。
任務與訊息
背景 task 各有 Session、Runtime、InputBroker、計畫與命令;瀏覽器 profile 歸發起任務的主 agent 所有,跨任務及委派 worker 重用。既有 agent 接單時只使用自己的私人記憶及委派內容,不複製對方完整聊天。子 task 繼承父 task 的工作區;委派给既有 agent 也不會悄悄切到該 agent 的另一個工作目錄。
協作工具為 find_agents、search_memory、delegate_task、spawn_agent、send_message、get_task、wait_task、cancel_task。前景不提供檔案、命令、瀏覽器或等待工具,交辦後就能回答下一則聊天。背景沿用原有 28 個工具並加入協作工具。
每個 task 只有一個 parent。同一任務樹可互傳訊息、讀取任務摘要;等待只允許等待後代,取消只允許自己及後代,避免循環等待和誤停兄弟任務。主聊天可管理它發起或接到的 task。send_message 不啟動新 task;後續交辦建立新的 task。
訊息先寫入 SQLite,在模型/工具邊界加入 task 對話,checkpoint 後才標記送達;已寫進對話但尚未標記的訊息以 ID 去重。定向插話不撤銷已開始的工具,會跳過同批尚未執行的操作。人工回答有獨立的 user 來源,peer 訊息與子任務回報不能直接充當人工確認。
終態結果與通知排程在同一筆 transaction 保存。子結果送到父 task 信箱;根結果在原主 agent 的對話排入整合回覆,並提供持久化事件。CLI 用遞增事件 ID 拉取及確認,斷線重連讀取尚未確認的事件。完成宣告仍是模型根據證據的判斷,不是對所有任務的正確性保證。
卡住時選擇其他路線
某一段工作卡住時,agent 應說明已嘗試的方法,透過 report_blocked 的 options 提供具體替代路線。例如「由我處理目前視窗的登入」或「先寫不需要登入的文案」,加上停止選項。有互動輸入時會停在選擇點,選擇後更新計畫並沿用原 task;沒有互動輸入時才直接回報 blocked。選項可用數字、a/b/c 或自由文字回答。
browser_handoff 會把同一個 task 的瀏覽器交給你。已可見的視窗直接帶到前景;原本隱藏時,重開同一份 profile,恢復頁籤、cookies、localStorage 與目前頁籤的 sessionStorage。請在工具開出的視窗操作;另外開啟的一般 Chrome 視窗不會自動共用這份狀態。視窗切換可能重新載入網頁,仍需觀察當下狀態。
handoff 提供「已完成登入,請檢查」、「登入仍失敗,改做其他部分」與停止等選項。選擇其他路線保留原 task/profile,不宣告登入成功。人工交回控制權後,模型必須檢查頁面才能判斷登入是否成功。中斷後恢復 handoff 時,會先打開原頁面再詢問。
在 named-agent CLI,用畫面提供的 /task <id> say <選項> 回答。硬性預算上限與無進展保護仍有效,不會因選擇替代方案而自動補預算。若已到終態,查看 /task <id> 並明確恢復原 task,避免換一個 worker 卻以為登入狀態會跟過去。
預算與資源
- 最多 4 個並行模型請求;背景任務及記憶整理合計最多 2 個,保留前景聊天容量。等待工具、等待子 task 或人工回答都不持有模型額度。
- 每棵根任務樹最多 8 個 task(含根),根深度 0,最多委派到深度 2。禁止委派回任務祖先的 agent;另一棵獨立任務仍可反向合作。
- 根任務樹共用
LAZYBOY_MAX_ROUNDS_TOTAL,預設 48;最後 4 次只供根任務使用。子 task 的請求也計入根計數,不會開一個 agent 就多拿 48 次。恢復不自動補預算;耗盡時需另開有明確範圍的新工作。 - 前景每次回覆最多 12 次模型請求。每個完成聊天回合/持久 agent 的任務最多再排一次記憶整理,失敗不阻擋聊天、不自動重試。這些與根任務執行預算分開計算。
- 同一 canonical 工作區內的工具操作互斥;長指令退出後才釋放鎖。操作不同工作區可並行。活躍指令須先結束或終止,才能等待子 task 或人工回答,避免拿著鎖等待別人工作。
- 每個長期 named agent 有自己的 Docker 電腦(容器、
/workspace、Chromium profile)。開這個 agent 會啟動它的座位並確認桌面就緒。同一 owner 的背景 task 與 computerUse 子 agent 用這台電腦;delegate_task給另一個 named agent 時改用被交辦者的電腦;臨時spawn_agentworker 用發起任務的 owner 座位。同時只有一個 task 持有該座位的瀏覽器,handoff 等待期間也不讓其他 worker 操作同一座位。browser_release或任務結束會關閉瀏覽器並釋放使用權,保留登入資料。委派瀏覽器子任務前先 release,避免互等。 - 升級首次使用時,固定 profile 優先連結至仍有 handoff 問題的舊 task profile,否則採該主 agent 最近使用的 profile,保留原資料,不合併不同 profile 的登入帳號。沒有舊 profile 才建立新的。一般 Chrome 的登入狀態不會自動匯入。
task 使用 queued、running、waiting_input、terminal 狀態;終態另有 done/answer/blocked/budget_exhausted/failed/cancelled/interrupted。停止執行中的 task 先提出取消,工具清理後才進 terminal。沒有連線的人工問題仍保持等待,只有明確回答或停止才繼續。
保存、恢復與記憶
預設資料在 ~/.lazyboy/team/,可用 LAZYBOY_DATA_DIR 改位置。目錄權限 0700、Unix socket 0600,程序鎖保證同一資料目錄只有一個 daemon 寫入。SQLite WAL 保存身分、原始對話、tasks、訊息、事件、client cursor 和記憶整理佇列;profiles 也存於該資料目錄。API key 不存入資料庫。
daemon 重啟後,未開始的 queued 工作保留;曾經 running 或 waiting_input 的 task 標示 interrupted,未知工具结果補齊,不自動重播。已開始的前景回覆及記憶整理也不自動重送模型。由 /task <id> resume 明確恢復;若父 task 也中斷,先恢復父 task。強制殺死服務可能留下未知外部效果,恢復時須重新觀察,不能假設操作沒發生。
記憶有來源、時間、類型及 supersedes 關係。使用者陳述、模型推論和工具實際觀察分開記錄;模型的完成摘要不會自動升格為工具驗證。專長只應包含一般領域與經驗,透過模型自動歸納,可能需使用 /expertise 修正。檢索用本機 SQLite FTS5,另有字串比對支援短中文詞,不需要 embedding 或搜尋 API。
前景模型只帶最近 20 個使用者訊息起始的對話段落及目前任務登記表;完整歷史仍保存,較早經驗透過私人記憶搜尋取回。刪筆記不等於刪聊天,未來若重新討論相同內容可能再次形成記憶。
隔離是應用層的記憶存取規則;shell 仍有本機使用者權限,不是 agent 間的 OS 安全沙箱。這版限定同機同使用者,不提供網路服務、跨電腦或其他產品協定。
驗證與參考
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo build -p lazyboy
python3 tests/team_flow.py # 本機 mock API、兩個 CLI、真實 Chromium
python3 tests/live_team.py # opt-in:目前付費模型,背景根任務最多 16 次請求
整合涵蓋專長歸納、私人記憶、既有 agent 接單、巢狀子 task、兩個前景對話、產物讀回、定向插話、人工等待、斷線重連、程序取消、瀏覽器隔離與 daemon 崩潰恢復。單元測試驗證循環、深度/數量/預算、回報去重與存取邊界。
參考 Codex 協作工具原始碼、agent 建立與恢復、官方 subagents 說明。借用委派、信箱、等待與回報概念;多主身分、私人記憶和本機 daemon 是本專案的實作。
主聊天中回覆「登入了」等待接手問題時,主 agent 使用 answer_task 轉送這一輪使用者原話;背景報告及 worker 不能假冒人類回答。多個問題指向不明時先釐清。send_message 是 agent 訊息,不能解除人類等待。舊快照不能用來判定人類操作後的登入狀態,必須由 worker 重新觀察。明確指定回覆仍可用 /task <id> say <內容>。
延續前次委派
delegate_task/spawn_agent 可指定 continue_from(已結束的 task ID)。runtime 自動附上前次目標、結果與工具證據、計畫、工作區、瀏覽器 URL 以及未解問題/未知操作,並保存來源關聯。接手者可用 get_task 讀取來源鏈的公開報告;不複製私人對話或記憶。新任務重新規劃與驗證現況,不繼承操作授權或重播未知工具。仍執行中的工作用訊息調整;等待人類回答時用 answer_task。不同 owner 或無關 task tree 不能借此讀取任務。