에이전트 JSON 스키마 템플릿: LLM 출력 표준화로 분석→예측→결정 “끊김” 없이 연결하기
최종 수정: 작성자: Finyul
프롬프트는 잘 짰는데 결과가 들쭉날쭉해서 시스템화가 막힌다면, 문제는 대개 모델이 아니라 출력 규격(에이전트 JSON 스키마)이 없습니다. 이 글은 분석→예측→결정 파이프라인을 JSON 스키마(데이터 계약)로 고정해 연결·검증·로깅·리플레이까지 가능하게 만드는 “복붙용 템플릿”을 제공합니다.
전체 폐루프(분석→예측→결정→실행) 큰 그림이 먼저 필요하면 LLM 멀티에이전트 투자 시스템(MAS) 완전 가이드를 참고하세요.

출력이 흔들리는 진짜 원인: “좋은 프롬프트”가 아니라 “데이터 계약 부재”
현장에서 가장 많이 터지는 증상은 이렇습니다.
- 같은 입력인데 필드명이 바뀜(confidence → score → prob)
- 확률을 준다더니 문장으로만 말함
- “결정”이 주문까지 말해버림(분석/예측/결정 경계 붕괴)
- 로그를 남기려는데 출력 포맷이 매번 달라서 파싱 실패
이걸 프롬프트로만 잡으려 하면, 결국 “더 길고 더 빡센 프롬프트”로 가다가 유지보수가 망가집니다. 해결책은 간단합니다.
- 스키마를 먼저 정하고 → 출력은 스키마에 맞춰 강제 → 검증 실패 시 HOLD/재시도 → 로그에 남겨 리플레이
역할 경계부터 잡고 싶다면 멀티에이전트 투자 시스템 역할 분리 설계: 분석·예측·의사결정 에이전트를 나누는 기준를 참고하세요.
에이전트 JSON 스키마, 정확히 뭐냐: “구조화 출력”이 아니라 “계약(Contract)”이다
용어 정리
- Output Schema(출력 스키마): LLM이 내야 하는 JSON의 형식(필드/타입/enum/필수값)
- Data Contract(데이터 계약): 단계 간(분석→예측→결정) 연결을 보장하는 입출력 약속
- Validation(검증): (1) JSON 파싱 (2) 스키마 검증 (3) 도메인 규칙 검증(예: 확률 합=1)
스키마는 “예쁘게 만들기”가 목적이 아니라, 운영에서 실패를 안전하게 처리하기 위한 장치입니다.
분석→예측→결정 연결에 필요한 “최소 계약” 3개
이 글에서는 딱 3가지 계약만 잡아도 파이프라인이 안정화됩니다.
- AnalysisOutput: 멀티소스 신호를 구조화(근거 포함)
- PredictionOutput: T+1/T+5/T+20 Up/Down/Side 확률 분포
- DecisionOutput: 예측을 “주문”이 아니라 이산 포지션 조절 액션으로 번역
Analysis Contract (분석)
근거 기반 신호를 구조화한다(행동 금지)
필수 필드
signals[], evidence[], confidence(0~1)
검증 포인트
evidence 최소 1개 필수
참고: 분석 에이전트 4종: announcement / event / price momentum / market
Prediction Contract (예측)
T+1/T+5/T+20 Up·Down·Side 확률만 출력
필수 필드
horizons.T1/T5/T20, up/down/side
검증 포인트
(도메인) up+down+side=1
참고: Nv≈30, qL/qU=30%/70%, τhigh≈1.4, τlow≈0.7, sideways≈33%
Decision Contract (결정)
주문이 아니라 "이산 포지션 조절 액션"만 출력
필수 필드
action(enum), rationale[], constraints_applied[]
검증 포인트
action은 7개 enum만 허용
참고: close / -40 / -20 / hold / +20 / +40 / upper limit
경계(금지행동) · 계약(JSON) · 검증(Validation)
연구 참고: 중국 공모 REITs(저변동 시장) 대상 LLM 멀티에이전트 연구는 분석 에이전트 4종(announcement/event/price momentum/market) → 예측 에이전트가 다중 호라이즌 확률(T+1/T+5/T+20) → 의사결정은 이산 액션(close, ±20, ±40, upper limit) 구조로 “analysis–prediction–decision–execution” 폐루프를 구성합니다. 동적 임계값 θ 설정에서 Nv≈30일, qL/qU=30%/70%, τhigh≈1.4, τlow≈0.7, 약 33% 거래일이 sideways(횡보)로 분류된다고 서술합니다.
복붙용 템플릿 0: 모든 에이전트에 공통으로 넣을 “Envelope(봉투)”
스키마가 커질수록, 공통 필드는 일관되게 박아두는 게 유지보수에 유리합니다.
- schema_id / schema_version (버전 관리)
- run_id (리플레이/추적)
- as_of (시점)
- asset (종목/펀드)
- inputs_hash (입력 스냅샷 식별)
- output (실제 페이로드)
| 필드 | 타입 | 필수 | 운영 목적 | 예시 값 |
|---|---|---|---|---|
| schema_id | string | 필수 | 스키마 식별 | "analysis_output_v1" |
| schema_version | string | 필수 | 버전 관리 | "1.0.0" |
| run_id | string | 필수 | 실행 추적/리플레이 키 | "2024-10-01_180102.SZ_run_0001" |
| as_of | string(ISO-8601) | 필수 | 의사결정 기준 시점 | "2024-10-01T09:30:00+08:00" |
| asset.code | string | 필수 | 종목/펀드 식별 | "180102.SZ" |
| inputs_hash | string | 권장 | 입력 스냅샷 고정(리플레이) | "sha256:…" |
| upstream_refs | array[string] | 권장 | 상위 단계 출력 참조 | ["analysis_run_id:…"] |
| model_id | string | 권장 | 사용 모델 기록 | "DeepSeek-R1" / "Qwen3-8B-FT" |
| data_window | object | 권장 | 윈도우/기간 기록 | "Oct 2024–Oct 2025" |
| transaction_cost_rate | number | 권장 | 비용 가정 기록 | 0.0003 (0.03%) |
| notes | string | 선택 | 사람용 메모 | "validation_retry" |
템플릿 1: AnalysisOutput JSON 스키마 (분석 에이전트용)
1) JSON Schema(요약 버전)
아래는 “분석 에이전트 출력”에 필요한 최소 스키마 골격입니다. (필드는 확장 가능)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AnalysisOutput",
"type": "object",
"required": ["schema_id", "run_id", "as_of", "asset", "signals"],
"properties": {
"schema_id": { "type": "string", "const": "analysis_output_v1" },
"run_id": { "type": "string" },
"as_of": { "type": "string" },
"asset": {
"type": "object",
"required": ["code"],
"properties": { "code": { "type": "string" }, "market": { "type": "string" } }
},
"signals": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["topic", "claim", "confidence", "evidence"],
"properties": {
"topic": { "type": "string" },
"claim": { "type": "string", "enum": ["positive", "neutral", "negative"] },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
"evidence": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["source", "ref"],
"properties": {
"source": { "type": "string", "enum": ["disclosure", "news", "price", "macro"] },
"ref": { "type": "string" }
}
}
},
"risk_flags": { "type": "array", "items": { "type": "string" } }
}
}
}
}
}2) 실제 연구 설정을 반영한 입력/피처(참고)
저변동 REITs 시장 분석 에이전트(가격 모멘텀)에서 사용된 대표 피처는 다음처럼 윈도우가 명시되어야 재현됩니다.
- MA: 5/10/20/60
- RSI: 6/12/24
- MACD(DIF/DEA/Histogram)
- Bollinger Bands: (20, 2σ)
- Volume MA: 5/10/20
- 구조 레벨: 고저점 롤링 윈도우 5/10/20/60
근거 팁
evidence의 ref는 “문서ID/기사ID/데이터스냅샷키”처럼 재조회 가능한 형태로 강제하세요.
템플릿 2: PredictionOutput JSON 스키마 (예측 에이전트용)
예측은 문장으로 쓰지 말고 확률 분포로만 고정하는 게 핵심입니다.
1) JSON Schema(요약 버전)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "PredictionOutput",
"type": "object",
"required": ["schema_id", "run_id", "as_of", "asset", "horizons"],
"properties": {
"schema_id": { "type": "string", "const": "prediction_output_v1" },
"run_id": { "type": "string" },
"as_of": { "type": "string" },
"asset": { "type": "object", "required": ["code"], "properties": { "code": { "type": "string" } } },
"horizons": {
"type": "object",
"required": ["T1", "T5", "T20"],
"properties": {
"T1": { "$ref": "#/$defs/prob3" },
"T5": { "$ref": "#/$defs/prob3" },
"T20": { "$ref": "#/$defs/prob3" }
}
}
},
"$defs": {
"prob3": {
"type": "object",
"required": ["up", "down", "side"],
"properties": {
"up": { "type": "number", "minimum": 0, "maximum": 1 },
"down": { "type": "number", "minimum": 0, "maximum": 1 },
"side": { "type": "number", "minimum": 0, "maximum": 1 }
}
}
}
}중요: JSON Schema만으로 “up+down+side=1”을 완벽히 강제하기 어렵습니다. 그래서 도메인 검증(런타임 체크)를 반드시 추가하세요.
| 검증 항목 | 규칙(조건) | 실패 시 증상 | 조치(폴백) | 로그에 남길 필드 |
|---|---|---|---|---|
| 확률 범위 체크 | up/down/side는 0~1 범위 | 음수/1 초과 | 예측 재생성 또는 HOLD 폴백 | run_id, offending_field, raw_output |
| 확률합 체크 | up + down + side = 1 | 합이 1이 아님(누락/중복/파싱 오류) | 예측 재생성 또는 HOLD 폴백 | sum_value, horizons, raw_output |
| 호라이즌 누락 체크 | T1/T5/T20 모두 존재 | T5만 있고 T1/T20 없음 등 | 누락 호라이즌 재생성(또는 전체 재생성) | missing_horizons |
| side(횡보) 경고 체크 | side가 지속적으로 0 또는 1에 고정되는 패턴은 이상 신호 | 참고: sideways 약 33%가 정상 범주 | 경고 플래그만 세우고 진행(또는 인간 검토 큐) | side_series_stats, warning_flag |
| side 정의 참조 존재 여부 | side_definition(또는 참조키)에 Nv≈30, qL/qU=30%/70%, τhigh≈1.4, τlow≈0.7 추적 가능 | side 기준이 빠져 재현 불가 | 기준 키 누락 시 재생성 또는 run_config에서 주입 | side_definition_ref |
2) sideways(횡보) 파라미터를 스키마에 포함시켜야 하는 이유
왜 예측 결과가 달라 보일까?
“횡보”란 가격이 크게 오르지도 내리지도 않고 옆으로만 움직이는 구간을 말합니다. 문제는 어디까지를 횡보로 볼지 사람마다·시스템마다 기준이 다르다는 점입니다. 그 기준이 머릿속에만 있으면, 같은 데이터를 넣어도 “예측이 왜 저번이랑 달라?” 하는 혼란이 생깁니다.
연구에서는 어떻게 하나?
실제 연구(예: 중국 공모 REITs 멀티에이전트)에서는 “횡보 기준”을 숫자로 고정해 둡니다. 예를 들면 “최근 30일 변동성”, “30%·70% 구간 경계”, “상승/하락 구간을 나누는 비율(τhigh≈1.4, τlow≈0.7)” 같은 값들이요. 이렇게 정해 두면, 그 설정에 따라 거래일의 약 33%가 횡보로 분류된다고 보고합니다.
그래서 출력에는 뭘 남기면 되나?
prediction_output에는 “횡보를 이렇게 정했다”는 요약(side_definition) 또는 그걸 가리키는 참조키를 넣는 것이 좋습니다. 그러면 나중에 같은 데이터로 다시 돌려도 “횡보 기준이 달라져서 결과가 바뀐 것처럼 보이는” 일을 막을 수 있습니다. 즉, “기준이 뭐였는지”가 출력에 남아 있어야 재현과 비교가 가능해집니다.
템플릿 3: DecisionOutput JSON 스키마 (의사결정 에이전트용)
의사결정은 “주문”이 아니라 포지션 조절 액션만 내야 안정적입니다.
1) JSON Schema(요약 버전)
아래 enum은 연구에서 제시된 이산 액션(예: close, reduce 40%, …, upper limit)을 그대로 시스템용 키로 옮긴 것입니다.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "DecisionOutput",
"type": "object",
"required": ["schema_id", "run_id", "as_of", "asset", "action", "rationale"],
"properties": {
"schema_id": { "type": "string", "const": "decision_output_v1" },
"run_id": { "type": "string" },
"as_of": { "type": "string" },
"asset": { "type": "object", "required": ["code"], "properties": { "code": { "type": "string" } } },
"action": {
"type": "string",
"enum": ["close", "reduce_40", "reduce_20", "hold", "increase_20", "increase_40", "increase_upper_limit"]
},
"rationale": {
"type": "array",
"minItems": 1,
"items": { "type": "string" }
},
"constraints_applied": { "type": "array", "items": { "type": "string" } }
}
}2) 결정 스키마에 “리스크 제약 상태”를 어떻게 반영할까
결정은 예측만 보고 내리면 안 됩니다. 최소한 constraints_applied에 아래 같은 제약 발동 여부를 남기세요: position cap / step size / pace restriction / stop rule. 이건 단순 로깅이 아니라, 나중에 왜 hold가 나왔는지를 재현하는 핵심 힌트가 됩니다.
검증(Validation) 파이프라인: “실패해도 안전하게”가 스키마의 목적이다
스키마 기반 운영의 정석은 이 4단계입니다.
- Parse: JSON 파싱 실패 → 즉시 재시도(최대 N회)
- Schema Validate: 필수 필드/타입/enum 검증 실패 → 재시도
- Domain Validate: 확률 합, 호라이즌 누락, 액션-제약 충돌 → HOLD 폴백
- Log: 어떤 단계에서 왜 실패했는지 저장(리플레이 가능)
| 실패 유형 | 대표 원인 | 탐지 방법 | 조치(재시도/폴백) | 로그 필드 |
|---|---|---|---|---|
| 파싱 실패 | JSON 깨짐/불필요 텍스트 혼입 | parser error | “JSON만 출력” 프롬프트로 재시도 → 실패 지속 시 HOLD | raw_text, parser_error |
| 필드 누락 | horizons 누락, evidence 누락 등 | schema validate 실패 | 누락 필드만 재생성 또는 전체 재시도 → 실패 시 HOLD | missing_fields |
| 확률합 불일치 | 계산 실수/필드 중복/누락 | 도메인 검증 실패 | 예측 재생성 → 실패 시 HOLD | sum_value, horizons |
| enum 위반 | 허용되지 않은 액션(예: “increase_30”) 출력 | schema validate 실패(enum mismatch) | “허용 enum 목록”을 시스템 메시지로 주입 후 재시도 → 실패 시 HOLD | invalid_enum, allowed_enum |
| evidence 누락 | 분석이 결론만 출력 | evidence minItems 위반 | 분석 재생성(근거 강제) → 실패 시 “needs_human_review” 플래그 + HOLD | evidence_missing, sources_expected |
폴백 기본값을 HOLD로 두고, 실패 사유를 로그에 남겨 리플레이 가능하게 만드는 것이 핵심.
실전 팁
“재시도”는 무조건 늘리면 비용만 올라갑니다. 보통 2회 재시도 + HOLD 폴백이 운영 안정성과 비용의 균형이 좋습니다. (재시도 사유는 반드시 로그에 남기기)
로그/리플레이를 위한 LogEvent 스키마(재현·추적의 핵심)
스키마를 잡았는데도 성과가 안 오르면, 원인은 대부분 “어디서 새는지”를 못 보는 겁니다. 그래서 로그도 스키마가 필요합니다.
- 입력 스냅샷 키(inputs_hash)
- 각 에이전트 출력 원문(JSON)
- 검증 결과(성공/실패, 실패 사유)
- 최종 액션과 실행 여부
- 성과 지표(옵션): CR/Sharpe/MDD 등

전략 운영에서 로그/리플레이(리뷰) 구조 만들기를 참고하세요.
“이 구조가 실제로 의미 있나?”를 보여주는 공개 성과 수치
중국 공모 REITs 28개 펀드(각 계정 초기자본 RMB 1 million, 거래비용 0.03%(0.0003))를 대상으로 한 2024년 10월~2025년 10월 백테스트에서, 멀티에이전트 기반 전략이 Buy&Hold 대비 평균 성과 개선을 보고합니다.
- 평균 CR(%): 15.50 / 13.75 / 10.69
- 평균 Sharpe: 1.71 / 1.77 / 0.75
- 평균 MDD(%): -4.09 / -3.46 / -11.12
CR (%)
Sharpe
MDD (%)
한계·주의
이 수치는 “수익 보장”이 아니라 특정 기간/시장/가정(거래비용 포함) 하에서의 결과입니다. 레짐 변화·체결·데이터 누락에 따라 실거래는 달라질 수 있습니다.
FAQ
자주 묻는 질문
- JSON 스키마만 있으면 출력이 완벽히 고정되나요?
- 아니요. 스키마는 "형식"을 고정합니다. 확률 합=1 같은 규칙은 추가로 도메인 검증이 필요합니다.
- function calling을 쓰면 스키마 검증이 필요 없나요?
- function calling은 형식을 강제하는 데 매우 유리하지만, 여전히 도메인 규칙(합=1, 제약 충돌 등)은 검증해야 합니다.
- 스키마가 너무 빡빡하면 모델 성능이 떨어지지 않나요?
- 보통 반대입니다. 운영에서는 "성능"보다 일관성·검증 가능성이 더 큰 이득을 줍니다. 애매하면 필드에 notes(텍스트)를 따로 두고 핵심은 구조화하세요.
- 분석 에이전트마다 스키마를 다르게 가져가도 되나요?
- 가능하지만, 최소한 공통 Envelope(run_id/as_of/asset/evidence)를 공유해야 나중에 합치기 쉽습니다.
- 가장 작은 시작(최소 템플릿)은?
- AnalysisOutput(근거 포함) + PredictionOutput(T5만) + DecisionOutput(hold/±20만) + 검증/로그부터 시작하세요.
결론: “스키마가 곧 시스템”이다
에이전트 JSON 스키마는 단순한 포맷이 아니라, 재현 가능한 폐루프를 만드는 데이터 계약입니다. 오늘 할 일은 하나입니다. 분석→예측→결정 3개 스키마를 고정하고, 검증 실패 시 안전하게 HOLD로 떨어지도록 만드세요.