<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>開源專案解析 on YennJ12 Engineering Blog</title><link>https://yennj12.js.org/yennj12_blog_V4/tags/%E9%96%8B%E6%BA%90%E5%B0%88%E6%A1%88%E8%A7%A3%E6%9E%90/</link><description>Recent content in 開源專案解析 on YennJ12 Engineering Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 07 Aug 2026 14:00:00 +0800</lastBuildDate><atom:link href="https://yennj12.js.org/yennj12_blog_V4/tags/%E9%96%8B%E6%BA%90%E5%B0%88%E6%A1%88%E8%A7%A3%E6%9E%90/feed.xml" rel="self" type="application/rss+xml"/><item><title>QM 深度解析（一）：多人協作 Agent 平台的架構全景</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/qm-multiplayer-agent-part1-architecture-zh/</link><pubDate>Fri, 07 Aug 2026 14:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/qm-multiplayer-agent-part1-architecture-zh/</guid><description>大部分 Agent 產品的設計起點是「一個使用者」。 你可以把它塞給整間公司用，然後很快會發現： 記憶混在一起、憑證共用、A 在頻道問的問題被 B 的 context 污染。 QM 的起點反過來 —— 它先假設有很多人，再問「他們怎麼共用同一個 Agent」。
本系列共五篇，逐層拆解 yc-software/qm： 它解決什麼問題、Scope 模型怎麼撐起多人隔離、Harness 抽象怎麼同時驅動四種 Agent 引擎、 安全模型怎麼分層，以及沙箱 / Skills / Cron 這些持久化能力怎麼組裝。
本篇是第一篇：架構全景。
一、核心命題：single-player 與 multiplayer 的分野 1.1 README 的第一段就是設計聲明 Most agents are designed like personal assistants. You can make one work for a whole company, but it quickly gets complex. QM is designed for startups. Employees each get their own isolated workspace and work independently without affecting each other, and they can also collaborate with the agent in channels, group messages, and projects.</description></item><item><title>OpenWorker 深度解析（一）：架構全景 — 一個能交付成果的桌面 AI 同事</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/openworker-intro-part1-architecture-overview-zh/</link><pubDate>Fri, 07 Aug 2026 09:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/openworker-intro-part1-architecture-overview-zh/</guid><description>大多數人看到「又一個 AI Agent 專案」，會直接跳到 README 的安裝步驟。 少數人會打開 engine.py，想知道那個 while 迴圈長什麼樣子。 但真正值得學的東西，藏在「它拒絕做什麼」裡。 OpenWorker 最有價值的部分，是它對「什麼時候不該讓 Agent 自己決定」的答案。
本系列共五篇，逐層拆解 andrewyng/openworker 這個專案： 它是什麼、核心程式碼怎麼寫、Harness（安全外殼）怎麼設計、LLM 層怎麼抽象， 以及它的能力擴充體系（Tools / Skills / Personas / MCP / Connectors）長什麼樣。
本篇是第一篇：架構全景。我們先建立地圖，後面四篇才鑽進程式碼。
一、核心問題：為什麼「聊天」不夠 1.1 Chatbot 與 Coworker 的差別 絕大多數 LLM 產品的產出是一段文字。你問它「幫我整理這週 Jira 上的 release 狀態」， 它回你一段 Markdown，然後你複製、貼上、修正格式、再手動貼到 Slack。
OpenWorker 的定位寫在 README 第一行：
AI that gets your everyday tasks done — delivers finished work, not just chat.
差別在於「最後一哩路」由誰走：
┌──────────────────────────────────────────────────────────────────┐ │ Chatbot 模式 │ │ │ │ 你 ──問題──▶ LLM ──文字──▶ 你 ──手動──▶ 檔案 / Slack / 行事曆 │ │ ▲ │ │ └── 這段仍然是人在做 │ └──────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────┐ │ Coworker 模式 │ │ │ │ 你 ──目標──▶ Agent ──工具呼叫──▶ 檔案 / Slack / 行事曆 │ │ │ ▲ │ │ └──「要送出了，OK 嗎？」┘ │ │ │ │ │ ▼ │ │ 你只做「批准」這一個動作 │ └──────────────────────────────────────────────────────────────────┘ 這個轉換帶來的不是體驗優化，而是全新的工程問題：</description></item><item><title>OpenWorker 深度解析（二）：TurnEngine — Agent 迴圈的完整解剖</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/openworker-intro-part2-turnengine-deep-dive-zh/</link><pubDate>Fri, 07 Aug 2026 10:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/openworker-intro-part2-turnengine-deep-dive-zh/</guid><description>大多數人以為 agent loop 就是「while 迴圈裡呼叫 LLM，有 tool_calls 就執行」。 那份實作大概 40 行，在 demo 裡跑得很好。 真實系統裡它是 1192 行，而多出來的 1152 行不是為了功能，是為了「壞掉的時候別壞得太難看」。 這篇要讀的，就是那 1152 行。
本篇是 OpenWorker 深度解析系列 的第二篇，主角只有一個檔案：coworker/engine.py。
一、Agent Loop 的本質，以及它的三個謊言 1.1 教科書版本 1# 你在每一篇 tutorial 裡看到的版本 2messages = [{&amp;#34;role&amp;#34;: &amp;#34;system&amp;#34;, &amp;#34;content&amp;#34;: SYSTEM}, {&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: user_input}] 3while True: 4 resp = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS) 5 msg = resp.choices[0].message 6 messages.append(msg) 7 if not msg.tool_calls: 8 break 9 for tc in msg.tool_calls: 10 result = TOOL_FUNCS[tc.</description></item></channel></rss>