iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
AI 自動化

AI 公司模擬器:Discord x Multi-Agent 架構實作系列 第 16 篇

DAY 16|完成第一輪討論,讓四位 Agent 依序發言

  • 分享至 

  • xImage
  •  

DAY 15 建立了 MeetingManager,Python 已經能依固定順序呼叫 Agent,也會保存每一步的輸入、輸出與狀態。不過,當時還沒有接到 Discord,使用者看不到背景執行的結果。

今天把 /start 接上 Meeting Manager。PM、Research、Creative 與 Finance 會依序執行,每完成一位 Agent,就把進度和結果送到 Discord。Review Agent 暫時不加入,因為第一輪還沒有整合後的草案可以審查。

今天完成的內容

  • 新增只執行四位 Agent 的 start_first_round()
  • 用 callback 將每一步結果交回 Discord
  • 在 /start 顯示 1/4 到 4/4
  • 將結構化輸出轉成可閱讀的 JSON
  • 訊息超過長度時自動分段
  • 使用 Fake Agent 與 Fake Discord Interaction 測試流程

第一輪有哪些角色?

完整會議有五位 Agent,第一輪先執行前四位:

1/4 PM:拆解專案需求
2/4 Research:整理資訊與待查證項目
3/4 Creative:提出創意方案
4/4 Finance:評估成本與風險

這次沒有另外建立一套會議模型,而是沿用 DAY 15 的 MeetingRecord,建立紀錄後只保留前四個步驟:

if first_round_only:
    record.steps = record.steps[:4]

因此原本的狀態保存、Guild Lock 與錯誤處理都能繼續使用,不需要在 Discord 指令中重寫流程。

用 callback 回報執行進度

MeetingManager 不應該直接依賴 Discord。它只負責執行 Agent,至於結果要顯示成純文字、Embed 或其他格式,應由外層決定。

我先定義 callback:

MeetingStepCallback = Callable[
    [int, int, MeetingStepRecord],
    Awaitable[None],
]

三個參數分別代表目前進度、總步驟數,以及這次完成的會議步驟。每位 Agent 回答後,程式會先保存資料,再執行 callback:

response = await agent.respond(step.input_text)
step.output_data = response.model_dump(mode="json")
step.status = MeetingStepStatus.COMPLETED
self._save(record)

if on_step is not None:
    await on_step(index + 1, total_steps, step)

先保存再傳送有一個好處:即使 Discord 發訊息時失敗,已經完成的 Agent 結果仍會留在 meetings.json。

/start 接上第一輪討論

原本 /start 只會把專案改成進行中,現在則會接著呼叫 start_first_round():

輸入 /start
    ↓
啟動專案並顯示會議資訊
    ↓
依序執行四位 Agent
    ↓
每完成一步就傳送 Followup
    ↓
顯示「第一輪討論完成」

本機模型需要時間推論,所以指令開始時先使用:

await interaction.response.defer(thinking=True)

defer() 先告訴 Discord 已收到指令,後面的進度再透過 interaction.followup.send() 傳送。會議內容要讓伺服器成員看見,因此不使用私密回覆;如果在私訊執行 /start,才會用 ephemeral=True 顯示錯誤。

Discord 層提供的 callback 會把結構化輸出交給格式化函式,再逐段送出:

async def display_agent_step(current, total, step):
    messages = format_discussion_messages(
        step.agent_name,
        current,
        total,
        step.output_data or {},
        max_length=settings.max_meeting_message_length,
    )

    for message in messages:
        await interaction.followup.send(message)

第一輪如何傳遞資料?

PM 先收到原始需求,後面的 Agent 則會取得前面已完成的結構化輸出:

PM       → 原始需求
Research → 原始需求 + PM 結果
Creative → 原始需求 + PM、Research 結果
Finance  → 原始需求 + PM、Research、Creative 結果

這個版本先確認資料能依序傳遞,還沒有篩選欄位。下一篇再建立共享會議內容,避免後面的 Agent 收到太多不相關資料。

將結構化輸出顯示在 Discord

四位 Agent 的 Pydantic Model 欄位不同。為了先確認資料是否完整,這一版直接把 output_data 轉成有縮排的 JSON:

body = json.dumps(
    output_data,
    ensure_ascii=False,
    indent=2,
)

ensure_ascii=False 讓中文維持原樣,indent=2 讓巢狀資料比較容易閱讀。這仍是偏向除錯用途的畫面,等欄位穩定後再改成 Embed 或條列式重點。

為什麼訊息限制在 1900 字?

Discord 一般訊息的 content 上限是 2000 字元。專案將每段限制在 1900 字,替進度標題與「(續)」保留空間:

max_meeting_message_length: int = 1900

split_discord_message() 會優先在換行處分段;沒有合適的換行時,才依字元上限切開。第二段之後會補上「(續)」,避免被看成下一位 Agent 的回覆。

  1. 輸入 /start PRJ-003 後,Discord 顯示專案會議已啟動。
    https://ithelp.ithome.com.tw/upload/images/20260930/20183880WqVaqwQwh8.png

  2. 頻道依序出現 1/4 到 4/4,最後顯示第一輪討論完成。
    https://ithelp.ithome.com.tw/upload/images/20260930/20183880EFNvpPRSBt.pnghttps://ithelp.ithome.com.tw/upload/images/20260930/20183880K0uqDanvBw.pnghttps://ithelp.ithome.com.tw/upload/images/20260930/20183880wFYkMQQFbK.pnghttps://ithelp.ithome.com.tw/upload/images/20260930/20183880m6AVHzFcZK.pnghttps://ithelp.ithome.com.tw/upload/images/20260930/20183880QCPEDFm9vB.png

目前的 JSON 畫面還不算美觀,但已經能直接看到每一位 Agent 的執行進度與結果。

今天的成果

DAY 15 的 Meeting Manager 已經接到 Discord /start。第一輪會依序執行 PM、Research、Creative 與 Finance,每一步完成後先保存結果,再透過 callback 顯示到頻道;內容過長時也會自動分段。

下一篇會整理 Agent 之間的共享內容,只保留下一位角色真正需要的前文。


上一篇
DAY 15|建立 Meeting Manager
下一篇
DAY 17|建立共享會議內容,讓 Agent 接得上前面的討論
系列文
AI 公司模擬器:Discord x Multi-Agent 架構實作 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言