Theme / v4.19.4

Oh My OpenAgent

AI 代理編排系統

實戰範例

實戰範例 009:第一次啟動 Team Mode,用 Sisyphus 與 Athena 平行交付一個小工具函式

新手嚮導式範例。從安裝 Oh My OpenAgent 開始,第一次啟動 Team Mode,讓 Sisyphus 實作 formatPrice 工具函式、Athena 同步寫單元測試,見識 Hash-Anchored Edit 如何在共用型別檔上防衝突。

實戰背景

這個範例寫給第一次接觸 Oh My OpenAgent (OMO) 的開發者。我們刻意把需求縮到最小,讓你可以把注意力全部放在「多代理協同到底怎麼運作」這件事上,而不是被業務邏輯干擾。

痛點與問題描述

我們在一個電商 side project 裡,需要新增一個 formatPrice 工具函式。規格很單純:

  • 輸入:金額(以整數 cents 表示)與幣別代碼(如 TWDUSD)。
  • 輸出:人類可讀的顯示字串,例如 formatPrice(1299, "TWD") 應回傳 "NT$12.99"

如果走傳統流程,你會先打開 src/utils/format.ts 寫完函式,等編譯通過後再切到 tests/utils/format.test.ts 補測試。開發與測試是兩個分開的步驟。

OMO 給的另一條路是:把實作與測試丟給兩個並行的代理,讓它們在同一個 worktree 內各自推進。本範例就帶你走完這條路。


安裝與環境確認

第一次使用,依照 theme.yaml 提供的官方指令安裝(任選一個平台):

# OpenCode 平台
bunx oh-my-openagent install

# Codex CLI 平台
npx lazycodex-ai install

# 同時安裝到兩個平台
bunx oh-my-openagent install --platform=both

安裝完成後,OMO 會自動掛載 11 個內建專業代理與相關 MCP(包含 Exa、Context7、Grep.app 等),並把命令註冊進你的 CLI。


端到端 6 輪 AI 協作紀錄

以下是 You 與 OMO 之間的第一次協作歷程。

── 第 1 輪:用 explore 描述需求 ──

  • You:
    /opsx:explore "我需要新增 formatPrice(cents, currency) 工具函式,並配齊單元測試。請幫我用 OMO Team Mode 平行交付。"
  • AI:

    收到。這個任務結構很適合 Team Mode 雙代理平行交付。

    我規劃的分工是:

    1. Sisyphussrc/utils/format.ts 實作 formatPrice
    2. Athenatests/utils/format.test.ts 平行撰寫單元測試。
    3. 兩邊會共用 src/types/money.ts 的型別定義,我會自動啟用 Hash-Anchored Edit 保護這個檔案。

    準備好就可以啟動 Team Mode。

── 第 2 輪:第一次啟動 Team Mode ──

  • You:
    啟動 Team Mode,指派 Sisyphus 實作、Athena 寫測試,開兩個 worker。
  • AI:

    [OMO] Team Mode Initialized

    已在背景啟動兩個 worker:

    1. Worker: impl 指派 Sisyphus,負責 src/utils/format.ts
    2. Worker: tests 指派 Athena,負責 tests/utils/format.test.ts

    兩個 worker 的 context 完全隔離,不會互相污染。共用檔案 src/types/money.ts 已加上 Hash-Anchored Edit 控制器。

第一次啟動 Team Mode 時,你會注意到 OMO 沒有要求你手動建立分支或 worktree,背景的 Git Worktree 配置是自動完成的。

── 第 3 輪:觀察 Sisyphus 的實作 ──

  • You:
    報告一下 Sisyphus 目前的進度。
  • AI:

    Sisyphus 已完成兩件事:

    1. 在共用檔 src/types/money.ts 加上 Currency 型別:
      export type Currency = "TWD" | "USD" | "JPY";
    2. src/utils/format.ts 實作主邏輯:
      import type { Currency } from "../types/money";
      
      const SYMBOLS: Record<Currency, string> = {
        TWD: "NT$",
        USD: "$",
        JPY: "¥",
      };
      
      export function formatPrice(cents: number, currency: Currency): string {
        if (cents < 0) throw new RangeError("cents must be non-negative");
        const symbol = SYMBOLS[currency];
        const divisor = currency === "JPY" ? 1 : 100;
        const value = (cents / divisor).toFixed(divisor === 1 ? 0 : 2);
        return `${symbol}${value}`;
      }

    Sisyphus 已提交本輪變更,等待 Athena 的測試對齊。

── 第 4 輪:Athena 平行寫測試,遇 Hash 鎖排隊 ──

  • You:
    Athena 在寫測試時,如果也想動到 money.ts 會怎樣?
  • AI:

    這正是 Hash-Anchored Edit 的價值所在。

    目前 Hash-Anchored Edit 的鎖定狀態顯示:

    • 共用檔 src/types/money.tsWorker: impl (Sisyphus) 持有錨定鎖(鎖定第 1 到 3 行)。

    Athena 原本想把 Currency 加上一個 EUR 列舉值,但偵測到 Sisyphus 還在持有這個區塊的雜湊鎖,於是自動進入 queue 等待,不會強行覆蓋。等 Sisyphus 釋放鎖後,OMO 會通知 Athena 重新嘗試,或讓 Sisyphus 直接補上 EUR

    Athena 於是先在 tests/utils/format.test.ts 完成主測試:

    import { formatPrice } from "../../src/utils/format";
    
    test("formats TWD cents to display string", () => {
      expect(formatPrice(1299, "TWD")).toBe("NT$12.99");
    });
    
    test("JPY has no decimal places", () => {
      expect(formatPrice(1500, "JPY")).toBe("¥1500");
    });
    
    test("rejects negative cents", () => {
      expect(() => formatPrice(-1, "USD")).toThrow(RangeError);
    });

── 第 5 輪:合併與執行測試 ──

  • You:
    合併兩個 worker 的成果,然後跑單元測試。
  • AI:

    Implementing: omo-beginner-formatprice

    我已把兩個 worker 的變更合併回主分支。因為編輯期間全程使用 Hash-Anchored Edit 的區塊雜湊鎖,這次合併零衝突、所有錨定鎖均已釋放。

    接著執行單元測試:

    ✔ formatPrice - formats TWD cents to display string (3ms)
    ✔ formatPrice - JPY has no decimal places (1ms)
    ✔ formatPrice - rejects negative cents (1ms)
    Tests: 3 passed, 3 total.

── 第 6 輪:歸檔與清理 ──

  • You:
    收尾,順便告訴我這次小任務花了多少時間。
  • AI:

    已執行驗證、合併主規格、關閉背景 worktree 與 tmux pane。

    Archive Complete

    計畫 omo-beginner-formatprice 已歸檔。

    本次耗時約 7 分鐘(含安裝)。如果之後同類型的小工具函式變多,你可以一次把 Team Mode 開到 8 個 worker(Team Mode 的上限),讓多組 Sisyphus 與 Athena 平行交付。


關鍵學習點

  • 第一次跑 Team Mode,最小的可運作單位就是兩個代理:一個負責實作、一個負責測試。不需要一開始就湊齊 11 個代理。
  • Hash-Anchored Edit 在共用型別檔上特別有感。即使只動 src/types/money.ts 一個檔案,鎖機制也會防止兩個 worker 同時改同一個區塊。
  • 新手的第一個平行任務,只需要「啟動 Team Mode」與「合併成果」兩個動作,先記住這兩步就足以走完第一個平行任務。
  • 新手不必先學 OpenSpec。本範例直接用 /opsx:explore 描述需求就能開工,OpenSpec 的規格撰寫可以等任務規模變大後再引入。