SDK 教學 · 2 / 10
建立並延續對話
當產品要自行掌控互動介面,但仍希望由 Heddle 負責耐久的對話語意時,就從 terminal quickstart 移到 conversation engine。
客製化深度
層級 2 · 產品端對話流程
託管深度
Process 內的 Node.js host
文件狀態
支援的 SDK 邊界
前置假設
- 產品自行決定何時建立對話,以及何時送出使用者訊息。
- 每個進行中的 turn 由單一 process 負責;遠端重新連線會在 hosting 章節加入。
- 現階段可以接受預設的本機 session repository。
- 持久化 message、turn、continuation state、compaction metadata 與 session lease。
- 執行 model/tool loop,並在每個 turn 後回傳 structured result。
- 從 stateRoot 解析預設的 session、trace、memory 與 artifact 路徑。
- 把穩定的 product conversation ID 對應到 Heddle session ID,並執行 access policy。
- 決定何時建立、重新開啟、重新命名、封存或刪除 session。
- 在產品原本的 presentation layer 呈現 activity 與 result。
在 host boundary 建立一次 engine
請在 application composition root 建立 engine,而不是每個 request 都重新建立。Engine 會解析一次 storage 與 extension dependencies,並在 session 與 turn service 之間共用。
import { join } from 'node:path'
import {
createConversationEngine,
createConversationTextHost,
} from '@roackb2/heddle'
const workspaceRoot = process.cwd()
const stateRoot = join(workspaceRoot, '.heddle')
const engine = createConversationEngine({
workspaceRoot,
stateRoot,
model: process.env.HEDDLE_MODEL ?? 'gpt-5.4',
reasoningEffort: 'medium',
})Heddle 預設會推導出:
stateRoot/chat-sessions.catalog.json的 session catalog;stateRoot/chat-sessions下的 session body;stateRoot/memory下的 memory;stateRoot/traces下的 trace;stateRoot/artifacts下的 artifact。
建立可持久化的 session
所有 session operations 都是非同步:
const session = await engine.sessions.create({
name: 'Product assistant',
})請把 session.id 儲存在產品自己的 conversation record 旁。Heddle 刻意不接管你的 account、tenant 或 domain relationships。
送出多個使用者 turn
每一則新的使用者訊息都使用 submit,並沿用同一個 session ID:
const textHost = createConversationTextHost()
const first = await engine.turns.submit({
sessionId: session.id,
prompt: 'Summarize the workspace in three bullets.',
host: textHost.host,
})
textHost.renderTurnResult(first)
const second = await engine.turns.submit({
sessionId: session.id,
prompt: 'Expand the second bullet with supporting evidence.',
host: textHost.host,
})
textHost.renderTurnResult(second)Heddle 會重新載入持久化歷史、在必要時執行 compaction、為 turn 取得 session lease,最後儲存新的 messages。不要在產品端重建歷史再貼進每個 prompt;那會形成另一套彼此競爭的 conversation model。
重新開啟既有 session
const existing = await engine.sessions.readExisting(savedHeddleSessionId)
if (!existing) {
throw new Error('Conversation no longer exists')
}檢查持久化狀態時請使用 readExisting。它與相容性導向的 read 不同,不會在空 repository 中具體化 Heddle 的 fallback session。
其他支援的 lifecycle operations 包含 listCatalog、rename、setPinned、setArchived 與 delete。請先在這些 calls 外完成使用者授權,解析出已授權的 product record 後,才查找對應的 Heddle session。
Submit 與 continue 的差異
engine.turns.submit({ sessionId, prompt })會在現有對話中開始新的使用者 turn。engine.turns.continue({ sessionId })會在中斷或既有 run 後,重新使用上一個 continuation prompt。- 若 session 沒有可延續的 prior run,
continue會丟出錯誤。
不要把 continue 當成一般的第二則訊息 API。
何時加入 hosted run layer
Conversation engine call 會等待單一 process 內的 turn 完成。若 turn 必須超過 HTTP request 的生命週期、需要可定址的 cancellation 或 approval lifecycle,或需要讓 client 中斷後重播排序事件,就加入 ConversationRunService。