run_self_distill
Analyzes recent agent conversations to detect success or failure signals, then generates and persists improvement lessons that prevent future mistakes without human feedback.
Instructions
Run the self-distillation agent to auto-evaluate recent agent sessions and generate improvement lessons without human feedback. Reads conversation logs, detects success/failure signals, and persists lessons.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dryRun | No | If true, analyzes but does not persist lessons | |
| limit | No | Max conversation logs to process (default 20) | |
| model | No | LLM model to use for analysis (requires ANTHROPIC_API_KEY) |
Implementation Reference
- scripts/self-distill-agent.js:397-483 (handler)Main handler function for the run_self_distill tool. Reads conversation logs, detects outcome signals (errors, test failures, corrections, successes), classifies outcomes as positive/negative/neutral, generates lessons (heuristically or via LLM), persists them as lessons, and returns a manifest.
async function runSelfDistill({ dryRun = false, limit = 20, model } = {}) { const startedAt = new Date().toISOString(); const logPaths = discoverConversationLogs({ limit }); const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY); const analysisMode = hasApiKey ? 'llm' : 'heuristic'; const allLessons = []; let sessionsProcessed = 0; let sessionsSkipped = 0; for (const logPath of logPaths) { const entries = readJsonl(logPath); if (entries.length === 0) { sessionsSkipped++; continue; } // Treat each log file as one conversation session const conversationWindow = entries.slice(-30); // last 30 messages max const signals = detectOutcomeSignals(conversationWindow); const outcome = classifyOutcome(signals); if (outcome === 'neutral') { sessionsSkipped++; continue; } sessionsProcessed++; let lessons; if (hasApiKey) { lessons = await generateLlmLessons(conversationWindow, model); // Fall back to heuristic if LLM returns nothing if (!lessons || lessons.length === 0) { lessons = generateHeuristicLessons(conversationWindow, signals); } } else { lessons = generateHeuristicLessons(conversationWindow, signals); } for (const lesson of lessons) { if (!dryRun) { createLesson({ feedbackId: null, signal: lesson.signal, inferredLesson: lesson.action.description, triggerMessage: lesson.trigger.condition, priorSummary: lesson.evidence || '', confidence: Math.round((lesson.confidence || 0.5) * 100), tags: ['self-distill', lesson.signal], metadata: { source: 'self-distill-agent', analysisMode, triggerType: lesson.trigger.type, actionType: lesson.action.type, logPath, }, }); } allLessons.push(lesson); } } const manifest = { id: buildStableId('distill'), startedAt, completedAt: new Date().toISOString(), dryRun, analysisMode, sessionsProcessed, sessionsSkipped, lessonsGenerated: allLessons.length, logPaths, lessons: allLessons.map((l) => ({ signal: l.signal, trigger: l.trigger, action: l.action, confidence: l.confidence, })), }; if (!dryRun) { writeRunManifest(manifest); } return manifest; } - adapters/mcp/server-stdio.js:1087-1090 (registration)MCP tool registration — maps 'run_self_distill' string to a require() of the self-distill-agent module, calling runSelfDistill with dryRun, limit, and model args from the MCP request.
case 'run_self_distill': { const { runSelfDistill } = require('../../scripts/self-distill-agent'); return toTextResult(await runSelfDistill({ dryRun: args.dryRun, limit: args.limit, model: args.model })); } - getSelfDistillStatus helper — reads persisted run manifests and returns summary of last run and total stats. Exported and callable via the companion 'self_distill_status' MCP tool.
function getSelfDistillStatus() { const runs = readRunManifests(); if (runs.length === 0) return null; const lastRun = runs[runs.length - 1]; return { lastRunId: lastRun.id, lastRunAt: lastRun.completedAt, totalRuns: runs.length, totalLessons: runs.reduce((sum, r) => sum + (r.lessonsGenerated || 0), 0), lastAnalysisMode: lastRun.analysisMode, lastSessionsProcessed: lastRun.sessionsProcessed, lastLessonsGenerated: lastRun.lessonsGenerated, }; } - Module exports — runSelfDistill, getSelfDistillStatus, detectOutcomeSignals, discoverConversationLogs, classifyOutcome, generateHeuristicLessons, and SELF_DISTILL_RUNS_PATH are publicly exposed.
module.exports = { runSelfDistill, getSelfDistillStatus, detectOutcomeSignals, discoverConversationLogs, classifyOutcome, generateHeuristicLessons, SELF_DISTILL_RUNS_PATH, };