에이전트 프레임워크 v2¶
작성: 2026-05-15 v1 대비 변경: 종합 판정을 코드(synthesize.py)로 이관. LLM은 도메인 해석만 담당.
핵심 아키텍처¶
원자 에이전트 (LLM) synthesize.py (코드) 서술 에이전트 (LLM)
도메인 해석 + 점수화 → 결정론적 종합 판정 → 사람이 읽을 리포트
잘하는 것: 해석 잘하는 것: 일관성 잘하는 것: 글쓰기
못하는 것: 일관된 종합 못하는 것: 해석 못하는 것: 없음
규칙: LLM이 GO/WAIT/PASS를 결정하지 않는다. 코드가 결정한다. LLM은 (1) 도메인별 verdict+score를 생성하고 (2) 코드의 판정을 리포트로 변환한다.
1. 원자 에이전트 표준 출력 스키마¶
모든 도메인 에이전트는 이 스키마로 JSON을 출력:
{
"domain": "chart | flow | material | fundamentals | environment",
"code": "042700",
"name": "한미반도체",
"as_of": "2026-05-15T16:30:00+09:00",
"verdict": "긍정 | 중립 | 부정",
"score": 8,
"confidence": 0.85,
"key_evidence": "3주 베이스 돌파, MARUBOZU 92%, VP POC 380K 위",
"risk_factor": "52주 신고가 근접 저항",
"data_frame": {
"primary_metric": "close",
"value": 420000,
"change_1d": 5.5,
"change_5d": 12.3,
"change_20d": 18.3,
"streak": 3,
"direction": "accelerating"
},
"domain_specific": {}
}
필드 규칙¶
| 필드 | 타입 | 규칙 |
|---|---|---|
| verdict | enum | 긍정/중립/부정. 3값만 허용. |
| score | int | 0~10. 도메인 내부 기준으로 산출. |
| confidence | float | 0.0~1.0. 데이터 충분성/신뢰도. |
| key_evidence | string | 1~2문장. 판정 근거. 수치 포함 필수. |
| risk_factor | string | 1문장. 주요 리스크. null 허용. |
| data_frame | object | 핵심 지표의 변화+누적 프레임. |
| domain_specific | object | 도메인별 추가 필드 (아래 정의). |
도메인별 domain_specific 필드¶
chart:
{
"trend": "상승 | 횡보 | 하락",
"sl": 390000,
"tp": 480000,
"rr_ratio": 2.0,
"sl_basis": "VP HVN 385K + MA20 392K",
"at_peak_signal": false,
"peak_evidence": null,
"structure": "base_breakout | pullback | channel | range"
}
flow:
{
"pattern": "매집 | 추격 | 차익실현 | 전환 | 혼조 | 폭탄",
"dual_buy": true,
"foreign_5d_cum": 850000,
"inst_5d_cum": 120000,
"foreign_20d_cum": -1800000,
"positioning_extreme": false,
"subject_dynamics": "외인 매집 3일째, 기관 동조"
}
material:
{
"catalyst_grade": "S | A | B | C | D",
"structural_grade": "structural | semi_structural | temporary",
"freshness": "Fresh | Aging | Stale",
"freshness_days": 2,
"priced_in": "no | partial | yes",
"propagation": "NVIDIA 매출↑ → HBM 수요↑ → 한미반도체 패키징",
"theme": "AI반도체/HBM"
}
fundamentals:
{
"op_yoy_trend": "가속 | 유지 | 감속 | 적자전환",
"op_yoy_quarters": [32, 45],
"valuation_grade": "저평가 | 적정 | 고평가 | 극단",
"red_flag": false,
"red_flag_detail": null,
"dart_confirmed": true
}
environment:
{
"theme_lifecycle": "EMERGING | ACCELERATING | LEADING | COOLING | RE_ACCELERATING",
"macro_regime": "risk_on_growth | risk_on_rotation | neutral | risk_off",
"bond_equity_conflict": "none | mild | severe",
"crowding": "low | moderate | high",
"sector_rs_rank": 5
}
2. synthesize.py 규칙표¶
거부권 (Veto) — 무조건 적용, 예외 없음¶
| 규칙 | 조건 | 결과 |
|---|---|---|
| VETO_CHART | chart.verdict == "부정" | PASS |
| VETO_RR | chart.rr_ratio < 1.5 | PASS |
| VETO_RED_FLAG | fundamentals.red_flag == true | 최대 WAIT |
교차검증 (X1~X7) — 모순 감지¶
| # | 검증 | 입력 | 차단 조건 |
|---|---|---|---|
| X1 | 채권 vs 주식 | env.bond_equity_conflict | severe → GO 불가 |
| X2 | 컨센서스 과밀 | env.crowding | (단독 비차단) |
| X3 | 촉매 선반영 | material.priced_in | yes → GO 불가 |
| X4 | 차트 vs 수급 괴리 | chart.verdict ↔ flow.verdict | (기록만, 비차단) |
| X5 | 재료 vs 실적 불일치 | material.verdict 긍정 + fund.verdict 부정 | contradiction → GO 불가 |
| X6 | 포지셔닝 극단 | flow.positioning_extreme | true → 사이즈 50% |
| X7 | 과밀+선반영 동시 | X2 high + X3 yes | → GO 불가 |
GO 4조건 — 전부 충족 시 GO¶
| # | 조건 | 입력 |
|---|---|---|
| G1 | 고점 신호 부재 | chart.at_peak_signal == false |
| G2 | SL 확보 (R:R ≥ 1.5) | chart.rr_ratio >= 1.5 |
| G3 | 재료 뒷받침 | material.structural_grade ∈ {structural, semi_structural} |
| G4 | 수급 확인 | flow.dual_buy == true 또는 flow.pattern == "매집" |
최종 판정 매트릭스¶
거부권 발동?
→ YES → PASS 또는 WAIT (규칙에 따라)
→ NO ↓
교차검증 차단?
→ YES → WAIT (차단 사유 명시)
→ NO ↓
GO 4조건 전부 충족 + 가중점수 ≥ 1.2?
→ YES → GO (사이즈: X6에 따라 full 또는 half)
→ NO ↓
GO 3/4 충족 + 가중점수 ≥ 1.0?
→ YES → WAIT (미충족 조건 명시)
→ NO ↓
가중점수 ≥ 0.8?
→ YES → WAIT
→ NO → PASS
가중 점수¶
weighted_score = Σ (domain.score × domain.confidence × domain.weight)
가중치: chart=0.25, flow=0.25, material=0.20, fundamentals=0.15, environment=0.15
score: 0~10 스케일 (각 도메인 에이전트가 산출)
confidence: 0.0~1.0 (데이터 충분성)
3. Claude CLI 워크플로우¶
종목 분석 시¶
스킬 (rs_evening.md 또는 candidate-pipeline):
1. candidate_from_theme.py → 종목 풀 확보
2. 종목별 5개 에이전트 호출 (병렬 가능):
Agent(subagent_type="domain/chart-analyst", prompt="종목 042700 분석...")
→ data/agent_results/YYYYMMDD/042700_chart.json
Agent(subagent_type="domain/flow-analyst", prompt="종목 042700 수급...")
→ data/agent_results/YYYYMMDD/042700_flow.json
Agent(subagent_type="domain/material-analyst", prompt="종목 042700 재료...")
→ data/agent_results/YYYYMMDD/042700_material.json
Agent(subagent_type="domain/fundamentals-analyst", prompt="종목 042700 실적...")
→ data/agent_results/YYYYMMDD/042700_fundamentals.json
Agent(subagent_type="domain/environment-analyst", prompt="종목 042700 환경...")
→ data/agent_results/YYYYMMDD/042700_environment.json
3. synthesize.py 실행 (코드 판정):
scripts/synthesize.py --dir data/agent_results/YYYYMMDD/ --code 042700
→ data/agent_results/YYYYMMDD/verdicts.json
4. 서술 에이전트 호출 (리포트 작성):
Agent(subagent_type="narrator", prompt="verdicts.json을 읽고 리포트 작성...")
→ 리포트 마크다운
시장 전체 분석 시 (장전/장마감/저녁)¶
스킬 (rs_morning_open.md):
1. 데이터 수집 스크립트 (병렬):
fetch_global_assets.py → data/routine_data/global_assets.json
fetch_market_top.py → data/market_top/YYYYMMDD.json
...
2. 시장 에이전트 호출 (순차 — 앞 결과가 뒤 입력):
Agent: global-asset-scanner → data/outputs/YYYYMMDD/mo1_global.json
Agent: sector-transfer-mapper → data/outputs/YYYYMMDD/mo2_sector.json
(mo1 결과를 입력으로 받음)
Agent: overnight-material-grader → data/outputs/YYYYMMDD/mo3_material.json
Agent: signal-synthesizer → data/outputs/YYYYMMDD/mo5_signals.json
(mo1~mo3 전체를 입력으로 받음)
3. morning_view.json 조립 (코드 — 스크립트):
assemble_morning_view.py → data/outputs/YYYYMMDD/morning_view.json
4. 리포트 작성 (에이전트):
Agent: morning-reporter → docs/morning_open/YYYYMMDD_morning_open.md
4. 에이전트 목록 (재구성)¶
도메인 분석 에이전트 (종목별, 5개)¶
| 에이전트 | 질문 | 내부 복잡도 | 산출물 |
|---|---|---|---|
| chart-analyst | "이 차트 구조가 진입에 유리한가?" | C1~C10 통합, mtf_chart_profiler, VP+VSA+구조 | {code}_chart.json |
| flow-analyst | "스마트머니가 사고 있는가, 빠지고 있는가?" | SEN-1~5 통합, 5d/20d 누적, 패턴 분류 | {code}_flow.json |
| material-analyst | "카탈리스트가 구조적인가, 실제 매출에 닿는가?" | NC-3+NC-6+material-validator 통합, 4Q binary | {code}_material.json |
| fundamentals-analyst | "이익이 개선되고 있는가?" | FA-M1~M7 통합, DART 3~4분기 IS, OP YoY | {code}_fundamentals.json |
| environment-analyst | "테마·매크로·섹터가 우호적인가?" | M1+S1+S2 통합, lifecycle, RS, regime | {code}_environment.json |
각 에이전트는 내부적으로 복잡하지만 (기존 원자 에이전트 여러 개의 역할을 통합), 출력은 표준 스키마 하나로 고정됨.
시장 분석 에이전트 (전체 시장, 단계별)¶
| 단계 | 에이전트 | 질문 |
|---|---|---|
| 장전 | global-asset-scanner | 밤사이 글로벌 자산 변화와 한국 영향? |
| 장전 | sector-transfer-mapper | 미장 섹터 → 한국 테마 전이? |
| 장전 | overnight-material-grader | 밤사이 재료 중 오늘 장에 영향 줄 것? |
| 장전 | signal-synthesizer | 오늘 시그널은 무엇이고 종목 연결은? |
| 장마감 | signal-scorecard | 아침 시그널이 맞았나 틀렸나? |
| 장마감 | theme-strength-ranker | 오늘 실제 강했던 테마와 생명주기? |
| 장마감 | discovery-detector | 오늘 새로 등장한 이상 움직임? |
| 저녁 | macro-4axis | 금리/원자재/환율/유동성 4축 환경? |
| 저녁 | material-validator | 각 재료가 구조적인가 일시적인가? |
| 저녁 | theme-scenario-builder | 내일 유력 테마와 시나리오? |
조립/서술 에이전트 (판정 후)¶
| 에이전트 | 역할 |
|---|---|
| morning-reporter | morning_view.json → 장전 마크다운 리포트 |
| postmarket-reporter | post_market_view.json → 장마감 마크다운 리포트 |
| evening-reporter | evening_view.json → 저녁 마크다운 리포트 |
5. 역할 분리 요약¶
| 역할 | 누가 | 왜 |
|---|---|---|
| 도메인 해석 | LLM (에이전트) | 차트 패턴 읽기, 수급 패턴 분류 등은 LLM이 잘함 |
| 점수 산출 | LLM (에이전트) | 도메인 내부 기준으로 0~10 채점은 LLM이 할 수 있음 |
| 종합 판정 | 코드 (synthesize.py) | 5개 점수를 합산하여 GO/WAIT/PASS — 일관성 필요 |
| 교차 모순 검출 | 코드 (synthesize.py) | X1~X7 규칙 — 결정론적이어야 함 |
| 리포트 작성 | LLM (서술 에이전트) | 코드 판정을 사람이 읽을 형태로 — LLM이 잘함 |
| PM 최종 결정 | PM | GO여도 PM이 실행 여부 결정 |
|
||
| synthesize.py verdict | ||
| ↓ (다음날) | ||
| signal_scorecard에서 HIT/MISS 판정 | ||
| ↓ (주간) | ||
| accuracy_log.jsonl 집계 | ||
| ↓ (월간) | ||
| 가중치/임계값 조정 검토 (PM 승인 후 synthesize.py 수정) | ||
| ``` |