把 Linear 當成 AI Agent 的工作佇列 — 不用自己造 Queue,PM 也看得到
這是 QA Pipeline 系列的第 5 篇。前面四篇講了 pipeline 結構、spec-driven、learned-patterns 跟 launchd 排程。這些都是「agent 跟 infra」的話題。這一篇換個視角:agent 怎麼跟人類協作?
具體講就是:work queue 要放哪裡。
Redis queue 反模式
看過太多 agent 系統第一步就做這件事:
- Agent A 把任務寫到 Redis list
- Agent B 從 Redis pop 出來跑
- 偶爾有個 status 欄位、偶爾有 retry、偶爾有 dead-letter
結果變一個黑箱。PM 看不到在跑什麼、誰阻塞誰、哪些任務被 retry 幾次。然後 PM 跑來問:「昨晚 pipeline 到底修了哪些 bug?」你得進 Kibana 撈 log、還要拼湊 timestamp。
Agent 的 work queue 為什麼不能跟人類共用介面?
Linear 本來就是 queue,而且是人機共用的
攤開 Linear 一張 issue 的能力:
- 狀態機:Backlog / Todo / In Progress / In Review / Done / Canceled
- Labels:可以標
qa-bot、needs-human-review、module:auth等語意標籤 - Relations:
relatedTo/blocks/duplicate - Attachments:PR link 直接變成預覽卡片
- Comments:agent 寫、人看、人回、agent 下次再讀
- Cycles:sprint 週期、retrospective 統計內建
- Audit trail:每一次狀態變化、誰動的、什麼時候動的、內建
這整包就是一個成熟的 workflow engine。平常你用它管人、現在拿它管 agent。
linear-client.ts — agent 的 Linear CLI
我寫了一個 TypeScript CLI(scripts/lib/linear-client.ts,用 npx tsx 執行)。所有 agent 透過這個 CLI 跟 Linear 互動:
create-issue <json-file>
create-sub-issue <parent-id> <json-file>
update-issue <issue-id> <json-file>
set-state <issue-id> <state-name> [comment]
close-issue <issue-id> <comment>
add-comment <issue-id> <comment>
add-relation <issue-id> <type> <related-id>
add-attachment <issue-id> <url> [title]
set-due-date <issue-id> <YYYY-MM-DD>
set-estimate <issue-id> <points>
add-to-cycle <issue-id> <cycle-id>
get-issue <issue-id>
list-issues
list-actionable-issues
list-all-issues
search-issue <title-prefix>
get-labels
create-label <name> <color>
get-states
get-active-cycle
17 個子命令,覆蓋全部 Linear GraphQL 基礎能力。
為什麼是 CLI 不是 SDK
Claude Code agent 用 Bash tool 最穩。每次 run 的 tool invocation 長這樣:
Bash: npx tsx scripts/lib/linear-client.ts list-actionable-issues
比起把 Linear SDK 包進 agent 的 Read/Edit context、或者另外做一個 MCP server,子命令 + JSON stdout 是最少抽象的管道。debug 時我自己也用同一個 CLI。
底層 GraphQL client 有 retry + jitter(重要,Linear API 雖然穩、但峰值時會 429):
async function graphql(config, query, variables = {}) {
const maxRetries = 3
let delay = 1000
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(API_URL, {
method: "POST",
headers: { Authorization: config.apiKey, "Content-Type": "application/json" },
body: JSON.stringify({ query, variables })
})
if (res.ok) return res.json()
if (res.status === 429 || res.status >= 500) {
await new Promise(r => setTimeout(r, delay + Math.random() * 500))
delay *= 2
continue
}
throw new Error(`Linear API error: ${res.status}`)
}
}
list-actionable-issues — 整個 queue 的入口
所有 agent 的 work queue 實際上就是這個命令:
list-actionable-issues — List issues in Todo/Backlog/In Progress with qa-bot label
(for qa-fixer/explorer)
篩選條件:
- 有
qa-botlabel(agent 領域) - 狀態在 Todo / Backlog / In Progress(沒被 close)
- 沒被
needs-human-reviewlabel 鎖住
qa-fixer 每次 run 一開始呼叫這個命令、拿到自己該處理的清單、一個個處理完。沒有 Redis、沒有 SQS、沒有 JSON 檔。
兩個 agent 不會搶同一張 issue
Race condition 經典問題。我的解法用 Linear 狀態機當 soft lock:
fixer 領 issue → 立刻 set-state "In Progress" + comment「qa-fixer picking up (shift=am, date=2026-04-14)」
→ 開始修
→ 改完 set-state "In Review" + add-attachment <pr-url>
下一個 fixer 來 list-actionable-issues 時看到這張已經 In Progress、自動跳過。
這不是嚴格 atomic — 理論上有 race window(A 拿到 → A 正要改狀態 → B 也拿到同一張)。但實務上 pipeline 是序列跑、不會有兩個 fixer 同時動手,所以從來沒發生。如果哪天要嚴格 atomic、就得上 Linear webhook 或外部 redlock — 但那是「團隊多人協作 + 多台機器並行跑 agent」才需要的。單機 serial 就跳過。
Attachment 自動把 issue ↔ PR 綁起來
fixer 開完 PR 立刻:
npx tsx scripts/lib/linear-client.ts add-attachment \
AUT-54 \
https://github.com/your-org/your-repo/pull/123 \
"fix/qa-bot/2026-04-13"
這個連結在 Linear UI 會顯示成 PR card、自動 render PR title 跟狀態。PM 點進去直接看到 PR 內容、不用切到 GitHub。
以前我在別的 agent 系統做這件事要自己寫 Slack bot + GitHub webhook。Linear 內建。
為什麼 PM 會愛這個
三個實際體驗:
- 不用進 GitHub:PM 打開 Linear 就看到所有 agent 在做什麼、每張 issue 的進度、對應 PR 有沒有 merged
- Cycle view:這個 sprint agent 修了幾張 bug、哪些模組、vs 人類的 issue 比例
- Label filter:想看人類做的就 filter 掉
qa-bot、想看 agent 的就只留qa-bot、想看有歧義的就篩needs-human-review
過去兩週我跟 PM 的對齊會議縮了一半時間 — 他自己看 Linear 就知道我(跟 agent)在幹嘛。
反對意見
「Linear 要錢、我們用 GitHub Issues」
公平。GitHub Issues 可以做類似的事,只是 workflow 比較原始(狀態機只有 open/closed、沒有 cycle、沒有 dedicated attachment card)。重點是「用現成的人機共用 workflow engine」— Linear / GitHub Issues / Jira / Shortcut 都行。不要自建 queue 就對了。
「Linear GraphQL API 會被 rate limit」
會。所以 linear-client.ts 有 retry + exponential backoff + jitter。過去兩週 hit rate limit ~3 次、全部自動 recover。
「agent 會把 Linear 弄得太吵、PM 看不到真的 issue」
有風險。我的解法是 qa-bot label 一律要掛。PM 的預設 view 把 qa-bot filter 掉 — 想看時再開。兩週下來 60 張 agent issue vs ~8 張人類 issue,用 label 分群不會亂。
Takeaway
一句話:
不要為 agent 造一個新的 queue。找一個人類已經在用、有狀態機、有可視化、有 audit 的 queue 來兼用。
這不只省工,還有個隱藏好處:agent 的行為變得可被觀察、可被糾正。人類可以直接在 Linear 裡 reassign issue、改 label、加 comment — agent 下次 run 就讀到。這個 human-in-the-loop 的介面已經存在、不用另造。
下一篇 #6 是系列收尾 — 兩週跑下來的真實數字、做對的三件事、做錯的三件事、以及為什麼我要把這套抽成 claude-qa-pipeline OSS。
如果你也在設計 agent 的 work queue、或者已經在 Linear / Jira / GitHub Issues 上跑類似的 workflow,Twitter @waiting7777 想聽你的做法。
Waiting7777
WoW Arena 冠軍轉前端,用電競 meta 思維拆解技術趨勢。
相關文章
AI Agents開發者工具+1Orca 七個月拿下 10 萬顆星:我拆了它的 GitHub 數據,看到 agent 開發真正的瓶頸
一個由 agent 寫出來、拿來管 agent 的開源 IDE。19,000 個 commit、979 次 release 背後,最值得看的數字是 2,525 個放了一個月還沒人處理的 PR。
2026年10月20日 · Waiting7777 · 7 分鐘閱讀
繼續閱讀 →
AI Agents自動化測試+1跑了兩週 Agent QA Pipeline — 真實數字、踩到的坑、重來我會怎麼做
這是 post-mortem,不是 case study。做對的三件事、做錯的三件事、以及為什麼這套東西接下來要抽成 `claude-qa-pipeline` OSS。
2026年10月20日 · Waiting7777 · 6 分鐘閱讀
繼續閱讀 →
自動化測試開發者工具你的 100% Coverage 是假的 — 用 test-audit 抓出沒被真正測到的分支
AI 寫的 code 跑出漂亮的覆蓋率數字,但 error path 根本沒人測過,這工具專門抓這個。
2026年10月20日 · Waiting7777 · 3 分鐘閱讀
繼續閱讀 →這篇文章對你有幫助嗎?
每週一篇 — 技術趨勢背後的商業邏輯
AI 產業在變什麼、工程師該注意什麼——拆清楚寄到你的信箱。