議:一個協(xié)議統(tǒng)一流式、存儲與模型的完整指南)
揭秘 PenguinHarness 的 OmniMessage 協(xié)議一個協(xié)議統(tǒng)一流式、存儲與模型的完整指南【免費(fèi)下載鏈接】penguin-harness Unified and Stable RSI Platform項(xiàng)目地址: https://gitcode.com/gh_mirrors/pe/penguin-harnessPenguinHarness 是一個開源的 Agent Harness 平臺而它的底層基石是OmniMessage 協(xié)議——一套統(tǒng)一的消息協(xié)議SDK 產(chǎn)出它Trace 存儲它Server 再經(jīng) SSE 原樣推送它。這意味著流出去的、存下來的、以及模型看到的內(nèi)容是同一種結(jié)構(gòu)前端、后端與存儲之間不存在第二套格式。這篇文章用通俗的方式帶你完整看懂 OmniMessage它長什么樣、有哪幾類消息、如何做到流式即存儲以及為什么它讓 Agent 會話可以無損恢復(fù)。為什么一個協(xié)議如此重要 構(gòu)建 AI Agent 應(yīng)用時工程師常常要面對三套語言流式輸出模型一邊生成一邊往外吐 token客戶端要邊收邊渲染磁盤存儲會話歷史要落盤將來還要能完整回放、恢復(fù)模型上下文下一輪請求要把歷史消息重新喂給模型。如果三者各用各的格式你就得寫大量的轉(zhuǎn)換代碼把流式分片拼成完整消息、把完整消息轉(zhuǎn)成存儲格式、再把存儲格式還原成模型能讀的上下文。任何一處轉(zhuǎn)換出錯會話恢復(fù)就會出問題。OmniMessage 的解法很直接只定義一種結(jié)構(gòu)所有環(huán)節(jié)共用它。整個系統(tǒng)的內(nèi)核只認(rèn)識 OmniMessage不做任何協(xié)議轉(zhuǎn)換——供應(yīng)商協(xié)議的差異被封裝在模型網(wǎng)關(guān)一側(cè)UI 的差異被封裝在渲染層一側(cè)。協(xié)議的類型定義集中在 packages/core/src/omnimessage/types.ts。統(tǒng)一的信封三類消息一個結(jié)構(gòu)每條 OmniMessage 共用同一個信封只有payload不同時間戳、消息類型、消息體外加一個可選的origin字段。外層type只有三種取值消息類型含義出現(xiàn)規(guī)律session_meta一個模型上下文的完整運(yùn)行時配置每個上下文恰好一條model_msg上下文內(nèi)的內(nèi)容文本、思考、工具調(diào)用與結(jié)果消息主體event_msg上下文之外的運(yùn)行時事件審批、用量、壓縮、中斷、鉤子回答伴隨出現(xiàn)其中session_meta相當(dāng)于開局記錄它記下會話 ID、所用模型、完整裝配好的系統(tǒng)提示詞、Agent 狀態(tài)與工作區(qū)路徑。每個 Trace 文件都以一條session_meta開頭會話內(nèi)切換模型時會開啟新上下文、寫下一條新的 meta。恢復(fù)會話時引擎直接讀最新文件里的 meta 就能還原運(yùn)行時配置——這就是存儲即恢復(fù)的基礎(chǔ)。完整消息與流式分片流式如何做到零拼接model_msg里有兩組 payload完整消息共七種用payload.type區(qū)分text普通文本區(qū)分 user / assistant 角色thinking/inline_thinking模型思考塊tool_call/tool_call_output工具調(diào)用與結(jié)果通過tool_call_id嚴(yán)格配對image_url/inline_data圖片與其他二進(jìn)制內(nèi)容。流式分片共四種partial_*payload與完整消息一一對應(yīng)并帶一個event_type標(biāo)記所處階段start→delta→stop。這里最優(yōu)雅的地方是流式紀(jì)律每段流式內(nèi)容都嚴(yán)格遵守同一時序規(guī)則——partial_text(start) → partial_text(delta) → … → partial_text(stop) → text (complete)所有 delta 拼接起來恰好等于完整消息且stop之后緊跟完整消息本身。因此渲染層可以邊收 delta 邊繪制、收到完整消息后原地替換而 Trace只記錄完整消息不存分片。接口內(nèi)部把結(jié)構(gòu)閉合好從不向上層泄漏未閉合的分片使用方永遠(yuǎn)不需要自己拼接。event_msg把運(yùn)行時的一切變成消息event_msg共十二種事件記錄模型上下文之外的運(yùn)行時事實(shí)例如事件記錄的內(nèi)容tool_list_ready實(shí)際發(fā)給模型的完整工具 schemarequest_begin/request_end一次模型請求的開始與終態(tài)含重試詳情approval_decision一次工具審批決策allow / deny / forbiddentoken_usage會話累計(jì)與本次請求的 Token 用量compaction_begin/compaction_end上下文壓縮的觸發(fā)與結(jié)果abort一次用戶中斷及其原因碼subagent父 Trace 中指向子會話的指針hook一次鉤子回答鉤子點(diǎn)、名稱、決策凡是報(bào)告失敗的事件都攜帶同一對錯誤字段error_code是穩(wěn)定、機(jī)器可讀的原因碼渲染層據(jù)此做本地化error_message是原始失敗文本。這個設(shè)計(jì)呼應(yīng)了 PenguinHarness 的一條核心信條錯誤從不以異常形式穿過接口邊界錯誤本身就是消息。stop_reason所有終止記錄共用一套詞匯所有帶終止原因的記錄——模型消息、工具結(jié)果、請求終態(tài)、壓縮終態(tài)、MCP 連接終態(tài)——共用同一個四值枚舉取值含義引擎反應(yīng)completed正常完成繼續(xù)aborted用戶中斷或取消停止產(chǎn)出abort事件交還用戶retryable值得重試的失敗超時、429/5xx、響應(yīng)被截?cái)嗟劝赐吮茈A梯自動重連fatal重試也無法修復(fù)憑據(jù)被拒、確定性 4xx 拒絕停止運(yùn)行交還用戶四值只回答一個問題要不要重試。失敗屬于哪一類看error_code細(xì)節(jié)看error_message。職責(zé)單一整個協(xié)議就不會出現(xiàn)十個地方十種錯誤語義的混亂。origin 與 fidelity路由子 Agent、保真供應(yīng)商細(xì)節(jié)兩個可選字段解決了兩個看似無關(guān)的問題origin子 Agent 的消息路由。當(dāng) Agent 用run_subagent派生子會話時子會話的消息轉(zhuǎn)發(fā)給父級每經(jīng)過一層就在origin鏈?zhǔn)准右粋€子會話 ID由外到內(nèi)。渲染層按這條鏈把消息歸入對應(yīng)的嵌套卡片而帶origin的消息不寫入父 Trace——子會話有自己的 Trace父 Trace 只保留一條subagent指針事件。fidelity供應(yīng)商保真負(fù)載。一些模型回放歷史時要求攜帶逐字節(jié)一致的供應(yīng)商數(shù)據(jù)如思考簽名、加密推理內(nèi)容。fidelity是一個對 PenguinHarness完全不透明的 JSON 對象全鏈路原樣透傳、原樣存儲不改寫、不丟失。這也是 Trace 能無損恢復(fù)會話的前提之一。同一協(xié)議貫穿三條通道 通道使用的子集SDK 邊界session.run的輸出完整model_msg 流式partial_* 全部event_msg落盤的 Tracesession_meta 完整model_msg 全部event_msg不存分片與origin消息Server 的 SSE 推送與 SDK 邊界相同原樣的單行 JSON每條消息在進(jìn)入輸出流的同時追加寫入 Trace因此流序與 Trace 序天然一致。Trace 觀測面板可以直接回放這些消息還原出每一輪的執(zhí)行時間線消息如何在一輪的五個參與者Human、engine、LLM、Environment、Trace之間傳遞、哪些順序有保證官方文檔有專門一頁梳理packages/docs/content/message-flow.zh.md。動手體驗(yàn)用 SDK 消費(fèi) OmniMessage 流想感受協(xié)議的統(tǒng)一性只需幾行代碼。prismshadow/penguin-core導(dǎo)出了協(xié)議的全部類型、構(gòu)造函數(shù)builders和運(yùn)行時判別函數(shù)完整用法見 packages/docs/content/quickstart-sdk.zh.md 與 packages/core/README.mdimport { createAgent, isCompleteModelMessage, userText } from prismshadow/penguin-core; const agent await createAgent({ agentId: default_agent }); const session await agent.createSession({ workspaceDir: process.cwd() }); for await (const output of session.run([userText(列出當(dāng)前目錄的文件)], { approve: async () allow, })) { if (isCompleteModelMessage(output) output.payload.type text) { console.log(output.payload.text); } }循環(huán)中你拿到的就是Trace 里存的內(nèi)容、SSE 里推的內(nèi)容——同一種結(jié)構(gòu)。想深入?yún)f(xié)議逐字段定義官方文檔是最佳入口packages/docs/content/omni-message.zh.md。寫在最后OmniMessage 的哲學(xué)可以濃縮成一句話流出去的、存下來的和模型看到的是同一種結(jié)構(gòu)。它用一個信封、三類消息、四值終止原因和不透明的保真字段同時解決了流式渲染、磁盤存儲與會話恢復(fù)三個看似矛盾的需求也讓一切可觀測、Session 可從 Trace 完整恢復(fù)成了平臺級的承諾。如果你想了解它如何與 ReAct 循環(huán)、壓縮和重連協(xié)作可以繼續(xù)閱讀 packages/docs/content/architecture.zh.md 與 packages/docs/content/agent-loop.zh.md?!久赓M(fèi)下載鏈接】penguin-harness Unified and Stable RSI Platform項(xiàng)目地址: https://gitcode.com/gh_mirrors/pe/penguin-harness創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考