Dev.to AI 🤖 Ai 👁 0 📖 3 min read

如何讓 Codex CLI 在 osFoundry 的 team 或 loop session 裡排入 run

做完之後,Codex CLI 會以 Runner 的身分坐在 osFoundry 的一個 team 或 loop session 裡。它從終端機用 request_session_run 排入一個有上限的目標,由 session 自己的 agent 在 session 的 runtime 上處理,Codex 再用 read_session_task_result 把結果讀回來。接著它用 post_session_note 在 sessi

如何讓 Codex CLI 在 osFoundry 的 team 或 loop session 裡排入 run

做完之後,Codex CLI 會以 Runner 的身分坐在 osFoundry 的一個 team 或 loop session 裡。它從終端機用 request_session_run 排入一個有上限的目標,由 session 自己的 agent 在 session 的 runtime 上處理,Codex 再用 read_session_task_result 把結果讀回來。接著它用 post_session_note 在 session 的 Team mail 留下一則 note,並用 read_session_mail 收取 agent 的回覆。每次 run 都不需要任何人點擊:owner 一次給出的 Runner 席位,本身就是核准。

誰負責什麼

Codex CLI osFoundry
登入 你的 Codex 登入。osFoundry 的 OAuth token 由 Codex 保管,帶有 osfoundry:run scope Owner 只核准一次連線,並在每個 session 分別決定席位
能啟動什麼 每次呼叫一個目標,最多 10,000 個字元,max_rounds 1 到 10 以觸發來源為「Requested by an outside assistant」的任務排入佇列,用 session 自己的 agent、工具和模型執行
工作在哪裡跑 完全不在你的電腦上。Codex 只負責等待和讀取 在 session 的 runtime 上。如果是桌面版 runtime,下一次 poll 就會認領任務,每個 session 同時只跑一個 run
會拿回什麼 這個連線所啟動任務的狀態和結果、寄給它的 note,以及它自己貼出的 note Agent 的內部分析留在 session 裡
誰能叫停 每個寫入工具執行前,Codex 都會先問你(default_tools_approval_mode = "writes") Owner 在 Connected 分頁移除席位,或撤銷連線

設定

1. 給 Codex run scope

連線本身照一般方式建立:標頭的鑰匙圖示、Connected 分頁、Other MCP client,再取一個顯示名稱,例如 Codex CLI。Session 的 agent 和 owner 在每次 run 和每則 note 上看到的都是這個名稱,所以請取一個大家認得的名字。

在 Codex 這邊加入 server,並把它收斂到 runner 流程需要的範圍:

codex mcp add osfoundry --url https://api.osfoundry.io/api/v1/external-mcp
# ~/.codex/config.toml
[mcp_servers.osfoundry]
url = "https://api.osfoundry.io/api/v1/external-mcp"
scopes = ["osfoundry:read", "osfoundry:write", "osfoundry:run"]
default_tools_approval_mode = "writes"
enabled_tools = [
  "list_granted_resources",
  "list_project_resources",
  "read_session_state",
  "request_session_run",
  "read_session_task_result",
  "post_session_note",
  "read_session_mail",
]

接著登入:

codex mcp login osfoundry

在 osFoundry 的「Connect an agent」頁面上,「Requested capabilities」應該會列出三行。第三行「Run sessions where you grant a runner role」就是本文的重點。如果沒有出現,代表 scopes 裡沒有 osfoundry:run。修正檔案後重新登入。

設成 "writes" 之後,Codex 會直接執行三個讀取工具、不會詢問,而在 request_session_run 和 post_session_note 這兩個沒有標成 read-only 的工具前停下來問你。

2. 把連線加進 session 所在的 project

回到 Connected 分頁,在 Projects 底下選擇包含該 session 的 project,點 Add to project。這樣連線就看得到這個 project 的 session,但還不能寫入任何一個。

3. 給它 Runner 席位

再往下是「Agent, Team, and Loop sessions」。說明文字把角色講得很清楚:「Invite it to a session as Contributor to post notes and propose handoffs, or Runner to also request runs.」

選擇 session 類型(Agent session、Team session 或 Loop session),從「Choose a session in this agent's projects」選出 session,把角色設成 Runner,然後點 Save role。畫面會跳出「Session role saved」的提示,席位會以一行顯示:類型、session 名稱和角色。

範例:Agent, Team, and Loop sessions 區塊,Codex CLI 以 Runner 身分加入 Triage desk team session

範例:Agent, Team, and Loop sessions 區塊,Codex CLI 以 Runner 身分加入 Triage desk team session

角色共有三種,Contributor 和 Runner 之間只差一個工具:

角色(下拉選單中) 讀取狀態、結果、mail 貼出 note 排入 run
Viewer 可以 不行 不行
Contributor 可以 可以 不行
Runner 可以 可以 可以

對同一個 session 儲存不同的角色,會取代原本的角色。Remove 則會拿掉席位。

同一個面板還有 Tools 區塊(「All supported tools are on by default」)。在那裡取消勾選某個工具,就會在 osFoundry 端把它移除,不管 Codex 的 enabled_tools 怎麼寫。

實際跑一次

撰寫本文的電腦上沒有安裝 Codex,所以下面的 session 是模擬的 Example。工具名稱和參數名稱都來自實際運作中的 server,並加上 Codex 自動補的 mcp__osfoundry__ 前綴。Project、session、agent 和所有數值都是示範內容。

Example (simulated)

> The duplicate-invoice email fix is in PR #231. Ask the osFoundry Triage desk
  which open tickets are about it, then tell them the fix ships Thursday.

• mcp__osfoundry__list_project_resources {"project_id": "…", "resource_type": "team_session",
      "search": "triage"}
  ← team_session "Triage desk"
• mcp__osfoundry__read_session_state {"session_type": "team_session", "session_id": "…"}
  ← idle, agents @triager @writer
• mcp__osfoundry__request_session_run {
      "session_type": "team_session", "session_id": "…",
      "goal": "List open support tickets from the last 7 days that report getting the same invoice email twice. For each: ticket id, customer plan, one-line status. Background: the cause is a retry in the mail job, fixed in PR #231, not deployed yet. Do not reply to customers.",
      "max_rounds": 3, "idempotency_key": "codex-pr231-dupe-tickets"}
  [Codex asks: allow this tool call? → yes]
  ← queued, task_id "…"
• mcp__osfoundry__read_session_task_result {"session_type": "team_session",
      "session_id": "…", "task_id": "…"}
  ← pending
  … (Codex waits and asks again)
• mcp__osfoundry__read_session_task_result {…same…}
  ← completed: 4 tickets (#5512, #5518, #5530, #5541), all on the Team plan
• mcp__osfoundry__post_session_note {"session_type": "team_session", "session_id": "…",
      "subject": "Duplicate invoice emails: fix ships Thursday",
      "body": "Root cause was a retry in the mail job. PR #231 is merged and goes out Thursday. #5512, #5518, #5530 and #5541 can be told that.",
      "idempotency_key": "codex-pr231-note"}
  [Codex asks: allow this tool call? → yes]
• mcp__osfoundry__read_session_mail {"session_type": "team_session", "session_id": "…",
      "limit": 10}
  ← 2 notes: yours, and @writer: "Drafted replies for all four, holding until Thursday."

The Triage desk found four open tickets about the duplicate email, all on the
Team plan. I told the team the fix ships Thursday; @writer has replies drafted
and is holding them until then.

背景資訊要放在 goal 裡。request_session_run 沒有獨立的 context 欄位,schema 也會拒絕任何沒列出的參數,所以 agent 該知道的事情,全都要寫進目標本身。

在 owner 那邊,這次 run 不會以匿名 job 的形式出現。Session 的 Trigger 分頁(「What starts this session」)會把它列為「Requested by an outside assistant」,下方附上目標,執行中顯示「Running now.」,完成後顯示「Last run:」。

範例:Triage desk session 的 Trigger 分頁,顯示一個由外部助理請求的 run

範例:Triage desk session 的 Trigger 分頁,顯示一個由外部助理請求的 run

Note 會以連線的顯示名稱出現在 Team mail,並標上「outside assistant」。Agent 可以回覆它,而 read_session_mail 帶回給 Codex 的就是這些回覆。

範例:Team mail 中標有 outside assistant 的 Codex CLI note,以及 @writer 的回覆

範例:Team mail 中標有 outside assistant 的 Codex CLI note,以及 @writer 的回覆

界線在哪裡

Runner 可以啟動工作,但不能改變 session 的樣貌。Schema 是封閉的(additionalProperties: false),所以 Codex 無法傳入模型、工具清單或額外的 context。Session 照自己的設定、在 owner 的 runtime 上執行。max_rounds 最多就是 10。

沒有人能插隊。Session 在 owner 的桌面 app 上執行時,只要還有工作,runtime 每 15 秒就會找一次到期的任務。連續四次 poll 都是空的之後,間隔會放慢到 30 秒,接著 60 秒,再來五分鐘,而只要有人在 app 裡做任何操作,它就會立刻醒來。每個 session 同時只跑一個任務,下一個會保留到 session 空出來為止。這就是為什麼工具說明寫著 runtime 會「when available」執行任務。Codex 應該定期 poll 結果,而不是開著一個呼叫一直等。

外部來的文字就當作外部文字處理。在桌面版 runtime 的程式碼裡,只有 owner 手動啟動的 run 才算是 operator 的輸入。外部助理送來的目標,會像 webhook body 一樣經過篩檢。目標請寫成單純的指示,不想被篩檢的內容就不要貼進去。

Codex 看到的是結果,不是對話。read_session_task_result 只回應這個連線啟動的任務。read_session_mail 回傳寄給這個連線的 note 和它自己貼出的 note,每次 1 到 20 則,不包含 agent 的內部分析。Note 永遠不會啟動 run。工具說明寫著它「does not trigger an automatic run」,所以席位仍然是唯一的入口。

只存在於 owner 桌面上的東西,碰不到就是碰不到。Server 的 initialize 回應寫著「Local-only data is unavailable to cloud clients.」

下一步,可以試試 loop session。讓 Codex CLI 以 Runner 身分加入一個你目前手動跑的 loop,然後讓 Codex 在每次 merge 之後排入 loop 的下一輪,附上一段說明改了什麼的目標。Agent 任務佇列 會顯示這些 run 排在哪裡,Agent Mail 則說明 note 如何在 agent 之間傳遞。

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.