tiny-agent 從第一性原理打造可靠 Agent

第零部|基礎知識 · 第 0 章

模型、Token 與 Context

建立 Agent 工程的共同語言:模型如何產生輸出,以及 token、message、context、tool、session 與 memory 分別是什麼。

約 28 分鐘 1 / 10

一句話掌握本章核心:在討論 Agent 之前,必須先釐清「模型實際收到什麼」。本章依序拆解 Token、Message、Context、Context Window、Tool Call、Session 與 Memory。讀完後,你將能清楚指出每一次 API 呼叫中,每一份資料究竟儲存在模型權重、應用程式記憶體,還是硬碟之中。

先建立清晰的系統心智模型

在固定模型權重與推論設定下,可將大型語言模型(Large Language Model,LLM)視為一個不自行保存應用程式對話狀態的推論函式:輸入 Token 序列,計算下一個 Token 的條件機率分佈。這是設計 Runtime 時最純粹的工程抽象。實際取樣回覆可能略有不同,而部分 Provider API 也能在伺服器端保存或串接對話狀態。

產品中看似會流暢聊天、能讀寫專案檔案、能執行命令列的「AI」,本質上並非模型本身具備作業系統特權,而是外層的 Host Application 將模型、資料結構與系統呼叫(System Call)串接整合的成果。

LLM Host Application 與作業系統邊界圖
圖 1:LLM 與 Host Application 的系統邊界——在 tiny-agent 採用的 Chat Completions 架構中,作業系統副作用均由 Host 依已啟用工具與 Runtime Guard 代為執行。
圖 2:tiny-ts 的完整系統架構。開啟後可縮放、搜尋元件、追蹤路徑與切換導覽視角。
第 00 章延伸

tiny-ts 系統架構

使用者 (User)
  ↓
Host Application
  ├─ 組合 Instructions、歷史對話、檢索資料與 Tool Definitions
  ├─ 呼叫 Model API(送出 Active Context)
  ├─ 驗證並執行 Model 請求的 Tool(發動 System Effects,如檔案讀寫或 Shell 執行)
  └─ 保存 Transcript / Session(持久化狀態到硬碟)
  ↓
Model:根據本次有效 Context 計算下一個回覆或 Tool Call 提議

對 tiny-agent 目前使用的 OpenRouter Chat Completions 配接器(Adapter)而言,模型可用的資料完全來自本次 Request 中的 Messages、Tool Definitions 與其他明確輸入。未送入的檔案系統、資料庫或環境變數,絕對不會憑空出現在 Context 中。這不是所有 API 的通則:例如 OpenAI Responses API 可用 previous_response_id 串接由 Provider 伺服器端管理的對話狀態,詳見 OpenAI Conversation State。

在深入探討 Token、Context 與推論生命週期前,推薦先觀看 3Blue1Brown 的視覺化解析。它能幫助你在腦中建立神經網路計算的具體直覺,之後再閱讀本章的工程定義時,更容易將「模型本身」與「外層 Agent 系統」清晰拆分。

若影片無法嵌入播放,可直接前往 YouTube 觀看。

Token:計算與計費的基本單位

TL;DR:模型不認識「字元」或「單字」,它處理的是經過 Tokenizer 切割後的整數識別碼(Token ID)。

原始文字字串 → [ Tokenizer ] → Token IDs [15496, 11, 703] → [ Model ] → Output Token IDs → [ Decoder ] → 輸出文字字串
  • 英文單字:常見單字通常是一個 Token(如 apple),罕見字或複合詞會被拆解為多個 Subwords。
  • 中文字詞:不保證「一字一 Token」。實際切分與數量取決於模型使用的 Tokenizer。
  • 非文字資料:程式碼縮排、JSON 標點符號、大型 Log 與 Base64 字串通常也會占用可觀 Token,程度仍依 Tokenizer 與資料內容而定。
  • 資源限制:Token 數量會影響 Context Window 用量、傳輸與推論延遲、以及依 Token 計費的 API 成本。排隊、模型、硬體與快取也會影響延遲。

模型如何產生答案

TL;DR:模型輸出是「逐字機率預測」,不是「資料庫查詢」。

模型每一步都根據目前已有的所有 Tokens(Prefix),計算下一個 Token 的條件機率分佈 P(token | previous tokens),再由 Decoding Policy 取樣選出一個 Token,寫入序列後重複此迴圈,直到觸發停止符號(Stop Sequence)或達到最大長度上限。

核心現象計算機科學成因軟體工程對策
可能產生幻覺 (Hallucination)模型追求機率分佈上的語意連貫,非事實查證關鍵資訊必須依賴 Tool 讀取真實資料驗證
上下文順序敏感 (Order Matters)自注意力機制(Self-Attention)受位置編碼強烈影響關鍵 Instructions 與 Guardrails 應放置於顯著位置
輸出具隨機性 (Non-deterministic)Temperature 取樣機制與分散式浮點數運算微小誤差測試應驗證「資料契約 (Contract)」而非比對字串逐字相符

Prompt、Message 與 Transcript

現代 LLM API(如 OpenAI, Anthropic)多採用具有「結構化角色」的 Message 陣列作為標準輸入:

角色 (Role)用途與語意資料來源與信任等級
system / developer設定 Agent 核心身分、行為規範、工具使用守則受信任的 Host Application
user使用者輸入的指令、問題或外部事件外部使用者(不受信任輸入)
assistant模型先前的推論回應或發起的 Tool Call 請求LLM 生成輸出(待驗證)
tool對應 Tool Call 執行後的觀測結果或錯誤文字Host Tool Adapter 產生。內容仍可能來自不受信任的檔案、行程或遠端服務

三者名詞釐清:

  • Prompt:指送入模型的所有輸入集合(包含 Instructions、對話歷史與 Tool 定義)。
  • Transcript:在記憶體或硬碟中,依照嚴格時序 append-only 累積的 Message 歷史陣列。
  • Role Invariant:Host 必須維持 Message 序列合法。例如:Assistant 一輪發出的每個 Tool Call,都必須有相同 tool_call_id 的 Tool Result。完成這組 Calls 前不可插入無關的新對話。

Context 到底是什麼

Context 是模型在單次推論當下,暫存於其計算視窗中的「全部有效輸入集合」。

Active Context 視窗 vs 外部儲存邊界對比圖
圖 3:可見 Context 與外部儲存的邊界——未被 Host 明確投影進本次推論 Request 的資料,模型一概不知。

在 Active Context 裡(模型看得見)

  • 本次 Request 明確送入的 System Prompt
  • 目前選入對話歷史中的 Messages
  • 本次提供給模型的 Tool JSON Schemas
  • 剛由 Host 執行並寫回的 Tool Result

不在 Active Context 裡(模型完全看不見)

  • 本機硬碟中存在但尚未被 read 的檔案
  • 資料庫中存在但尚未被查詢的記錄
  • 上一個已結束 Process 的記憶體狀態
  • 被 Compaction(歷史壓縮)移出視窗的原始對話

Context Window 與 Token Budget

Context Window 是模型單次 Request 能處理的 Token 上限。OpenAI 與 Anthropic 的官方文件均說明,輸入、輸出,以及適用時的 Reasoning Tokens、Tool Definitions 與 Tool Results 都可能計入此上限。其分配可簡化為以下約束:

System Instructions + Conversation Messages + Tool Definitions + Retrieved Docs + Max Output Tokens ≤ Context Window Limit

在系統工程中,並非「Context 越大塞越多越好」。超過上限會引發截斷錯誤。而在上限內塞入過多雜訊則會導致注意力稀釋(Needle In A Haystack 效應),使模型遺漏核心規則。

Context 管理手法工程目標具體作法
Selection(精準篩選)降低雜訊,提升注意力集中度只注入與當前任務高度相關的指令與檔案片段
Progressive Loading(漸進載入)節省初始 Token,按需付費啟動時僅載入 Skill 名稱,被觸發時才載入詳細文件
Compaction(上下文壓縮)突破長對話 Window 限制將舊對話摘要為結構化 Facts,移除非關鍵中間過程
Bounding(輸出邊界保護)防止單一 Tool 撐爆 Window截斷過長的 Bash 輸出與巨大檔案內容

Tool Call:模型提議,Host 執行

重要原則:Tool Call 是結構化的工具呼叫提議。只有在 Provider 與模型支援且啟用 Strict Mode 時,才可期待參數可靠遵循 Schema。tiny-agent 目前的 Chat Completions Tool Definitions 未啟用 strict: true,因此 Host 仍須解析並驗證所有參數。模型沒有直接取得作業系統執行權限,真正的副作用由 Host 發動。參見 OpenAI Function Calling:Strict Mode。

1. Host 送入定義  ───→  提供 read(path: string) 的 JSON Schema
                             ↓
2. Model 發起提議  ───→  回傳結構化 JSON:{ name: "read", arguments: { path: "main.go" } }
                             ↓
3. Host 驗證派發  ───→  檢查 Plugin Allowlist、參數為 JSON Object 與 Built-in 欄位型別
                             ↓
4. Host 發動 Effect ──→  呼叫 OS System Call 讀取檔案
                             ↓
5. Host 寫回結果  ───→  以 role: "tool" 訊息將檔案內容 Append 回 Transcript
                             ↓
6. Model 下次可見  ───→  模型在下一個 Request 才能根據內容進行推理

狀態解構:Model、Session 與 Memory

在資工系統設計中,切忌將所有儲存抽象籠統稱為「記憶」。必須嚴格區分每一種狀態的儲存媒介與生命週期:

概念名詞本質定義儲存媒介生命週期 (Lifecycle)
Model Weights神經網路訓練權重GPU VRAM / Provider 伺服器長久固定,推論時不改變
Active Context當前單次推論可引用的 Token 集合Inference Runtime。Provider 可能另有不受應用程式控制的快取或對話狀態應用程式不可假設下次 Request 能直接取用,須依 Endpoint 的狀態契約
In-memory Transcript ViewRuntime 當下使用的結構化 Message 串列Host Process Heap MemoryProcess 結束即消失,但可由 Durable Session 重建
Durable Session支援 Crash Recovery 的交易記錄本機磁碟(JSONL WAL 檔案)持久儲存,支援跨 Process 復原
Memory Service跨任務的長期事實或偏好索引例如關聯式、文件、向量或 Key-Value Store,也可由檔案或 Provider Service 實作依產品政策跨 Session 或專案保存

六個常見的觀念誤解 (Pitfalls)

常見錯誤直覺系統工程真實情況
❌ 「模型知道專案裡的所有檔案」✅ 模型只知道本次 Request 送進去的檔案,其餘必須透過 Tool 讀取。
❌ 「UI 畫面上看得到的訊息,模型都看得到」✅ UI 呈現的是歷史儲存,送入模型前可能已經過裁切、篩選或摘要。
❌ 「有了 JSON Schema 就能保證安全」✅ Schema 或 Strict Mode 只處理結構契約。權限、路徑、Shell 與網路政策必須由 Host / Deployment Guard 負責。tiny-agent 目前不做 CWD Containment。
❌ 「Prompt Caching 能擴大 Context 容量」✅ 快取只降低重複 Prefix 的運算時間與計費,無法突破 Context Window 物理上限。
❌ 「模型說它已經修改好檔案,代表檔案已修改」✅ 應核對 Host 實際派發的 Tool、目標路徑、執行結果與後續讀取或測試。Tool Result 比模型自述更可稽核,但不是單獨且充分的真實性證明。
❌ 「Process 崩潰重啟後,可以直接重放所有動作」✅ 外部副作用(如寫檔、發 API)狀態未知,未經安全檢查重放會引發嚴重重複副作用。

自我檢查 (Review Questions)

  1. 硬碟中存在但未被 Tool 讀取的檔案,是否存在於模型的 Active Context 中?
  2. Provider 的 Prompt Cache 命中時,會不會釋放 Context Window 的可用容量?
  3. Tool Call 回傳的 arguments 參數,在 Host 端可以直接信任並執行嗎?為什麼?
  4. Transcript、Active Context 與 Durable Session 這三者在生命週期上有何本質區別?
  5. 當模型輸出「測試已全數通過」時,Host 端應依據什麼證據確認真實性?

釐清了基礎概念後,我們知道:在本專案的工程抽象中,Model 負責推論。Host 掌控 Transcript、執行 Tool 並產生副作用。Session 負責持久化狀態。下一章會以教學用的 Canonical Agent Loop 串起這些角色。