跳轉到

Bring Your Own Agent (BYOA Core) 研究筆記

資料來源

項目 連結
GitHub Repo https://github.com/class83108/Bring-Your-Own-Agent
PyPI 套件 https://pypi.org/project/byoa-core/(0.1.0,2026-02-12 上傳)
架構文件 docs/architecture.md(15KB)+ docs/architecture.excalidraw
開發規範 CLAUDE.md(9KB,型別/命名/Gherkin/工具鏈全套規範)
Gherkin 規格 docs/features/core/*.feature(24 份)+ docs/features/app/*.feature(5 份)
Eval 任務 tests/eval/tasks/t01–t13 + tests/eval/framework.py + tools/eval_viewer.html
Roadmap docs/todo.md

Repo 現況(2026-07-27):★ 0 / fork 0 / issue 0 / MIT / Python 3.12+ / 181 個檔案 / 90 commits,全部出自單一作者 class83108(YAO AN CHUANG)。開發期 2026-01-24 → 2026-03-03(約 5.5 週密集開發),此後約 5 個月無新 commit。Development Status :: 3 - Alpha。

專案概述

這是一個從零重建 coding agent harness 的專案。README 的定位是「可擴充的 AI Agent 核心框架,透過 API 直接與 Claude 互動,自由組裝 Tools、Skills、MCP」,四個賣點:

賣點 原文說法
API-first 直接呼叫 Anthropic API,不依賴 CLI 工具,無被封禁風險
Pay-per-use 按量計費,輕度使用比月費訂閱更划算
可組裝 Tools、Skills、MCP 三種擴充機制,像樂高一樣自由拼裝
可嵌入 作為 library 嵌入你的應用,不是獨立 CLI 工具

但真正值得注意的不是這四點,而是它實際重建了什麼。掃一遍 src/agent_core/ 會看到:兩階段上下文壓縮、subagent 防遞迴機制、skill 的漸進式載入與隱形模式、tool result 自動分頁、think 工具、檔案式工作記憶、token counter + 費用估算、可續傳串流(EventStore)、多模態輸入、多 provider 路由 gateway、指數退避重試。這是 Claude Code / Anthropic harness 那套已知設計的一份完整的、正向重建的、繁體中文實作。

以「有沒有人用」衡量,這個專案是零(0 star、0 fork、0 issue、5 個月未動)。以「能不能讀懂 agent harness 到底在做什麼」衡量,它是本站目前收錄過最直接的教材之一——因為它不是逆向猜測別人的 minified 程式碼,而是有規格、有測試、有架構圖、有 eval 分數的正向實作。

技術架構

三層 + Protocol 解耦

┌──────────────────────────────────────────────────┐
│          可插拔擴充層 (Extension Layer)            │
│   Tools  ·  Skills  ·  MCP                       │
├──────────────────────────────────────────────────┤
│          核心層 (Core Layer)                      │
│   Agent(串流 → 工具調用 → 迭代)                  │
│   + Compact · Subagent · Memory · TokenCounter   │
├──────────────────────────────────────────────────┤
│          基礎設施層 (Infrastructure Layer)         │
│   LLMProvider · SessionBackend · Sandbox · EventStore │
└──────────────────────────────────────────────────┘

四條設計原則寫得很明確:Protocol-based 依賴注入(結構子型別,使用者不需繼承 base class)、Async-first(所有 I/O 都是 async)、Message-centric(Agent 狀態就是對話歷史,replay-safe)、最小介面(每個 Protocol 只定義必要方法)。

五個擴展點與可替換目標:

Protocol 內建實作 文件明示的替換場景
LLMProvider Anthropic / OpenAI / Gemini / Gateway 本地 Ollama 等
SessionBackend MemoryBackend、SQLiteBackend Redis、DynamoDB、PostgreSQL
EventStore MemoryEventStore(含 TTL) Redis Streams、Kafka
Sandbox(ABC) LocalSandbox Docker Container、Firecracker microVM
MCPClient 使用者自行實作 任何 MCP Server

Agent 對話迴圈

stream_message(content, attachments?, stream_id?)
├─ 1. 驗證輸入 + 建構 user message
├─ 2. 追加到 conversation
├─ 3. _stream_with_tool_loop()
│   ├─ 3a. _maybe_compact()          ← token 使用率 ≥ 80% 觸發
│   ├─ 3b. provider.stream()          ← yield 文字 token + AgentEvent
│   ├─ 3c. 記錄 usage → 追加 assistant message
│   ├─ 3d. stop_reason == 'end_turn' ? 結束 : 繼續
│   └─ 3e. _execute_tool_calls()
│       ├─ asyncio.gather() 平行執行
│       ├─ 建構 tool_result blocks → 追加 user message
│       └─ 回到 3a(上限 max_tool_iterations = 25)
├─ 4. EventStore 記錄事件(若有 stream_id)
└─ 5. 標記串流完成 / 失敗

四個值得單獨看的機制

1. Compact(兩階段上下文壓縮)

usage < 80%  → 不壓縮
Phase 1: 截斷舊 tool_result(無 API 呼叫,低成本)
  ├─ 掃描 user messages 的 tool_result blocks
  ├─ 舊的 content 換成 '[已壓縮的工具結果]'
  ├─ 保留最近 N 輪不截斷
  └─ 有截斷就返回,不進 Phase 2
Phase 2: LLM 摘要
  ├─ 找安全分割點(不打斷 tool_use → tool_result 配對)
  └─ 早期對話送 LLM 摘要,換成 user/assistant 摘要訊息對

「安全分割點偵測」是整個設計裡最容易被忽略但最致命的一步——如果切在 tool_use 和對應的 tool_result 之間,API 會直接拒絕整個請求。

2. Subagent(子代理)

複製 ToolRegistry 但排除 create_subagent 本身(防遞迴)、獨立 conversation(不污染父 agent context)、共享父 agent 的 Sandbox(同一安全邊界)、只回傳 {'result': accumulated_text}。可平行建立多個。

3. Skill 的三段可見性

狀態 system prompt 裡有什麼
已註冊未啟用 只有 name + description(LLM 知道有這個能力存在)
已啟用 完整 instructions 注入
disable_model_invocation=True 連描述都不載入(完全隱形)

而且做成 REST API 讓終端使用者在對話中即時切換:POST /api/skills/{name}/activate。這是 Anthropic Agent Skills 漸進式披露(progressive disclosure)的一個獨立重實作,連 disable-model-invocation 這個 frontmatter 欄位名都對得上。

4. GatewayProvider(框架內建的迷你 LLM Gateway)

_MODEL_PREFIX_MAP = [
    ('claude-', 'anthropic'), ('gpt-', 'openai'),
    ('o1', 'openai'), ('o3', 'openai'), ('o4', 'openai'),
    ('gemini-', 'gemini'),
]

用模型名稱前綴自動路由,加上 fallback 備援與 middleware chain(middleware 的具體實作如 cost tracking、OTel tracing 刻意留在應用層)。Provider 類別用 lazy import 避免迴圈依賴。

內建工具

工具 說明
read_file / edit_file / list_files / grep_search 檔案讀寫、目錄瀏覽、正則搜尋(支援上下文行數)
bash Shell 執行(含安全限制)
think 無副作用的推理記錄
web_fetch / web_search httpx + BeautifulSoup / Tavily API
create_subagent 建立子代理
memory view/write/delete 檔案式工作記憶,路徑穿越防護用 resolve().is_relative_to(root)

memory 工具的 system prompt 引導詞很值得抄:「假設對話隨時可能被壓縮」——直接把 compact 的存在告知 agent,讓它主動把重要狀態寫進檔案。

Eval 驅動開發

這是全專案最稀有的部分。tests/eval/ 裡有 13 個 SWE 風格任務,難度分級(easy/medium/hard/special):

Task 內容
t01–t04 修語法錯誤 / 修失敗測試 / 加函式 / 加錯誤處理
t05–t06 從症狀找 bug / 從測試反推實作
t07 大型 codebase
t08 模糊需求
t09 自我修復迴圈
t10 完整 TDD 循環
t11 Web crawler(本地 HTTP 爬蟲)
t12 迷宮探索(Memory + Compact 壓力測試)
t13 Subagent 平行修復

EvalResult 記錄的欄位比分數本身更有意思:

task_name, task_level, passed, score,        # 基本
tool_calls, tool_call_sequence,              # 工具用了幾次、順序長什麼樣
total_tokens, duration_seconds,              # 成本
ran_verification,                            # ← agent 有沒有自己跑測試
system_prompt_hash,                          # ← SHA256 前 8 碼,綁定提示詞版本

system_prompt_hash 加 ran_verification 這兩個欄位,讓「改了 system prompt 之後 agent 變乖了嗎」變成可查詢的資料而不是印象。todo.md 裡確實照這個流程走:v1-baseline 9/10 通過、avg 0.91,然後列出 P0–P4 優化方向(system prompt 強化、工具描述任務導向化、max iterations 上限、working memory、think 工具),逐條標記完成並註明對應的 target task。

Task 自動探索用 pkgutil.iter_modules 掃 t??_*.py,並驗證模組有 TASK_NAME / setup / evaluate 才收——一個輕量的 Protocol 檢查。另附 tools/eval_viewer.html(17KB)看結果。

工程紀律

面向 做法
規格先行 Gherkin 驅動 TDD:.feature(繁中 # language: zh-TW)→ 紅燈測試 → 綠燈實作 → 重構。29 份 feature 檔,用 Rule: 分組 scenario
型別 pyright strict 模式;CLAUDE.md 明文規定「優先定義型別,避免 cast()」,並列出 5 種替代手段(TypedDict + Literal discriminated union、縮窄參數型別、用 ['key'] 而非 .get() 觸發 narrowing、TypeGuard),cast() 只准用在反序列化邊界
測試分層 unit(tests/core、tests/app)/ smoke(tests/manual,需 --run-smoke + 真實 API + 會花錢)/ eval(需 --run-eval)
CI GitHub Actions ×3:ci.yml、codeql.yml、sonarcloud.yml + codecov + pre-commit + Allure 報告
慣例 Conventional Commits、feature/* branch、ruff(single quote、line-length 100)、uv 管套件且禁止手改 pyproject.toml dependencies

測試量遠大於實作量:test_agent.py 41KB vs agent.py 15KB;test_api.py 46KB vs main.py 18KB。

快速開始

uv add byoa-core          # 或 pip install byoa-core
uv add byoa-core[all]     # web(fetch/search) + mcp + openai
export ANTHROPIC_API_KEY=...
import asyncio
from pathlib import Path
from agent_core import Agent, AgentCoreConfig, AnthropicProvider, Skill, SkillRegistry
from agent_core.tools.setup import create_default_registry

async def main():
    config = AgentCoreConfig(system_prompt='你是專業的程式開發助手。')
    registry = create_default_registry(Path('./workspace'))   # read/edit/list/grep/bash

    skills = SkillRegistry()
    skills.register(Skill(name='code_review', description='程式碼審查',
                          instructions='審查程式碼並以表格輸出結果。'))
    skills.activate('code_review')

    agent = Agent(config=config, provider=AnthropicProvider(config.provider),
                  tool_registry=registry, skill_registry=skills)

    async for chunk in agent.stream_message('請讀取 main.py 並審查程式碼'):
        if isinstance(chunk, str):
            print(chunk, end='', flush=True)

asyncio.run(main())

另附 FastAPI 應用層(src/apps/agent_app/main.py)與 vanilla JS 前端(static/,app.js 23KB),提供 SSE 串流對話、session CRUD、token 用量、沙箱檔案樹、skill 即時開關等端點:

uv run uvicorn agent_app.main:app --reload --port 8000

目前限制與注意事項

項目 說明
實質停更 2026-03-03 後約 5 個月無 commit。90 commits 全出自一人,無外部貢獻者、無 issue 討論。作為生產依賴風險高
LocalSandbox 不是真沙箱 只做路徑驗證(resolve().is_relative_to)+ subprocess 執行。真正的容器隔離(ContainerRunner、RunnerPool)在 todo.md Priority 7 仍未打勾。bash 工具「含安全限制」但邊界靠應用層自己補
文件落後於程式碼 README 架構圖只列 anthropic_provider,實際已有 OpenAI / Gemini / Gateway 三個;README 的 Protocol 表仍寫「LLMProvider 內建實作:AnthropicProvider」;todo.md 把「多 Provider」列為「應用層待辦」(早就做完)、把「發佈到 PyPI」標為未完成(2026-02-12 就上了)。讀這個 repo 要以程式碼為準
無 PyPI 更新 PyPI 只有 0.1.0(2026-02-12),之後 2 週的 OpenAI/Gemini/Gateway 開發都沒發版。uv add byoa-core 拿到的是舊版,最新功能得從 git 裝
零外部驗證 0 star / 0 fork / 0 issue。eval 分數是作者自測(v1-baseline 9/10、avg 0.91),無第三方復現
Python 3.12+ 硬需求 pyright strict + from __future__ import annotations 風格,向下相容未考慮
全繁中 註解、docstring、feature 檔、規範文件都是繁體中文。對中文讀者是優勢,要國際化就得整批翻譯

研究價值與啟示

關鍵洞察

1. 這是「正向重建」而非「逆向拆解」,正好補上本站缺的那一半視角。 本站已收錄 Analysis Claude Code、Claude Code Reverse、Claude Code from Source——那些都是從 minified bundle 往回猜設計意圖。BYOA 走反方向:先寫 Gherkin 規格,再寫紅燈測試,再實作,最後用 eval 量測。同一組機制(compact、subagent、skill 漸進載入、tool result 分頁、max iterations)從兩個方向看,逆向能告訴你「官方實際怎麼寫」,正向能告訴你「為什麼非得這樣寫、不這樣寫會壞在哪」。想真的理解 harness,兩邊都得讀。

2. system_prompt_hash + ran_verification 這兩個 eval 欄位,是整個 repo 最該被抄走的 12 行程式碼。 多數人調 agent prompt 的流程是「改一改、跑幾次、感覺好像好一點」。BYOA 把 system prompt 的 SHA256 前 8 碼寫進每一筆 eval 結果,於是「哪個版本的提示詞得到這個分數」變成可查資料;再加上 ran_verification(agent 有沒有自己跑測試)、tool_call_sequence(工具調用的順序),量測的就不只是「答對了嗎」,而是「它的工作習慣變好了嗎」。todo.md 的優化表格能逐條標 ✅ 並註明 target task,靠的就是這個。這件事和 i-have-adhd 給輸出風格建 eval harness 是同一個思路的不同尺度:prompt 是需要回歸測試的產出物。

3. Protocol-based DI 讓「BYOA」這個名字名副其實,但代價是使用者要自己補的東西不少。 五個 Protocol 都把「替換場景」寫在文件裡(Redis / Kafka / Firecracker / Ollama),這是很誠實的設計——框架不假裝自己有生產級後端。但反過來說,MCPClient 和 LockProvider 的內建實作是「使用者自行實作」,Sandbox 只有 LocalSandbox,EventStore 只有記憶體版。框架給的是介面與參考實作,不是 batteries-included。這對學習是優點(每個介面都小到能一眼看完),對上生產是待辦清單。

4. 「無被封禁風險」是這個專案真正的產品起點,而它揭示了一個市場縫隙。 README 第一個賣點不是技術,是「不依賴 CLI 工具,無被封禁風險」+「輕度使用比月費划算」。這把 Claude Code 訂閱制的兩個真實焦慮直接寫成賣點。有意思的是這個縫隙的存在方式:官方 Claude Agent SDK 也是 API-first,但它是「用官方的殼」;BYOA 選擇連殼都自己寫。對只要一個可嵌入 library、不想要一整個 CLI harness 的人,這個選擇是理性的——即使代價是自己維護 15KB 的 agent loop。

5. 5.5 週、90 commits、單人做到這個完整度,靠的是規格先行而不是寫得快。 29 份 Gherkin feature 檔、CLAUDE.md 裡連「什麼時候不准用 cast()」都寫成 5 條替代手段、pyright strict、CodeQL + SonarCloud + codecov 三重 CI——這些看起來像過度工程,但正是它能在單人條件下維持 181 個檔案不失控的原因。特別是 CLAUDE.md 的型別規範那段:它其實是寫給 AI coding agent 看的(討論 discriminated union narrowing 該用 ['key'] 而不是 .get()),把「這個專案的品味」編碼成 agent 讀得懂的規則。這和 Ponytail、Awesome DESIGN.md 是同一件事的不同維度。

6. 文件漂移是高速單人開發的固定成本,而它有跡可循。 README 說只有 Anthropic provider、todo.md 說多 provider 是「應用層待辦」、todo.md 說 PyPI 未發佈——三處都被程式碼推翻。這不是粗心:2026-02-24 到 03-03 那 8 天連續加了 OpenAI、Gemini、Gateway 三個 provider 並重組專案結構,文件根本追不上,然後開發就停了,漂移被凍結在那裡。讀任何停更的個人專案,都應該先假設文件是舊的,用 git log 和檔案樹交叉驗證。

與其他專案的關聯

專案 關係
Analysis Claude Code、Claude Code Reverse、Claude Code from Source 鏡像關係。那三個從 minified bundle 逆向推設計;BYOA 從規格正向重建同一組機制。同題目的兩種解法,配著讀最有價值
Claude Agent SDK 官方的 API-first 答案。BYOA 是「連官方 SDK 都不用,自己寫一遍」的版本——用來理解官方 SDK 幫你擋掉了哪些事
CrewAI、Google ADK、OpenAI Agents SDK、LangChain 同為 agent 框架,但那些是團隊產品、有生態與社群。BYOA 的定位不同:它是單人可讀完的完整實作(core 約 200KB Python),適合當「框架到底在幫我做什麼」的解剖對象
LiteLLM GatewayProvider 是 LiteLLM 的框架內建迷你版——模型前綴路由 + fallback + middleware chain。可以對照看「自建 gateway 要處理哪些事、什麼時候該直接用 LiteLLM」
i-have-adhd 兩者都自建 eval harness 來擋 prompt 迴歸,但尺度相反:i-have-adhd 量測輸出形狀(14 個 case、加權 rubric、release gate),BYOA 量測任務完成能力(13 個 SWE task、score + tool_call_sequence + ran_verification)。合起來剛好是「agent 該怎麼講話」與「agent 該怎麼做事」兩套回歸測試
Ponytail、Awesome DESIGN.md CLAUDE.md 把型別品味(何時不准 cast())寫成 agent 讀得懂的規則,是同一種「把品味編碼成檔案」的做法,只是維度換成靜態型別
AI Engineering from Scratch、Karpathy LLM Wiki 同屬「從零重建以求理解」的學習路徑。差別是那些是為教學而寫,BYOA 是為自用而寫、順便成了教材——所以它保留了教學專案通常會省略的髒細節(compact 的安全分割點、subagent 防遞迴、tool result 分頁)