前幾篇一路看過 Codex、Claude Code、OpenClaw,也看過 Hindsight、ai-memory 這類 Memory 工具,但如果真的把 Coding Agent 放進團隊裡,另一個更實際的問題:
每個人用不同 Agent,怎麼還能維持同一套工作方式?
假設現在有三個工程師一起維護航空客服 Agent:
Alice → Claude Code
Bob → Codex
Carol → Cursor
Alice 寫了一個 cancel-ticket Skill,Bob 發現取消 API 有一個容易踩到的限制,Carol 又新增了一個航空訂位 MCP。
如果沒有額外管理,很容易最後變成:
Claude Code 有一套 Skill
Codex 有另一套 Rule
Cursor 又有自己的 MCP 設定
Alice 知道的問題
Bob 不知道
某條 SOP 改了
每個人再各自更新一次
Tencent/teamai-cli 想解的就是這件事。
它比較像放在這些 Coding Agent 上面的一層:
Team Repo
│
Skill / Rule / Agent / MCP
Docs / Learnings / Hooks
│
TeamAI
sync / render
↙ ↓ ↘
Claude Code Codex Cursor
也就是:
Agent 還是各自執行,但團隊共同使用的能力與知識,由 TeamAI 統一管理。
官方把這件事分成三層:
| TeamAI Layer | 白話來說 |
|---|---|
| Team Execution | 大家的 Agent 要怎麼工作 |
| Team Context | 大家的 Agent 要知道什麼 |
| Team Improvement | 一個人的經驗怎麼改善整個 Team |
接下來就從這三件事看 TeamAI 的設計。
TeamAI 比較特別的是,它希望 Team Repo 可以保存的是整套 Agent 工作環境:
skills/
rules/
docs/
agents/
hooks/
mcp/
models/
learnings/
teamwiki/
例如航空客服 Team 可以有:
skills/
change-flight/
cancel-ticket/
rules/
customer-confirmation.md
agents/
fare-reviewer.yaml
mcp/
mcp.yaml
learnings/
...
teamwiki/
...
這裡每一種東西負責的事情不同。
skills/ 是可以反覆執行的能力,例如改票流程;rules/ 是每次都應該遵守的要求,例如改票前必須再次確認乘客;agents/ 可以放團隊共用的 Reviewer Agent;mcp/ 則定義大家要使用哪些外部工具。
所以 TeamAI 共享的不是單一 Prompt,而是一整套 Team Harness。
但這裡馬上會碰到一個問題,Claude Code 和 Codex 的設定格式根本不一樣。
Claude Code 可能讀:
.claude/skills
.claude/rules
.claude/settings.json
.claude/CLAUDE.md
.claude/agents
Codex 則使用:
.codex/skills
.codex/rules
.codex/hooks.json
.codex/agents
.codex/config.toml
TeamAI 是在中間做 Adapter,相關設定直接放在:src/types.ts,裡面的 toolPaths 會定義各 Agent Harness 真正使用的位置。
Team Definition
│
TeamAI Adapter
┌─────────┼─────────┐
↓ ↓ ↓
Claude Codex Cursor
format format format
Agent definition 也有同樣的概念。
src/builtin-agents.ts 會根據不同 Tool Render 成對方原生可以理解的格式,例如 Codex Agent 可以輸出成 .toml,Claude 類工具則使用 Markdown。
這是 TeamAI 第一個很重要的設計:
團隊共享的是「能力定義」,TeamAI 再負責適配不同 Agent Harness。
第一次加入 Team 時,可以執行:
teamai init <team-repo> --agent claude,codex
--agent 表示這台機器要替哪些 Coding Agent 準備資源。
平常修改 Skill、Rule 或 Agent 後,可以:
Developer 修改資源
↓
teamai push
↓
建立 Branch / PR / MR
↓
Review
↓
Merge 到 Team Repo
其他人下次開 Agent 時,SessionStart Hook 會執行:
SessionStart
↓
teamai pull
↓
抓最新 Team Repo
↓
轉成各 Agent 原生格式
因此 Admin 如果修改:
rules/customer-confirmation.md
Alice 下次開 Claude Code,Bob 下次開 Codex,都會取得同一版規則。
這裡也能看出 TeamAI 和 OpenClaw 這類 Multi-Agent 系統的差異。
OpenClaw 比較像:
Agent A
↓ delegate
Agent B
TeamAI 則是:
Alice / Claude Code
↓
Team Repo
↓
Bob / Codex
Carol / Cursor
它是讓不同人、不同工具、不同時間的 Agent 都使用同一套 Team Harness。
如果公司只有三個人、一個專案,把所有 Skill 和 Knowledge 全部同步給大家或許還沒問題。
但實際上很快會出現:
航空客服
信用卡客服
內部 DevOps
資料平台
如果所有 Memory、Rule、Skill 全混在一起,反而會造成 Context Pollution。
TeamAI 因此提供兩個不同維度:
Project
+
Role
Project 代表:
我現在在哪個產品或專案工作?
Role 則代表:
我在這個 Team 裡負責什麼?
例如公司有:
Project:
flight
credit-card
Role:
developer
support
reviewer
航空客服專案可以在 manifest/projects.yaml 定義:
projects:
- id: flight
resources:
knowledge: [flight]
skills: [flight]
learnings: [flight]
agents: [flight]
工程師進入航空客服 Repo 時:
teamai init <team-repo> --project flight
這個工作目錄之後就只會同步 flight 相關資源。
Learning 也是一樣。
learnings/
代表整個 Team 都可以使用的共通知識。
而:
learnings/flight/
只提供給 flight project。
因此可以形成:
Alice / Claude Code ──┐
├─ flight
Bob / Codex ──────────┘
Carol / Cursor ───────── credit-card
三個人仍然使用同一個 Team Repo,但不需要把完全不相關的知識全部塞給彼此。
Role 則再往下控制:
developer
reviewer
support
需要哪些 Skill 或 Knowledge。
所以 TeamAI 的 Multi-user 是:
同一個 Team Repo 裡,把共享資源按照 Project 與 Role 分配給真正需要的人。
這個設計其實比「每個 User 各自準備一份 CLAUDE.md」更接近真正團隊環境。
前面的 Team Execution 解決的是「大家使用同一套 Skill、Rule、Agent、MCP」,Team Context 則處理另一個問題:Alice 已經花一小時解掉的問題,Bob 明天換成 Codex 時,能不能直接用到這段經驗。
Team Context 會搜尋的資料包含:
Learnings
Docs
Rules
Skills
TeamWiki
Codebase Graph
其中 learnings/ 最接近長期 Memory,但 TeamAI 不會把每段 Conversation 都直接存進去,而是先找「這次 Session 是否真的有值得留下來的經驗」。
假設 Alice 用 Claude Code 排查取消機票:
cancel_ticket()
↓
409
↓
修改參數、再次嘗試
↓
仍然失敗
↓
最後發現 ticket_status 已過期
↓
refresh ticket_status
↓
cancel_ticket()
↓
成功
TeamAI 並不理解 409 的業務意義,也不需要在 cancel_ticket() 裡額外加入 TeamAI Log。初始化後,它會替支援的 Coding Agent 安裝 SessionStart、PostToolUse、UserPromptSubmit、Stop 等 Hook,定義在:src/builtin-hooks.ts。
這些 Hook 收集的是 Agent Harness 本來就有的執行紀錄,例如 Tool Result、使用者 Prompt、Stop event,再由 src/contribute-check.ts 在 Stop 時整理成幾種 friction:
interrupt 使用者中途停止 Agent
toolReject 使用者拒絕 Tool Call
correction Agent 回答後,使用者馬上糾正
toolError Tool 執行失敗
例如 src/dashboard-collector.ts 看到 transcript 裡:
tool_result
is_error = true
因此不需要每個 Tool 自己寫 TeamAI Log,或需要自訂 MCP Tool 必須正確回報錯誤;如果 API 回 409,MCP 卻把它包成正常成功結果,TeamAI 不會只看到「409」就自行判斷這是一個 failure。
Correction 目前邏輯是 Agent Stop 後 60 秒內收到新的 Prompt,而且包含 不是、wrong、redo、don't 等 correction keyword,就計一次 correction;團隊也能在 teamai.yaml 補自己的詞:
sharing:
intervention:
correctionKeywords:
- "不對"
- "改回來"
- "不要這樣做"
這些訊號最後會算成 friction score,目前 interrupt、toolReject、correction 各加 20 分,toolError 則依失敗次數加分;除了 score 達標,Session 還必須至少有 15 次 Tool Call,避免一次偶發錯誤就被當成值得長期保存的經驗。
流程:
Agent transcript / lifecycle event
↓
TeamAI Hook 收集
↓
Stop 時統計 friction
↓
score 達標 + 有足夠工作量
↓
提示這次 Session 可能值得整理
Stop Hook 到這裡只負責提醒,不會直接寫入 Learning。要使用這個 Share 流程,Recall 必須先開啟:
sharing:
recall:
enabled: true
符合條件時,使用者會看到類似:
This session may contain a problem worth documenting:
the AI retried failing tools ...
Consider running:
/teamai share what this session taught me
之後才由 share workflow 整理 Session,呼叫 teamai contribute,產生例如:
learnings/flight/cancellation-api.md
內容可能只留下真正可重用的結論:
Cancellation API 在 stale ticket_status 下可能回 409,
取消前應重新取得最新 ticket_status。
TeamAI 也不會在每次 Prompt 前強制執行 Retrieval,Recall 預設是關閉的,必須先在 teamai.yaml 設定:
sharing:
recall:
enabled: true
或由使用者執行:
teamai recall enable
這個 command 的實作在:src/recall-toggle.ts,它會安裝兩樣東西:teamai-recall Agent+Team Knowledge Recall Rule;Rule 會告訴 Main Agent,在 Debug、修改程式或設計決策前,優先查 Team Knowledge;如果只是 typo、局部修改,或答案已經明確存在目前檔案,就可以跳過。
Main Agent
↓
依 TeamAI 注入的 Rule
判斷這個 Task 是否值得查 Knowledge
↓
teamai-recall
它先執行:
teamai recall --check "<keywords>"
如果沒有足夠相關的結果,就停止;有相關內容時,才進一步搜尋:
skills
learnings
docs
rules
teamwiki
讀取真正命中的文件,再把精簡 Summary 交回 Main Agent。
所以 Bob 問:
取消機票一直回 409,幫我排查
實際流程:
Codex
↓
Recall Rule 判斷值得查詢
↓
teamai-recall
↓
teamai recall --check
↓
找到 cancellation-api learning
↓
讀取相關文件
↓
整理摘要給 Codex
這樣 Main Agent 不需要把整個 Team Knowledge Base 放進 Context,只取得這次任務真正相關的部分。
TeamWiki 也不會在安裝 TeamAI 後自己產生,要先明確執行:
teamai codebase --extract /path/to/repo
主要實作在:src/codebase-extract.ts
TeamAI 會對 Source Code 做 Static Analysis,透過 AST / tree-sitter 與 heuristic extraction,整理 component、interface、dependency、call relationship 等結構,再寫入 teamwiki/。
因此 Recall 不只能找到:Alice 曾遇到 stale ticket_status 造成 409,也可以同時找到:
CancellationService 在哪個模組
呼叫哪些 Repository
相關 Interface 是什麼
Team Context 最後其實是把三種資料放到同一個 Recall 入口:
人的經驗
→ learnings/
正式團隊知識
→ rules/ + skills/ + docs/
程式碼靜態結構
→ codebase --extract
→ teamwiki/
Team Context 解決了:
Alice 遇到問題
↓
留下 Learning
↓
Bob 之後可以 Recall
但 TeamAI 沒有把每一條 Learning 都直接當成正式 SOP。一次成功的排查只能證明「這件事曾經發生」,還不能證明「以後所有 Agent 都應該這樣做」。
因此 TeamAI 會記錄 Learning 後續是否真的被團隊使用,例如 Recall 次數、Upvote 次數與最近使用時間,再由:
src/maintenance/confidence.ts
計算 confidence。這個分數不是 LLM 主觀回答「我覺得可信度 0.93」,而是由實際使用資料計算,例如:
recalled_count
upvoted_count
last_recalled_at
目前一條 Learning 要成為 Promotion Candidate,需要同時符合:
confidence >= 0.90
upvotes >= 5
distinct users >= 2
age >= 14 days
達標後也不會自動升級。它只會出現在:
teamai dashboard
→ Team Improvement
→ Promotable Learnings
或執行:
teamai recall promote
時被列出,例如:
cancellation-api
confidence: 0.94
suggested: rules
TeamAI 把成熟 Learning 分成三種可能用途:
| 類型 | 適合的內容 |
|---|---|
rules |
必須遵守的限制或標準 |
skills |
可以重複執行的 SOP / Workflow |
docs |
架構、背景、Reference |
例如:
取消前必須重新取得最新 ticket_status
比較像 rule。
如果內容是:
1. 查最新 ticket_status
2. 驗證是否可取消
3. 計算退款
4. 向使用者確認
5. 執行 cancel_ticket
就比較像 skill;如果內容是在說明 CancellationService、version conflict 與 409 的關係,則更接近 doc。
類型也不是完全靠人猜,src/maintenance/promote.ts 的 inferCategory() 會先讓本機可用的 AI CLI 判斷 skills / rules / docs,AI 不可用時再退回 Keyword Rule,因此 Dashboard 才會顯示:
suggested: rules
使用者可以直接接受推薦:
teamai recall promote cancellation-api
也可以覆寫:
teamai recall promote cancellation-api --category rules
真正 Promote 時,TeamAI 不會去搜尋既有 Rule,然後猜應該插進哪一個段落,而是建立新的正式 Knowledge,例如:
learnings/cancellation-api.md
↓
rules/cancellation-api.md
同時由 AI 把原本「這次排查發生了什麼」改寫成適合 Rule、Skill 或 Doc 的格式,原 Learning 則記上:
promoted_to: rules/cancellation-api.md
避免再次被 Promote。
因此 TeamAI 的 Learning lifecycle 比較準確地是:
Session
↓
friction 達標
↓
提示 Share
↓
Learning
↓
其他人 Recall / 使用
↓
Confidence
↓
成為 Promotion Candidate
↓
AI 推薦類型 + 人決定
↓
Rule / Skill / Doc
也就是 TeamAI 並不是單純「把 Memory 記久一點」,而是把 Session 經驗 → 可搜尋的 Learning → 經過團隊驗證的正式 Knowledge 分成三個階段,這才是 Team Context 和 Team Improvement 真正接起來的地方。
前幾天介紹過 Hindsight 和 ai-memory。
三套系統都能讓 Agent 使用過去的資訊,但核心問題不太一樣。
| 比較 | Hindsight | ai-memory | TeamAI |
|---|---|---|---|
| 核心定位 | 通用 Agent Long-term Memory | Coding Agent 的跨 Session / 跨 Harness Memory | Team Harness + Team Knowledge |
| 主要記憶內容 | Memory Bank 裡的 Memory / Observation / Mental Model | Project Wiki、Session Observation、Handoff | Learning、Rule、Skill、Docs、TeamWiki |
| 寫入重點 | retain 後建立長期 Memory |
Lifecycle Hook 自動 Capture 工作過程 | 從有 friction 的 Session 整理值得共享的 Learning |
| Recall | recall / reflect |
FTS、Entity、Graph、Optional Vector | teamai-recall Subagent + BM25 / Code Graph |
| 主要隔離方式 | Memory Bank | Workspace + Project + User / Handoff | Project + Role namespace |
| 跨 Claude / Codex | 可以整合 | 核心設計 | 核心設計 |
| Cross-Agent Handoff | 不是主要 abstraction | 有明確 Handoff Protocol | 不是主要目的 |
| Team Sharing | 可建立 Shared Bank | 支援同 Project 多人共享 | 核心使用情境 |
| Session 工作歷史 | 可以 Retain | 核心能力 | 有 Session 資料,但主要用來找 friction |
| 知識治理 | Memory / Mental Model | Consolidation、Aging、Dedup | Learning → Confidence → Rule / Skill / Doc |
| Source of Truth | Memory Service | Git-backed Markdown Wiki | Team Git Repo |
| 最適合 | App / Agent 需要持續學習與推理的 Memory | Coding Agent 換 Session、換 Harness還能接著做 | 多人使用不同 Coding Agent,但希望共享同一套能力與知識 |
所以 TeamAI 雖然有 Memory,但它的終點是:
經驗
↓
Learning
↓
驗證
↓
Rule / Skill
↓
再分發給整個 Team