session_save_ledger
Records completed work sessions in an immutable audit trail for permanent tracking of project progress, decisions, and changes.
Instructions
Save an immutable session log entry to the session ledger. Use this at the END of each work session to record what was accomplished. The ledger is append-only — entries cannot be updated or deleted. This creates a permanent audit trail of all agent work sessions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | Project identifier (e.g. 'bcba-private', 'my-app'). Used to group and filter sessions. | |
| conversation_id | Yes | Unique conversation/session identifier. | |
| summary | Yes | Brief summary of what was accomplished in this session. | |
| todos | No | Optional list of open TODO items remaining after this session. | |
| files_changed | No | Optional list of files created or modified during this session. | |
| decisions | No | Optional list of key decisions made during this session. |
Implementation Reference
- The implementation of the session_save_ledger tool handler. It extracts keywords, persists the ledger entry via the storage backend, and asynchronously generates an embedding for the entry if an API key is provided.
export async function sessionSaveLedgerHandler(args: unknown) { if (!isSessionSaveLedgerArgs(args)) { throw new Error("Invalid arguments for session_save_ledger"); } const { project, conversation_id, summary, todos, files_changed, decisions } = args; const storage = await getStorage(); console.error(`[session_save_ledger] Saving ledger entry for project="${project}"`); // Auto-extract keywords from summary + decisions for knowledge accumulation const combinedText = [summary, ...(decisions || [])].join(" "); const keywords = toKeywordArray(combinedText); console.error(`[session_save_ledger] Extracted ${keywords.length} keywords: ${keywords.slice(0, 5).join(", ")}...`); // Save via storage backend const result = await storage.saveLedger({ project, conversation_id, summary, user_id: PRISM_USER_ID, todos: todos || [], files_changed: files_changed || [], decisions: decisions || [], keywords, }); // ─── Fire-and-forget embedding generation ─── if (GOOGLE_API_KEY && result) { const embeddingText = [summary, ...(decisions || [])].join("\n"); const savedEntry = Array.isArray(result) ? result[0] : result; const entryId = (savedEntry as any)?.id; if (entryId) { generateEmbedding(embeddingText) .then(async (embedding) => { await storage.patchLedger(entryId, { embedding: JSON.stringify(embedding), }); console.error(`[session_save_ledger] Embedding saved for entry ${entryId}`); }) .catch((err) => { console.error(`[session_save_ledger] Embedding generation failed (non-fatal): ${err.message}`); }); } } return { content: [{ type: "text", text: `✅ Session ledger saved for project "${project}"\n` + `Summary: ${summary}\n` + (todos?.length ? `TODOs: ${todos.length} items\n` : "") + (files_changed?.length ? `Files changed: ${files_changed.length}\n` : "") + (decisions?.length ? `Decisions: ${decisions.length}\n` : "") + (GOOGLE_API_KEY ? `📊 Embedding generation queued for semantic search.\n` : "") + `\nRaw response: ${JSON.stringify(result)}`, }], isError: false, }; } - src/tools/sessionMemoryDefinitions.ts:5-6 (registration)Tool definition and input schema registration for session_save_ledger.
export const SESSION_SAVE_LEDGER_TOOL: Tool = { name: "session_save_ledger",