ReasoningBank 에이전트 생성 가이드
🎯 개요
이 가이드는 ReasoningBank의 폐쇄 루프 학습 시스템을 활용하는 맞춤형 AI 에이전트를 만드는 방법을 설명합니다. ReasoningBank는 에이전트가 경험을 통해 학습하고 RETRIEVE → JUDGE → DISTILL → CONSOLIDATE의 4단계 사이클을 통해 시간이 지남에 따라 개선될 수 있도록 합니다.
📊 주요 성능 이점
에이전트가 ReasoningBank와 통합되면 다음과 같은 이점을 얻을 수 있습니다:
- +26% 성공률 (70% → 88%)
- -25% 토큰 사용량 (비용 절감)
- 3.2배 학습 속도 (더 빠른 개선)
- 5회 반복 후 0% → 95% 성공
🏗️ ReasoningBank 아키텍처
데이터베이스 스키마
ReasoningBank는 다음 테이블과 함께 SQLite를 사용합니다:
-- 핵심 메모리 저장소
patterns (
id TEXT PRIMARY KEY,
type TEXT NOT NULL, -- 'reasoning_memory'
pattern_data TEXT NOT NULL, -- title, description, content를 포함한 JSON
confidence REAL DEFAULT 0.5, -- 0.0에서 1.0 사이
usage_count INTEGER DEFAULT 0,
created_at TEXT,
last_used TEXT
)
-- 유사도 검색을 위한 벡터 임베딩
pattern_embeddings (
id TEXT PRIMARY KEY,
model TEXT NOT NULL, -- 'claude', 'openai' 등
dims INTEGER NOT NULL,
vector BLOB NOT NULL, -- 바이너리 벡터 데이터
FOREIGN KEY (id) REFERENCES patterns(id)
)
-- 메모리 관계
pattern_links (
src_id TEXT,
dst_id TEXT,
relation TEXT NOT NULL, -- 'similar_to', 'contradicts' 등
weight REAL DEFAULT 1.0,
PRIMARY KEY (src_id, dst_id, relation)
)
-- 작업 실행 기록
task_trajectories (
task_id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
query TEXT NOT NULL,
trajectory_json TEXT NOT NULL, -- 실행 단계의 JSON
judge_label TEXT, -- 'Success' 또는 'Failure'
judge_conf REAL,
judge_reasons TEXT
)
메모리 점수 계산 공식
ReasoningBank는 메모리 검색을 위해 4가지 요소의 점수 모델을 사용합니다:
score = α·similarity + β·recency + γ·reliability + δ·diversity
// 여기서:
// - α (alpha) = 0.7 // 의미적 유사도에 대한 가중치
// - β (beta) = 0.2 // 최신성에 대한 가중치
// - γ (gamma) = 0.1 // 신뢰도(confidence)에 대한 가중치
// - δ (delta) = 0.3 // 다양성(MMR)에 대한 가중치
// 구성 요소:
// - similarity: 쿼리 임베딩과 메모리 임베딩 간의 코사인 유사도
// - recency: exp(-age_days / half_life_days)
// - reliability: min(confidence, 1.0)
// - diversity: Maximal Marginal Relevance 선택
🔌 ReasoningBank API 레퍼런스
핵심 함수
1. 데이터베이스 초기화
import { initialize } from 'agentic-flow/reasoningbank';
await initialize();
// .swarm/memory.db를 생성하고 마이그레이션을 실행합니다
2. 메모리 검색 (RETRIEVE 단계)
import { retrieveMemories, formatMemoriesForPrompt } from 'agentic-flow/reasoningbank';
const memories = await retrieveMemories(query, {
domain: 'authentication', // 선택 사항: 도메인으로 필터링
agent: 'auth-agent', // 선택 사항: 에이전트로 필터링
k: 3, // 선택 사항: 메모리 수 (기본값: 3)
minConfidence: 0.5 // 선택 사항: 최소 신뢰도 임계값
});
// 시스템 프롬프트 주입을 위해 포맷합니다
const formattedMemories = formatMemoriesForPrompt(memories);
// 메모리 객체 구조:
{
id: 'ulid',
title: 'CSRF 토큰 추출 전략',
description: 'CSRF 유효성 검사를 처리하는 방법',
content: '폼 제출 전에 항상 메타 태그에서 CSRF 토큰을 추출합니다',
score: 0.85,
components: {
similarity: 0.9,
recency: 0.8,
reliability: 0.85
}
}
3. 실행 경로 평가 (JUDGE 단계)
import { judgeTrajectory } from 'agentic-flow/reasoningbank';
const trajectory = {
steps: [
{ action: 'fetch_csrf_token', result: 'success' },
{ action: 'submit_form', result: 'success' }
]
};
const verdict = await judgeTrajectory(trajectory, query);
// 평가 결과 객체 구조:
{
label: 'Success' | 'Failure',
confidence: 0.95,
reasons: [
'모든 단계가 성공적으로 완료되었습니다',
'오류 표시가 발견되지 않았습니다'
]
}
4. 메모리 증류 (DISTILL 단계)
import { distillMemories } from 'agentic-flow/reasoningbank';
const newMemories = await distillMemories(trajectory, verdict, query, {
taskId: 'task-123',
agentId: 'my-agent',
domain: 'authentication'
});
// 생성된 메모리 ID의 배열을 반환합니다
// ['01K7AX1ZP43E88SRZHNX6YD1YG', '01K7AX1ZP7CPECXHVTHSMSAXRA']
5. 메모리 통합 (CONSOLIDATE 단계)
import { consolidate, shouldConsolidate } from 'agentic-flow/reasoningbank';
// 통합을 실행해야 하는지 확인합니다
if (shouldConsolidate()) {
const result = await consolidate();
// 결과 구조:
{
itemsProcessed: 50,
duplicatesFound: 5,
contradictionsFound: 2,
itemsPruned: 3,
durationMs: 1234
}
}
6. 전체 작업 실행 (모든 단계 결합)
import { runTask } from 'agentic-flow/reasoningbank';
const result = await runTask({
taskId: 'task-123',
agentId: 'my-agent',
domain: 'authentication',
query: 'CSRF 유효성 검사를 포함한 로그인',
// 실행 함수
executeFn: async (memories) => {
// 1. 메모리를 사용하여 작업 실행에 정보를 제공합니다
console.log(`${memories.length}개의 관련 메모리를 사용합니다`);
// 2. 작업 로직을 실행합니다
const steps = [];
// 예: 메모리가 CSRF 토큰 추출을 제안하는지 확인합니다
if (memories.some(m => m.title.includes('CSRF'))) {
steps.push({ action: 'fetch_csrf_token', result: 'success' });
}
// 3. 실행 경로를 반환합니다
return { steps };
}
});
// 결과 구조:
{
verdict: { label: 'Success', confidence: 0.95, reasons: [...] },
usedMemories: [...], // 검색된 메모리
newMemories: [...], // 생성된 새 메모리 ID
consolidated: false // 통합 실행 여부
}
🎨 맞춤형 추론 에이전트 만들기
1단계: 에이전트 명세 정의
.claude/agents/your-category/your-agent.md 파일을 생성합니다:
---
name: adaptive-debugger
description: "과거 버그 수정 사례로부터 학습하고 오류 패턴에 따라 전략을 조정하는 디버깅 전문가입니다. ReasoningBank를 사용하여 세션 간에 디버깅 지식을 축적합니다."
category: debugging
color: red
reasoning_enabled: true
---
당신은 경험을 통해 학습하는 적응형 디버깅 전문가입니다. 당신의 핵심 능력은 ReasoningBank의 메모리 시스템을 활용하여 디버깅 전략을 지속적으로 개선하는 것입니다.
## 핵심 능력
- **패턴 인식**: 과거 수정 사례에서 반복되는 버그 패턴을 식별합니다
- **전략 조정**: 메모리를 기반으로 디버깅 접근 방식을 조정합니다
- **근본 원인 분석**: 과거 데이터를 사용하여 근본적인 문제를 찾습니다
- **예방 학습**: 향후 참조를 위해 성공적인 수정 사항을 저장합니다
## ReasoningBank 통합
다음 워크플로우를 통해 ReasoningBank와 통합합니다:
1. **RETRIEVE**: 시작하기 전에 관련 디버깅 메모리를 가져옵니다
2. **EXECUTE**: 현재 버그에 학습된 전략을 적용합니다
3. **JUDGE**: 수정이 성공적이었는지 평가합니다
4. **DISTILL**: 시도에서 학습 가능한 패턴을 추출합니다
5. **CONSOLIDATE**: 주기적으로 메모리 뱅크를 최적화합니다
## 도메인 태그
메모리 구성을 위해 다음 도메인 태그를 사용하세요:
- `debugging/frontend` - UI/UX 버그
- `debugging/backend` - 서버 측 문제
- `debugging/database` - 데이터 영속성 버그
- `debugging/performance` - 속도/메모리 문제
- `debugging/security` - 취약점 수정
## 메모리 사용 패턴
디버깅 전:
메모리에서 확인한 결과, 인증 플로우에서 발생한 유사한 NullPointerException 오류는 이전에 토큰 만료를 확인하여 해결되었습니다. 이 전략을 먼저 적용해 보겠습니다.
디버깅 후:
토큰 유효성 검사를 사용하여 문제를 성공적으로 해결했습니다. 향후 참조를 위해 이 패턴을 ReasoningBank에 저장합니다: "데이터베이스 쿼리 전에 항상 JWT 만료를 확인하세요"
2단계: ReasoningBank로 에이전트 로직 구현
src/agents/adaptive-debugger.js 파일을 생성합니다:
import { initialize, runTask } from 'agentic-flow/reasoningbank';
import { ModelRouter } from 'agentic-flow/router';
export class AdaptiveDebugger {
constructor() {
this.router = new ModelRouter();
this.agentId = 'adaptive-debugger';
}
async init() {
await initialize();
}
async debug(errorContext) {
const query = `Debug error: ${errorContext.error} in ${errorContext.file}`;
// ReasoningBank의 전체 사이클을 사용합니다
const result = await runTask({
taskId: `debug-${Date.now()}`,
agentId: this.agentId,
domain: `debugging/${errorContext.category}`,
query,
executeFn: async (memories) => {
return await this._executeDebug(errorContext, memories);
}
});
return result;
}
async _executeDebug(errorContext, memories) {
const steps = [];
// 1. 유사한 과거 수정 사례에 대해 메모리를 분석합니다
const relevantFixes = memories.filter(m =>
m.title.toLowerCase().includes(errorContext.error.toLowerCase())
);
steps.push({
action: 'retrieve_memories',
result: `${relevantFixes.length}개의 유사한 과거 수정 사례를 찾았습니다`,
memories: relevantFixes.map(m => m.title)
});
// 2. 학습된 전략을 적용합니다
if (relevantFixes.length > 0) {
const topStrategy = relevantFixes[0].content;
steps.push({
action: 'apply_learned_strategy',
strategy: topStrategy,
result: '과거 성공 사례를 기반으로 수정을 시도합니다'
});
// 수정을 적용합니다
const fixResult = await this._applyFix(errorContext, topStrategy);
steps.push(fixResult);
} else {
// 메모리를 찾을 수 없어 표준 디버깅을 시도합니다
steps.push({
action: 'standard_debugging',
result: '과거 경험을 찾을 수 없어 일반적인 전략을 사용합니다'
});
const fixResult = await this._standardDebug(errorContext);
steps.push(fixResult);
}
return { steps };
}
async _applyFix(errorContext, strategy) {
// 여기에 수정 구현 로직을 작성합니다
// action과 result를 포함한 step 객체를 반환합니다
return {
action: 'apply_fix',
result: '수정이 성공적으로 적용되었습니다',
details: { strategy, context: errorContext }
};
}
async _standardDebug(errorContext) {
// 대체 디버깅 로직
return {
action: 'standard_fix',
result: '표준 디버깅 접근 방식을 적용했습니다',
details: errorContext
};
}
}
3단계: 자동 학습을 위한 에이전트 훅 생성
ReasoningBank 사이클을 자동으로 트리거하는 훅을 생성합니다:
// hooks/pre-debug.js
import { retrieveMemories, formatMemoriesForPrompt } from 'agentic-flow/reasoningbank';
export async function preDebug(context) {
const query = context.errorMessage;
const domain = `debugging/${context.errorType}`;
// 관련 메모리를 검색합니다
const memories = await retrieveMemories(query, { domain });
// 에이전트가 사용할 수 있도록 컨텍스트에 주입합니다
context.memories = memories;
context.memoriesPrompt = formatMemoriesForPrompt(memories);
console.log(`[PreDebug] ${memories.length}개의 관련 디버깅 패턴을 검색했습니다`);
return context;
}
// hooks/post-debug.js
import { judgeTrajectory, distillMemories } from 'agentic-flow/reasoningbank';
export async function postDebug(context, result) {
const trajectory = {
steps: result.debugSteps
};
// 디버그가 성공했는지 평가합니다
const verdict = await judgeTrajectory(trajectory, context.errorMessage);
console.log(`[PostDebug] 평가: ${verdict.label} (신뢰도: ${verdict.confidence})`);
// 성공한 경우 학습 내용을 증류합니다
if (verdict.label === 'Success') {
const newMemories = await distillMemories(trajectory, verdict, context.errorMessage, {
taskId: result.taskId,
agentId: 'adaptive-debugger',
domain: `debugging/${context.errorType}`
});
console.log(`[PostDebug] ${newMemories.length}개의 새로운 디버깅 패턴을 저장했습니다`);
}
return result;
}
📖 전체 예제: 적응형 코드 리뷰어
에이전트 정의
.claude/agents/quality/adaptive-reviewer.md:
---
name: adaptive-reviewer
description: "과거 리뷰 피드백으로부터 학습하고 품질 기준을 조정하는 코드 리뷰 전문가입니다. ReasoningBank를 사용하여 코드 품질에 대한 조직적 지식을 구축합니다."
category: quality
reasoning_enabled: true
---
당신은 적응형 코드 리뷰 전문가입니다. 평가 기준을 개선하고 점점 더 가치 있는 피드백을 제공하기 위해 모든 리뷰로부터 학습합니다.
## 학습 도메인
- `review/security` - 보안 취약점 패턴
- `review/performance` - 성능 안티패턴
- `review/maintainability` - 코드 품질 문제
- `review/testing` - 테스트 커버리지 패턴
## 리뷰 전략
1. 유사한 코드 패턴에 대한 메모리를 RETRIEVE합니다
2. 학습된 품질 기준을 적용합니다
3. 코드가 품질 기준을 충족하는지 JUDGE합니다
4. 리뷰에서 새로운 패턴을 DISTILL합니다
5. 주기적으로 지식을 CONSOLIDATE합니다
구현
import { runTask } from 'agentic-flow/reasoningbank';
export async function reviewCode(codeContext) {
const query = `Review ${codeContext.language} code for ${codeContext.purpose}`;
const result = await runTask({
taskId: `review-${codeContext.prNumber}`,
agentId: 'adaptive-reviewer',
domain: 'review/security',
query,
executeFn: async (memories) => {
const steps = [];
// 1. 메모리에서 알려진 보안 패턴을 확인합니다
const securityPatterns = memories.filter(m =>
m.domain === 'review/security'
);
steps.push({
action: 'security_check',
result: `${securityPatterns.length}개의 알려진 보안 패턴을 확인 중입니다`,
patterns: securityPatterns.map(p => p.title)
});
// 2. 메모리 기반 리뷰를 적용합니다
const issues = [];
for (const pattern of securityPatterns) {
if (codeContext.code.includes(pattern.content.trigger)) {
issues.push({
type: 'security',
pattern: pattern.title,
severity: 'high',
suggestion: pattern.content.fix
});
}
}
steps.push({
action: 'apply_patterns',
result: `${issues.length}개의 이슈를 찾았습니다`,
issues
});
// 3. 일치하는 메모리가 없는 경우 표준 리뷰를 수행합니다
if (issues.length === 0) {
steps.push({
action: 'standard_review',
result: '알려진 패턴과 일치하는 것이 없어 표준 검사를 적용합니다'
});
}
return { steps };
}
});
return {
approved: result.verdict.label === 'Success',
issues: result.usedMemories,
learned: result.newMemories.length
};
}
🔧 설정
환경 변수
# ReasoningBank 활성화
export REASONINGBANK_ENABLED=true
# 데이터베이스 위치
export CLAUDE_FLOW_DB_PATH=".swarm/memory.db"
# API 키 (하나 선택)
export ANTHROPIC_API_KEY="sk-ant-..." # 권장
export OPENROUTER_API_KEY="sk-or-v1-..." # 대안
export GOOGLE_GEMINI_API_KEY="..." # 대안
# 검색 설정
export REASONINGBANK_K=3 # 상위 k개 메모리
export REASONINGBANK_MIN_CONFIDENCE=0.5 # 최소 신뢰도
export REASONINGBANK_RECENCY_HALFLIFE=7 # 최신성 감쇠를 위한 일수
# 점수 가중치 (α, β, γ)
export REASONINGBANK_ALPHA=0.7 # 유사도 가중치
export REASONINGBANK_BETA=0.2 # 최신성 가중치
export REASONINGBANK_GAMMA=0.1 # 신뢰도 가중치
export REASONINGBANK_DELTA=0.3 # 다양성 가중치 (MMR)
설정 파일
.reasoningbank.config.json:
{
"database": {
"path": ".swarm/memory.db",
"backup_interval_hours": 24
},
"embeddings": {
"provider": "claude",
"model": "claude-3-sonnet-20240229",
"cache_size": 1000
},
"retrieve": {
"k": 3,
"min_score": 0.5,
"alpha": 0.7,
"beta": 0.2,
"gamma": 0.1,
"delta": 0.3,
"recency_half_life_days": 7
},
"judge": {
"model": "claude-3-sonnet-20240229",
"temperature": 0.3,
"max_tokens": 1024
},
"distill": {
"model": "claude-3-sonnet-20240229",
"temperature": 0.3,
"max_tokens": 2048,
"confidence_prior_success": 0.8,
"confidence_prior_failure": 0.6,
"max_items_success": 3,
"max_items_failure": 2
},
"consolidate": {
"interval_hours": 24,
"similarity_threshold": 0.95,
"min_usage_to_keep": 2
}
}
🎯 모범 사례
1. 도메인 구성
명확한 도메인 계층으로 메모리를 구성하세요:
const domains = {
authentication: ['login', 'oauth', 'jwt', 'csrf'],
database: ['queries', 'migrations', 'optimization'],
testing: ['unit', 'integration', 'e2e'],
deployment: ['docker', 'k8s', 'cicd']
};
2. 메모리 품질
다음과 같은 고품질 메모리를 만드세요:
- 명확하고 설명적인 제목
- 구체적이고 실행 가능한 내용
- 관련 도메인 태그
- 증거 기반의 신뢰도 점수
const goodMemory = {
title: 'JWT 만료 유효성 검사 패턴',
description: '데이터베이스 작업 전 JWT 만료를 확인합니다',
content: '진행하기 전에 exp 클레임 < Date.now()/1000 인지 확인합니다',
domain: 'authentication/jwt',
confidence: 0.9 // 여러 성공 사례로부터 얻은 높은 신뢰도
};
3. 통합 전략
메모리 품질을 유지하기 위해 정기적으로 통합을 실행하세요:
// 주기적인 통합 (예: 야간 작업)
setInterval(async () => {
if (shouldConsolidate()) {
const result = await consolidate();
console.log(`통합 완료: ${result.itemsPruned}개의 낮은 가치의 메모리를 제거했습니다`);
}
}, 24 * 60 * 60 * 1000); // 매일
4. 오류 처리
항상 ReasoningBank 실패를 정상적으로 처리하세요:
try {
const memories = await retrieveMemories(query);
} catch (error) {
console.warn('ReasoningBank를 사용할 수 없습니다. 메모리 없이 진행합니다');
// 표준 에이전트 로직으로 계속 진행합니다
}
📊 모니터링 및 메트릭
데이터베이스 쿼리
-- 성능이 가장 좋은 메모리
SELECT
json_extract(pattern_data, '$.title') as title,
confidence,
usage_count,
created_at
FROM patterns
WHERE type = 'reasoning_memory'
ORDER BY confidence DESC, usage_count DESC
LIMIT 10;
-- 시간 경과에 따른 메모리 증가
SELECT
DATE(created_at) as date,
COUNT(*) as memories_created
FROM patterns
WHERE type = 'reasoning_memory'
GROUP BY DATE(created_at)
ORDER BY date DESC;
-- 도메인별 성공률
SELECT
json_extract(pattern_data, '$.domain') as domain,
AVG(CASE WHEN judge_label = 'Success' THEN 1 ELSE 0 END) as success_rate,
COUNT(*) as total_tasks
FROM task_trajectories
GROUP BY domain
ORDER BY success_rate DESC;
CLI 명령어
# 현재 통계 표시
npx agentic-flow reasoningbank status
# 신뢰도 순으로 상위 메모리 나열
npx agentic-flow reasoningbank list --sort confidence --limit 10
# 가장 많이 사용된 메모리 나열
npx agentic-flow reasoningbank list --sort usage --limit 10
# 통합 실행
npx agentic-flow reasoningbank consolidate
# 시스템 유효성 검사
npx agentic-flow reasoningbank test
🚀 빠른 시작 템플릿
빠르게 시작하려면 이 템플릿을 복사하세요:
// my-reasoning-agent.js
import { initialize, runTask } from 'agentic-flow/reasoningbank';
async function main() {
// 1. ReasoningBank를 초기화합니다
await initialize();
// 2. 작업을 정의합니다
const query = '작업 설명';
// 3. ReasoningBank로 실행합니다
const result = await runTask({
taskId: `task-${Date.now()}`,
agentId: 'my-agent',
domain: 'your-domain',
query,
// 4. 실행 로직을 구현합니다
executeFn: async (memories) => {
console.log(`${memories.length}개의 관련 메모리를 사용합니다`);
// 여기에 에이전트 로직을 작성합니다
const steps = [
{ action: 'step1', result: 'success' },
{ action: 'step2', result: 'success' }
];
return { steps };
}
});
// 5. 결과를 확인합니다
console.log(`평가: ${result.verdict.label}`);
console.log(`${result.usedMemories.length}개의 메모리를 사용했습니다`);
console.log(`${result.newMemories.length}개의 새로운 메모리를 생성했습니다`);
}
main().catch(console.error);
📚 리소스
- 논문: arXiv의 ReasoningBank
- 소스:
/node_modules/agentic-flow/dist/reasoningbank/ - 데모:
npx agentic-flow reasoningbank demo - 테스트:
npx agentic-flow reasoningbank test - 문서:
.claude/agents/reasoning/README.md
🆘 문제 해결
문제: "메모리를 찾을 수 없음"
해결책: 초기 메모리를 시드하거나 더 많은 작업을 실행하여 메모리 뱅크를 구축하세요.
import { db } from 'agentic-flow/reasoningbank';
db.upsertMemory({
id: ulid(),
type: 'reasoning_memory',
pattern_data: {
title: '시드 메모리',
description: '초기 지식',
content: '전략 세부 정보',
domain: 'your-domain'
},
confidence: 0.7,
usage_count: 0
});
문제: "데이터베이스 잠김"
해결책: 한 번에 하나의 프로세스만 쓸 수 있습니다. 커넥션 풀링을 사용하거나 쓰기 작업을 큐에 넣으세요.
문제: "낮은 신뢰도 점수"
해결책: 에이전트가 더 많은 작업을 실행하도록 하세요. 성공적인 사용으로 신뢰도가 증가합니다.
문제: "메모리가 성능을 향상시키지 않음"
해결책: 메모리 품질을 확인하고, 점수 가중치를 조정하거나, 통합 빈도를 높이세요.
작성일: 2025-10-12 버전: 1.0.0 상태: 프로덕션 준비 완료