← Tutorial
Tutorial

讓 Agent 把 Codebase 畫成圖:用 archify 畫出 DeepSeek Harness 的三張系統圖

2026-09-02 ·約 18 分鐘 · — views
本文目錄

最近寫 code 的時間變少了,看設計的時間變多了。code 大多是 agent 產出的,我逐行看的比例明顯下降,真正花時間的地方變成:這個模組切得合不合理、邊界放對了沒、資料有沒有繞過該走的路。

審設計有幾種介面。spec 是一種,讀 code 是一種,圖是另一種。圖的優勢很單純:它是最快能在 high-level 看出結構問題的方式。一張架構圖攤開,哪個服務不該直連資料庫、哪條邊跨過了 trust boundary,幾秒鐘就看得出來,讀 spec 要翻好幾頁才會發現。同一張圖拿去 Design Review、帶新人、跟 PM 對齊,也比一份 spec 好講得多。Backend 工程師大概是最常需要畫這種圖的人。

以前畫圖是我自己的事,現在這件事也可以交給 agent。我最近在用 archify,它讓 agent 直接讀 codebase 畫出系統圖,成品是一個可以互動、可以導覽、單一 HTML 檔就能寄給同事的頁面。這篇拿我實際跑過的三張圖來講它怎麼用,以及畫的過程中發生了什麼。

讀完精華版(2 分鐘),你會理解:

  • 五種圖型各自的「主角」是什麼,怎麼用主角挑對圖型
  • archify 是什麼、怎麼裝、下一句 prompt 之後 agent 會做什麼
  • 同一個 codebase(DeepSeek Harness)畫成 Architecture、Sequence、Lifecycle 三張圖時,各自暴露了什麼

這篇是工具實戰,不是畫圖理論。五種圖型和角色分工只是鋪墊,主體是 archify 從安裝、下 prompt 到拿到圖,中間每一步實際發生了什麼。


精華版

圖型主角回答的問題DeepSeek Harness 的例子
Architecture系統元件有什麼、誰連誰、邊界在哪app-boot → Cordis kernel → agent-loop → llm seam,sandbox 圈在哪
Workflow一個流程從頭到尾怎麼跑、哪裡分岔、誰負責profile 疊 bundle 疊 patch 的 boot 流程
Sequence一次互動訊息在幾個角色間怎麼來回一次 turn:turn/start → llm/stream → tool/call → turn/end
Data Flow資料從哪來、被誰加工、存哪、誰在用session log 一路到 fork / resume / telemetry
Lifecycle一個會變狀態的物件有哪些狀態、什麼事件觸發轉換、終態是什麼tool call 審批:pre-execute → 決策 → approval/asked → 拒絕或執行
  • archify:給 AI agent 用的 architecture-as-code skill。你用一句話說要畫什麼,agent 讀 codebase 或你的描述,寫出一份 typed JSON spec,render 成單檔互動 HTML,可以切 dark / light、導覽章節、匯出 PNG / SVG。
  • 五種 diagram type:architecture、workflow、sequence、dataflow、lifecycle,跟上表一一對應。agent 從需求判斷該用哪一種,不確定時工具有 guide 命令可以問。
  • 可以直接用的原因:render 前先跑 validate,邊線穿過無關節點、標籤互相遮蓋、邊界框圈到不該圈的節點,這些都會被擋下來;deliver 之後再開真實瀏覽器量四種螢幕尺寸,確認不溢出。圖拿到手就是能貼進文件的狀態。

選圖型時先問什麼? 問「這張圖的主角是誰」。主角是元件就 Architecture,是流程就 Workflow,是一次互動就 Sequence,是資料就 Data Flow,是一個會變狀態的東西就 Lifecycle。主角選對,圖型就對了。

archify 跟叫 agent 寫 mermaid 差在哪? mermaid 是畫圖語法,agent 吐出來就結束,排版靠 renderer 自動排,你拿到的是一張靜態圖。archify 的 spec 帶座標、帶邊界、帶導覽章節,agent 要為排版做判斷,產出是可以點、可以追上下游的互動頁面。它明確說自己不做 mermaid 自動解析、通用 auto-layout、WYSIWYG 編輯。


以下是完整版,按需取用。

圖為什麼變成審設計的介面?

圖變成審設計的介面,是因為 code 大多由 agent 產出之後,我審的東西從實作細節變成結構。以前我把畫圖當成溝通工具:Design Review 用、新人 onboarding 用、跟 PM 對齊用。這些用途沒變,但多了一個:圖變成我審 agent 產出的介面之一。

這帶來一個以前沒有的要求。溝通用的圖畫得大概對就好,聽的人會問、會補。審查用的圖不行,圖上的每一條邊、每一個框都是一個斷言:A 呼叫 B、C 和 D 在同一個 trust boundary 內。如果斷言是錯的,我會基於錯的圖做出錯的判斷,而且不會發現。

agent 畫的圖有一個特性:它一定整齊。整齊的圖看起來可信,這正是要小心的地方。一個邊界框畫大了一點、多圈進一個節點,語意上就是在說「這個節點也在這個 sandbox 裡」,看的人不會懷疑,因為圖很乾淨。

所以我對 agent 畫圖工具的要求是:它得讓我相信圖上的邊線、標籤、邊界框沒有畫錯,我才能把注意力放在「圖描述的設計合不合理」上。archify 是我目前用起來最接近這個要求的。

五種圖型怎麼選?先問這張圖的主角是誰

archify 支援五種圖型,剛好也是我平常會用到的五種。分辨方法只有一個問題:這張圖的主角是誰。

Architecture 的主角是系統元件。沒有時間軸,只有「有什麼、誰連誰、邊界在哪」。新人第一天問「我們系統長怎樣」、Design Review 要看新服務放哪裡,都是這張。

Workflow 的主角是一個流程。有順序、有分岔、有多個參與者。CI/CD pipeline、審批流程、incident runbook 都是。在 DeepSeek Harness 裡,profile 疊 bundle 疊 patch 組出 plugin tree 的 boot 流程就適合這張。

Sequence 的主角是一次互動。一條垂直時間軸,重點是呼叫和回傳的順序,包括哪裡同步、哪裡非同步、timeout 在哪一步。跟 Workflow 的差別是:Workflow 是一個流程的地圖,可以有很多分支;Sequence 是一次互動的顯微鏡,通常聚焦一條路徑。

Data Flow 的主角是資料。服務只是資料經過的站。哪裡脫敏、哪裡跨出 trust boundary、哪個 topic 被哪些 consumer 讀,這張圖最清楚。DeepSeek Harness 的 session log 是唯一的模型上下文來源,它往 fork、resume、telemetry 三個方向流出去,就是一張 Data Flow。

Lifecycle 的主角是一個會變狀態的物件。訂單、job、Pod、一個 tool call。重點是狀態、觸發轉換的事件、retry 和 wait、哪些是終態。

不同角色的日常會偏向不同的圖:

角色最常用典型場景
前端Sequence、Lifecycleauth flow 的 token refresh 時機、上傳元件的 idle → uploading → failed → retry
後端五種都用design doc 用 Architecture 開場,關鍵路徑補 Sequence,有狀態的核心實體補 Lifecycle
DataData Flow、Lifecyclepipeline 拓撲和 lineage、Airflow task 的 retry 狀態機
Infra / CI/CDWorkflow、Architecturepipeline 的 approval gate 和 rollback 分支、服務邊界和依賴

下面三張圖都畫同一個 codebase,DeepSeek Harness。用同一個系統示範,比較容易看出「主角換了,圖型就換了」。

archify 是什麼、怎麼安裝?

archify 的定位是給 AI agent 用的 architecture-as-code:把一個 codebase 或一段系統描述,直接在對話裡變成一張可互動的系統圖。它是一個 agent skill,Claude Code、Cursor、Codex CLI、OpenCode 都能裝。安裝方式之一:

npx skills add tt-a1i/archify -g

裝好之後,agent 讀到「畫一張架構圖」這類需求時,會照 skill 裡的流程走:

  1. 從需求判斷五種圖型中的哪一種
  2. 讀對應的 schema 和一個範例,寫出一份 JSON spec(有需要時先讀 repo,用真實 code 當證據)
  3. validate,不過就照診斷修,再跑
  4. deliver 出 HTML,跑 visual-check 開瀏覽器量尺寸

我在 Claude Code 裡的用法很直接:告訴它 repo 在哪、想要哪種圖、重點看什麼,剩下的它自己跑完。拿到的是一個 HTML 檔,打開就有 dark / light 切換、pan / zoom、搜尋節點、點一個節點看它的上下游、依章節導覽,還能匯出 PNG、SVG、WebM。這篇文章裡的三張圖都是從那個 HTML 匯出的。

spec 是 agent 寫的,我不需要動它。它存在的好處是圖可以進 git、可以 diff,下次要改一個節點名稱直接改 spec 重新 deliver 就好,不用重畫。

第一張 Architecture:DeepSeek Harness 由什麼組成?

我給的指令大意是:讀 DeepSeek Harness 的 repo,畫一張系統層級的架構圖,重點放在 plugin 組成、一個 step 的主路徑、工具執行的邊界。

agent 選了 L1 系統層級,12 個節點,三條路徑:

  • 啟動路徑:App bins(dsh CLI / Web / ACP / JSON-RPC)→ app-boot → Cordis kernel
  • 一個 step 的主路徑:agent-loop → system-prompt、session log、llm seam → DeepSeek API
  • 工具路徑:tool registry → execution world(fs / shell / subprocess / terminal)→ sandbox + approval,旁支 delegation seams

DeepSeek Harness 系統架構

三條路徑對應 HTML 裡的三個導覽章節,點進去會 focus 那條路徑的節點,其他的淡掉。底部三張 card 對應 repo 裡 architecture.md 的三個核心不變式:一切皆 plugin、model-visible ⟺ logged、capability seam 的 Definition / Provider / Consumer 三角。

過程中唯一一次修正發生在邊界框。agent 第一版想用一個框把「Cordis plugin tree」圈起來,表達「這些都是 plugin」。問題是 archify 的邊界框是矩形,圈進 plugin 節點的同時,會把 DeepSeek API 和 App bins 也一起框進去。DeepSeek API 是外部服務,App bins 是入口程式,兩個都不是 plugin。框畫出來語意就錯了:圖會宣稱外部 API 是 plugin tree 的一部分。

最後的決定是拿掉那個框,「一切皆 plugin」這個不變式改寫進底部的 card,用文字說。圖上只留一個框:provider 共用執行世界,圈 execution world 和 sandbox + approval,這兩個確實共用同一個執行世界,換 provider 就整組搬到遠端 sandbox。

這是我覺得畫圖最容易出錯的地方。邊界框是一個很強的斷言,它說「框內的東西屬於同一個集合」。人手畫圖時,框歪一點、多圈一個角,看的人會自動腦補。但如果這張圖要拿來審設計,那個被多圈進去的節點就會被當成事實。寧可不畫框,也不畫一個會誤導的框。

第二張 Sequence:一次 turn 的訊息怎麼跑?

Sequence 這張回答的是「一次 turn 裡訊息怎麼在 agent-loop、session log、llm、tools 之間跑」。架構圖回答「有什麼」,這裡主角變成一次互動,圖型就換成 Sequence。

事件名和順序取自 repo 的 docs/agent-lifecycle.md:turn/start → agent/pre-step → step/start + user/message → system-prompt/assemble → agent/request → llm/stream → assistant/chunk* → tool/call → tool/result → step/end → agent/turn-stopping → turn/end。七個參與者:User / SDK、agent-loop、Session log、Hook listeners、systemPrompt、ctx.llm、ctx.tools。

DeepSeek Harness 一次 turn 的事件鏈

這張的修正跟語意無關,跟螢幕有關。第一版有 17 條訊息加底部 card,visual-check 在 1440×900 溢出約 370px。archify 的規則是不接受用縮小字體、內部捲軸或 overflow hidden 來假裝通過,只能刪真正冗餘的內容或壓縮間距。

agent 的做法是把 return 訊息折進正向訊息的 label。原本「agent/request → ctx.llm」和「StreamChunk* 回來」是兩條線,合成一條「agent/request → llm/stream → StreamChunk*」。tool/call 那條同理,「pre / execute / post → frozen result」寫在同一個 label 裡。17 條變 12 條,底部 card 拿掉,四種尺寸都過。

這裡有一個取捨我要老實講。Hook listeners 那段保留了明確的 return 線(enter(messages) 或 reject),但 ctx.llm 和 ctx.tools 沒有,風格不完全一致。從 Sequence 的教科書定義看,這算偷懶;從「這張圖要在一個 1440×900 的螢幕上一眼讀完」看,這是對的。我目前的判斷是,一張圖服務一個問題,這張圖的問題是「事件順序是什麼」,return 的細節不是它要回答的。

第三張 Lifecycle:一個 tool call 會經過哪些狀態?

一次 turn 裡最需要單獨拆出來看的是 tool call 的審批。它有等待態、有多種拒絕路徑、有一個容易被畫錯的地方:拒絕之後呢?主角是「一個 tool call 的狀態」,換 Lifecycle。

事實來源是 repo 的 docs/tool-execution-pipeline.md 和 dsh-user-approval 的 README。主軸五個狀態:tool/call 已落地 → tools/pre-execute(hooks / permission / sandbox waterfall)→ 決策(allow / ask / deny)→ guards + execute → tool/result。

DeepSeek Harness tool call 審批狀態機

分支在決策那一格。ask 進等待態 approval/asked,只有 allowed-once 回到執行;rejected、cancelled、unavailable 都進拒絕態。deny 或 policy never 直接進拒絕態,不經過等待。

這張圖最重要的一條線在底部:拒絕態不是終點。被拒絕的 tool call 仍然會經過 post waterfall,產生一筆 isError 的 tool/result,模型看得到。這對應 DeepSeek Harness 的核心不變式「model-visible ⟺ logged」:模型能看到的事都要有記錄,包括被拒絕這件事。如果 Lifecycle 把拒絕畫成死路,圖就在暗示「拒絕之後模型什麼都不知道」,這是錯的。

archify 對 Lifecycle 有一條規則剛好對應這件事:failure 型的狀態如果是可恢復的,必須有一條真實的 transition 回到 active 態,不能只是畫個紅框放著。這條規則逼你回答「失敗之後往哪去」,我覺得是這五種圖型裡最實用的一條約束。

一個小瑕疵如實記錄:lifecycle renderer 自己多印了一行「03 / Outcomes」泳道標題。那是底部通道佔用的列,不是 spec 裡定義的泳道,內容沒有錯,但看圖的人會以為那是一個刻意分出來的層。guards 階段自己的 deny 我沒有單獨畫線,寫在 card 裡,這是我的簡化,不是工具的限制。

為什麼 archify 產出的圖可以直接用,不用手調排版?

三張圖我沒有手動調過任何排版,因為 archify 在 render 前跑 validate、render 後開真實瀏覽器量尺寸,排版問題在圖交到我手上之前就被擋掉了。

archify 在 render 前會跑 validate。它檢查的東西分幾類。schema 層:欄位對不對、id 有沒有重複、from 和 to 指的節點存不存在。layout 層:邊線有沒有穿過無關的節點、兩條邊有沒有共用一條看不出誰是誰的走廊、標籤有沒有蓋住別的路徑、邊界框圈住的是不是它宣稱的那些節點。標籤層:label 跟邊線之間的間隙要大於 label 本身的遮罩寬度,不夠就是重疊。

失敗時的診斷是結構化的:rule code、出問題的 subject、量測到的數字、可以用的修法清單。agent 拿到這份診斷後只改被點名的 subject,改完再驗。skill 裡還有一條規則:如果連續兩輪修正都沒讓錯誤數下降,就停下來如實報告,不要無限重試。

deliver 之後的 visual-check 是另一層。它開真實的 Chrome,在 1440×900、1600×1000、1920×1080、2048×1320 四種尺寸、明暗兩色下量:頁面有沒有橫向或縱向溢出、最小的節點文字有沒有低於可讀門檻、legend 和導覽列有沒有互相遮到。Sequence 那張的 17 條訊息就是在這一層被擋下來的。

互動層也有同樣的紀律。HTML 裡的 focus、上下游追蹤、導覽章節這些功能,全部只能用 spec 裡已經有的節點和關係,不能為了展示效果生出新的拓撲。

它也有明確不做的事:不自動解析 mermaid(agent 會讀 mermaid 的語意再重寫成 spec,但不是機械轉換)、不做通用 auto-layout、不做 WYSIWYG 編輯。Viewer 的 UI 文字只支援 en 和 zh-CN,我的內容是繁中,所以 Viewer 介面維持英文。

這跟 Vibe Coding 有什麼關係?

我現在的工作流裡,agent 寫 code、agent 畫圖、我審。審 code 我還有 test 和 type check 幫忙,審圖以前只有眼睛。現在排版和幾何的部分交給工具,我的眼睛可以省下來看「圖描述的設計合不合理」。

三張圖各自幫我看到一件事。Architecture 讓我確認 sandbox 邊界只圈了該圈的兩個節點。Sequence 讓我看到一次 turn 有 12 個事件在 7 個參與者之間流動,哪幾個是 hook 可以攔的。Lifecycle 讓我確認拒絕態有出口。這三件事讀 code 都能知道,但沒有一個能在幾秒鐘內看出來。


結語:當你審的是 agent 產出的設計而不是自己寫的 code,圖是最快的介面。archify 讓 agent 直接從 codebase 畫出這張圖,你只需要負責看它對不對。