Field Log · Entry

Production RAG Agent Harness: Trajectory 평가와 Release Gate (10/10)

RAG Agent 실행 모듈을 typed state·policy로 감싸고 durable runtime·trace·trajectory evaluation·release gate로 검증하는 production harness 구조

오늘의 결론

  • Model이 두뇌라면 harness는 state·tool·policy·runtime·trace·evaluation으로 행동 범위를 만드는 실행 환경입니다.
  • 최종 답 하나만 채점하지 않습니다. Final state, forbidden effect, route, evidence, tool argument, retry, approval을 함께 봅니다.
  • Agent의 hidden chain-of-thought를 저장할 필요는 없습니다. 구조화된 action·observation·state transition이 평가 가능한 trajectory입니다.
  • pass@k는 여러 후보 중 하나의 성공, pass^k는 반복 실행 모두의 성공을 보므로 목적이 다릅니다.
  • Release는 품질 평균 하나가 아니라 security invariant, task success, p95 latency, cost, reliability의 다중 gate를 통과해야 합니다.

앞 글까지 우리는 Agent의 한 부분씩 설계했습니다.

state machine · tool contract · adaptive router
planning · evidence sufficiency · memory lifecycle
durable execution · observability · security boundary

이제 각 부품을 한 runtime에 넣고, 변경할 때 더 좋아졌는지 검증해야 합니다. Prompt 하나와 tool 몇 개를 연결한 demo에서 production system으로 넘어가는 경계가 바로 Agent harness입니다.

RAG Agent의 실행 모듈을 typed state와 policy로 감싸고 durable runtime, trace, trajectory evaluation, release gate가 순환하는 production harness

그림 1. Harness는 model을 중심으로 한 실행 부품과 바깥의 안전장치를 함께 묶는다. 모든 run은 trace와 manifest가 되고, evaluation 결과가 release gate와 다음 개선으로 돌아온다.


Harness, Framework, Runtime, Model을 구분하기

Model

주어진 context에서 다음 token, structured output, tool proposal을 생성합니다. 판단 능력을 제공하지만 durable state, 권한, timeout, audit를 자동으로 보장하지 않습니다.

Agent Framework

Graph, node, tool binding, prompt template, model adapter 같은 개발 abstraction을 제공합니다. 빠르게 조립하도록 돕습니다.

Runtime

Queue, worker, checkpoint, retry, scheduler, interrupt처럼 실행을 지속하고 복구합니다.

Harness

특정 model·framework 바깥에서 Agent의 행동을 제한·관측·평가하는 시스템 경계입니다.

typed state and transition
tool registry and schema
policy and authorization
retrieval and evidence ledger
memory write/read gate
durable execution
trace and run manifest
evaluation and release gate

Framework를 바꿔도 이 contract와 evaluation을 유지할 수 있어야 합니다. 반대로 framework 기능을 전부 다시 만들 필요는 없습니다. Harness는 제품의 invariant를 소유하고 framework/runtime는 구현 수단으로 사용합니다.

Production Harness의 11개 Module

1. Ingress와 Goal Normalizer

User input, principal, tenant, locale, deadline을 검증하고 수행 가능한 goal로 정규화합니다.

{
  "goal_id": "goal_77",
  "principal": "user:user_104",
  "intent": "compare_refund_policies",
  "constraints": {"language": "ko-KR", "deadline_ms": 15000},
  "risk_tier": "R1"
}

2. Typed State Store

현재 goal, step, evidence, receipts, budget, approval, failure를 versioned state로 관리합니다. State reducer만 transition을 적용합니다.

3. Router

No-retrieval, single retrieval, iterative retrieval, tool workflow, human escalation 가운데 비용에 맞는 경로를 선택합니다.

4. Planner

복합 task를 dependency가 있는 step으로 나눕니다. Plan은 자유 텍스트가 아니라 검증 가능한 graph 또는 list입니다.

5. Model Adapter

Provider별 request를 공통 contract로 바꾸고 model ID, decoding, token usage, response hash를 기록합니다.

6. Retriever와 Evidence Manager

Query transform, sparse/dense search, fusion, rerank, context selection, evidence sufficiency를 수행하고 claim-source ledger를 만듭니다.

7. Tool Registry와 Effect Executor

JSON Schema, effect class, timeout, idempotency, input/output validator, capability requirement를 trusted registry에 둡니다.

8. Memory Manager

Working, episodic, semantic, procedural memory를 분리하고 provenance·consent·expiry가 있는 write/read gate를 적용합니다.

9. Policy와 Security Engine

Taint flow, capability, approval, egress, commit-time authorization을 model 바깥에서 결정합니다.

10. Durable Runtime와 Observability

Checkpoint·replay·retry·cancel을 제공하고 trace·span·event·artifact·manifest를 연결합니다.

11. Evaluator와 Release Controller

Final state와 trajectory를 평가하고 regression, canary, rollback을 결정합니다.

공통 Language: State, Action, Observation

서로 다른 module이 자유로운 dictionary를 주고받으면 evaluation과 migration이 깨집니다.

from dataclasses import dataclass
from typing import Literal

@dataclass(frozen=True)
class Action:
    action_id: str
    kind: Literal["RETRIEVE", "MODEL", "TOOL", "ASK", "FINISH"]
    operation: str
    input_ref: str
    input_hash: str
    effect_class: str
    policy_version: str

@dataclass(frozen=True)
class Observation:
    observation_id: str
    action_id: str
    status: Literal["OK", "ERROR", "UNKNOWN", "DENIED"]
    output_ref: str | None
    output_hash: str | None
    provenance: tuple[str, ...]
    receipt_id: str | None

@dataclass(frozen=True)
class AgentState:
    run_id: str
    version: int
    status: str
    goal_ref: str
    plan_ref: str | None
    evidence_refs: tuple[str, ...]
    completed_actions: tuple[str, ...]
    pending_action: str | None
    remaining_steps: int
    remaining_cost_usd: float
    deadline_at: str

큰 input/output은 reference로 분리하고 record에는 hash와 provenance를 둡니다. Schema에는 version을 붙이고 migration과 replay compatibility를 테스트합니다.

한 Run의 End-to-End Sequence

1. ingress validates principal, goal, risk, budget
2. state v1 is checkpointed
3. router selects workflow
4. planner emits typed steps and dependencies
5. retriever builds evidence ledger
6. sufficiency gate accepts, retries, or escalates
7. model proposes structured action
8. tool schema and policy validate proposal
9. capability and action-bound approval are checked
10. commit-time authorization validates fresh witness
11. durable executor runs with idempotency key
12. observation and receipt reduce state
13. verifier checks answer and final state
14. memory proposals pass write policy
15. trace, manifest, artifacts, evaluation are finalized

각 번호는 span 또는 state event와 연결됩니다. 실패하면 마지막 exception만 남기는 대신 어느 invariant가 처음 깨졌는지 기록합니다.

Trajectory란 무엇인가?

Trajectory는 run 동안 관찰 가능한 decision과 환경 변화의 순서입니다.

[
  {"seq": 1, "state": 1, "type": "ROUTE", "value": "ITERATIVE_RAG"},
  {"seq": 2, "state": 2, "type": "ACTION", "operation": "search.policy"},
  {"seq": 3, "state": 3, "type": "OBSERVATION", "evidence": ["chunk_7"]},
  {"seq": 4, "state": 4, "type": "EVIDENCE_GATE", "sufficient": false},
  {"seq": 5, "state": 5, "type": "ACTION", "operation": "search.policy"},
  {"seq": 6, "state": 6, "type": "OBSERVATION", "evidence": ["chunk_9"]},
  {"seq": 7, "state": 7, "type": "FINISH", "outcome": "SUCCEEDED"}
]

Hidden chain-of-thought를 수집하거나 평가 대상으로 만들 필요는 없습니다. Production trajectory에는 다음만 있어도 충분합니다.

  • normalized goal
  • route와 plan 구조
  • structured action
  • tool input hash와 safe projection
  • observation·receipt·evidence reference
  • state transition과 reason code
  • policy decision과 approval reference
  • resource usage와 terminal outcome

이는 privacy와 model 내부 reasoning 비공개 원칙을 지키면서도 행동을 진단할 수 있게 합니다.

평가의 여섯 Layer

Layer 1. Final State

업무가 실제로 원하는 상태가 되었는지 봅니다.

답변 문자열이 그럴듯한가?          ← 약한 검사
주문 DB가 목표 상태와 같은가?       ← 강한 검사
금지된 변경이 전혀 없는가?          ← 필수 검사

τ-bench는 대화 종료 뒤 database state를 annotated goal state와 비교합니다. Tool-using Agent에서는 마지막 자연어보다 환경의 canonical state가 더 믿을 만한 경우가 많습니다.

Layer 2. Policy와 Security

  • unauthorized effect가 없었는가?
  • capability와 approval 범위 안이었는가?
  • sensitive data가 forbidden sink로 나가지 않았는가?
  • commit witness가 유효했는가?
  • tenant boundary를 지켰는가?

Security invariant 하나라도 깨지면 task outcome이 맞아도 실패입니다.

Layer 3. Trajectory

  • 올바른 route와 tool을 골랐는가?
  • dependency 전에 step을 실행하지 않았는가?
  • observation을 다음 decision에 반영했는가?
  • 같은 실패를 의미 없이 반복하지 않았는가?
  • 충분한 evidence 뒤 멈췄는가?
  • final answer 전에 verification을 수행했는가?

AgentDiagnose는 trajectory에서 backtracking/exploration, task decomposition, observation reading, self-verification, objective quality 같은 역량을 진단하는 관점을 제시합니다. 특정 자동 score를 절대적인 정답으로 쓰기보다 failure taxonomy를 설계하는 참고로 활용합니다.

Layer 4. Component

Component대표 지표
Routerroute accuracy, avoidable retrieval
Plannervalid DAG, dependency violation
RetrieverRecall@k, nDCG, evidence coverage
Rerankeruseful evidence promotion
Generatorclaim correctness, faithfulness
Tool callerschema validity, correct operation/target
Memoryuseful recall, stale/poisoned injection
Runtimeresume success, duplicate effect prevention

RAGChecker처럼 retrieval과 generation을 세분화하면 “답이 틀렸다”를 retrieval miss와 generation hallucination으로 분해할 수 있습니다.

Layer 5. Reliability

같은 task를 여러 번 실행했을 때 일관되게 성공하는지 봅니다.

Layer 6. Efficiency와 Operations

  • end-to-end p50/p95/p99 latency
  • model/tool/retrieval latency breakdown
  • tokens와 cost per successful task
  • step·retry·approval count
  • timeout·cancel·compensation rate
  • checkpoint conflict와 queue wait

pass@k와 pass^k를 혼동하지 않기

pass@k

서로 다른 후보 k개 중 하나 이상 성공할 비율입니다. Code generation이나 search에서 여러 후보를 낼 수 있을 때 exploration 능력을 봅니다.

후보: 실패, 실패, 성공, 실패
pass@4: 성공

pass^k

같은 task를 k번 독립적으로 실행해 k번 모두 성공하는 task 비율입니다. τ-bench가 반복 실행 reliability를 보기 위해 제안했습니다.

trial: 성공, 성공, 실패, 성공
pass^4: 실패

Task t의 각 trial 성공을 s(t, i) ∈ {0,1}라 하면 empirical metric은 다음처럼 생각할 수 있습니다.

pass^k = mean_t [ s(t,1) × s(t,2) × ... × s(t,k) ]

Single-run success가 90%라도 독립 가정 아래 0.9^8 ≈ 43%입니다. Production automation은 “가끔 성공”보다 반복 신뢰도가 중요하므로 pass@1과 pass^k를 함께 봅니다. 실제 trial은 완전히 독립이지 않을 수 있으므로 seed·time·dependency snapshot을 기록하고 confidence interval도 보고합니다.

Evaluation Task의 Schema

좋은 test case는 prompt와 expected answer만 갖지 않습니다.

task_id: refund-policy-014
version: 3
initial_state_fixture: fixtures/order_014.json
principal:
  id: user_104
  roles: [customer]
user_goal: "주문 42의 환불 가능 여부를 확인하고 가능하면 신청해 줘"
policies:
  - policy/refund@12
available_tools:
  - order.read@2
  - refund.create@3
retrieval_snapshot: policy-ko@20260716
expected:
  final_state:
    order_42.refund_status: requested
  answer_claims:
    - claim: "환불 신청이 접수되었습니다"
      evidence: [receipt.refund_id]
  required_events:
    - evidence.sufficient
    - approval.granted
    - tool.receipt_recorded
  forbidden_effects:
    - payment.capture
    - order.cancel
  max_budget:
    steps: 8
    usd: 0.20
    wall_ms: 15000

Task data에도 provenance와 review owner를 둡니다. Production incident, user complaint, attack, newly supported workflow에서 case를 추가합니다.

Deterministic Environment를 먼저 만들기

Live API로만 평가하면 외부 상태가 바뀌어 regression인지 noise인지 구분하기 어렵습니다.

Fake Model

특정 request hash에 고정 response를 반환해 reducer, retry, schema handling을 테스트합니다.

Tool Simulator

In-memory 또는 ephemeral DB에서 실제 business rule을 구현합니다. Final state와 receipts를 검사할 수 있어야 합니다.

Retrieval Snapshot

고정 corpus·index·embedding·reranker version을 사용합니다. Query별 canned result만 쓰면 retrieval algorithm regression을 놓치므로 작은 실제 index fixture도 둡니다.

Virtual Clock

Timeout, expiry, delayed event, bitemporal memory를 빠르고 결정적으로 테스트합니다.

Fault Injector

429 with Retry-After
503 then success
response lost after commit
worker crash after receipt
approval expires before commit
resource version changes
malicious retrieved chunk

동일 seed와 snapshot에서 재현 가능해야 합니다.

Golden Trajectory를 정답 하나로 만들지 않기

정상적인 경로가 여러 개일 수 있습니다.

경로 A: hybrid search → rerank → answer
경로 B: metadata filter → dense search → answer

Golden exact sequence와 다르다고 B를 실패로 만들면 Agent의 유효한 adaptation을 벌합니다. 대신 invariant와 partial order를 평가합니다.

must_happen_before:
  - [approval.granted, refund.create]
  - [evidence.sufficient, answer.final]
at_most:
  search.policy: 3
allowed_tools: [order.read, search.policy, refund.create]
forbidden_tools: [payment.capture]

정확한 trajectory fixture는 deterministic unit test에, semantic invariant는 stochastic end-to-end test에 사용합니다.

자동 Evaluator의 우선순위

1. Deterministic Checker

가능하면 먼저 사용합니다.

DB state equality
JSON Schema validity
receipt existence
policy event sequence
forbidden effect absence
latency·cost budget
source ID membership

2. Reference-based Metric

Claim set, evidence set, answer slot처럼 비교 가능한 구조를 사용합니다.

3. Model-based Judge

Long-form relevance나 explanation quality처럼 규칙화하기 어려운 항목에 제한적으로 사용합니다.

Judge에는 다음이 필요합니다.

  • rubric과 scale anchor
  • anonymized candidate order
  • judge model·prompt version
  • calibration set과 human agreement
  • abstain/uncertain option
  • pairwise evaluation when appropriate
  • judge drift monitoring

Model judge가 security invariant나 money amount equality를 대신하면 안 됩니다.

First-Failure Taxonomy

Final failure만 세면 개선 지점이 보이지 않습니다.

INPUT_INVALID
ROUTE_INCORRECT
PLAN_INVALID
RETRIEVAL_MISS
EVIDENCE_INSUFFICIENT
TOOL_SELECTION_WRONG
TOOL_ARGUMENT_INVALID
POLICY_DENIED_CORRECTLY
POLICY_BYPASS
OBSERVATION_IGNORED
NO_PROGRESS
RUNTIME_EXHAUSTED
GENERATION_UNSUPPORTED
VERIFICATION_MISSED

각 run에는 가장 이른 violated invariant, downstream symptoms, affected versions를 기록합니다.

예:

first failure: RETRIEVAL_MISS
symptoms: evidence insufficient → extra retries → budget exhausted
not root cause: final answer absent

Counterfactual Replay로 변경점을 격리하기

같은 recorded trajectory에서 module 하나만 바꿉니다.

recorded observations + new reducer
same queries + new retriever snapshot
same evidence + new answer prompt
same proposals + new security policy
same tool fixtures + new retry policy

Model과 environment가 모두 바뀐 A/B 결과는 원인 해석이 어렵습니다. Counterfactual replay는 “어느 layer가 개선을 만들었는가?”를 좁힙니다.

주의:

  • 새 policy가 과거에는 보지 못한 정보에 의존하면 replay가 불가능할 수 있다.
  • recorded observation은 새 action의 결과를 알려 주지 않는다.
  • off-policy trajectory에는 coverage 한계가 있다.
  • live write effect는 재실행하지 않는다.

Mutation Test로 Evaluator를 검증하기

Evaluator가 모든 build를 통과시키지 않는지 일부러 결함을 넣습니다.

evidence source 하나 제거
tool target ID 바꾸기
approval 뒤 amount 변경
같은 action 두 번 실행
retry limit 제거
tenant filter 삭제
final claim 하나 hallucinate
memory provenance 끊기

각 mutation을 해당 checker가 잡아야 합니다. 잡지 못하면 product code보다 evaluation coverage부터 보강합니다.

CI Evaluation Pyramid

Pull Request: 빠른 결정적 Test

schema · reducer · policy · tool contract
fixed retrieval snapshot · fake model
security mutation · replay compatibility

수분 안에 끝나야 합니다.

Nightly: Stochastic Regression

여러 model seed·provider
multi-turn simulator
pass^k reliability
fault injection
cost·latency distribution

Pre-release: Full Scenario Matrix

tenant × locale × risk tier × route
model × prompt × tool schema × index
benign × adversarial × failure injection

Production: Shadow와 Canary

  • Shadow는 production input의 redacted copy를 새 version에 흘리되 write effect를 막습니다.
  • Canary는 작은 traffic과 제한된 capability로 실제 결과를 봅니다.
  • Security error와 unauthorized effect는 즉시 중단합니다.
  • 품질·latency·cost regression은 정한 window와 confidence로 판단합니다.

Release Gate 예시

아래 숫자는 설명을 위한 예시이며 제품 위험도와 baseline으로 정해야 합니다.

release_gate:
  hard_fail:
    unauthorized_effects: 0
    cross_tenant_leaks: 0
    duplicate_irreversible_effects: 0
    replay_incompatibilities: 0

  quality:
    task_success_min: 0.86
    grounded_answer_min: 0.95
    route_accuracy_min: 0.92
    regression_vs_baseline_max: -0.01

  reliability:
    pass_pow_4_min: 0.75
    resume_after_crash_min: 0.99

  efficiency:
    p95_latency_ms_max: 8000
    cost_per_success_usd_max: 0.12
    p95_steps_max: 10

Quality가 오르고 cost가 약간 증가하는 trade-off는 product owner가 판단할 수 있지만, security hard fail은 평균 점수로 상쇄하지 않습니다.

Gate result도 artifact로 남깁니다.

{
  "candidate": "[email protected]",
  "baseline": "[email protected]",
  "dataset": "production-regression@28",
  "environment": "snapshot@20260716",
  "decision": "BLOCKED",
  "failed_gates": ["pass_pow_4", "p95_latency"],
  "report_hash": "sha256:..."
}

Version Matrix와 Run Manifest

“Prompt만 바꿨다”는 말을 증명하려면 모든 dependency를 기록합니다.

agent code · workflow graph · state schema
model request ID · resolved model ID · decoding
system prompt · task prompt · few-shot set
tool names · JSON Schemas · server versions
corpus · parser · chunker · embedding · index snapshot
router · reranker · policy · memory snapshot
evaluator · judge model · dataset

각 version은 human label뿐 아니라 content hash를 가집니다. Run manifest와 evaluation report가 같은 version graph를 참조해야 합니다.

Production Loop Skeleton

def run_agent(request, deps):
    goal = deps.ingress.normalize(request)
    state = deps.state_store.create(goal, deps.budget.for_goal(goal))

    with deps.tracer.start_run(state) as trace:
        while not state.is_terminal:
            deps.runtime.check_deadline_and_lease(state)
            deps.policy.check_state_invariants(state)

            route = deps.router.choose(state)
            context = deps.context_builder.build(
                state=state,
                memories=deps.memory.retrieve_scoped(state),
                evidence=deps.evidence.current(state),
            )
            proposal = deps.model.propose(route, context)
            action = deps.contracts.validate_and_type(proposal)

            decision = deps.policy.precheck(state, action)
            if decision.requires_approval:
                return deps.runtime.interrupt_with_preview(state, action)
            if decision.denied:
                state = deps.reducer.apply(state, decision.observation)
                continue

            deps.budget.reserve(state, action)
            witness = deps.policy.authorize_at_commit(state, action)
            observation = deps.runtime.execute_durably(
                action,
                witness=witness,
                idempotency_key=state.key_for(action.action_id),
            )
            state = deps.reducer.apply(state, observation)
            deps.state_store.checkpoint(state)

        verification = deps.verifier.check(state)
        deps.memory.propose_writes(state, verification)
        manifest = deps.observability.finalize(state, trace)
        deps.online_evaluator.enqueue(manifest)
        return state.public_result()

실제 system은 더 복잡하지만 ownership은 분명해야 합니다.

model proposes
contract types
policy authorizes
runtime executes
reducer changes state
verifier judges outcome
observability records
evaluator gates release

운영 SLO와 Error Budget

모델 품질만 SLO로 두지 않습니다.

99.0% run reaches a valid terminal state within deadline
99.9% committed write has a durable receipt
100% high-risk write has valid authorization witness
< 1% no-progress termination on supported tasks
< 8s p95 for read-only policy questions

SLO 위반이 error budget을 소진하면 새 feature rollout을 늦추고 reliability 개선에 투자합니다. Security invariant는 error budget을 허용할 수 없는 hard boundary로 분리합니다.

Rollout과 Rollback

Shadow

실제 input distribution을 보되 외부 write를 simulator로 바꿉니다. Privacy와 data retention policy는 production과 동일하게 적용합니다.

Canary

1% traffic처럼 작게 시작하고 low-risk route부터 엽니다. Candidate version, capability scope, kill switch를 명확히 둡니다.

Progressive Expansion

read-only → reversible write → external communication → high-risk write

각 단계에서 task success, pass^k, policy denial, cost, p95를 다시 확인합니다.

Rollback

Code만 되돌려도 이미 새 schema로 저장한 state와 memory가 남을 수 있습니다.

  • state schema backward compatibility
  • workflow replay version
  • prompt·tool registry pinning
  • index alias rollback
  • memory write quarantine
  • in-flight run routing

Rollback rehearsal을 release 전에 수행합니다.

최신 연구를 읽는 다음 방향

Harness가 안정되면 model과 retrieval policy를 더 agentic하게 만들 수 있습니다. 2026년 연구 흐름에서 살펴볼 만한 두 방향은 다음입니다.

Query-aware Diversity

DF-RAG는 reasoning-intensive QA에서 유사도만 높여 중복 chunk가 늘어나는 문제를 다루고, query마다 필요한 diversity를 test time에 조절하는 방향을 제안합니다. 19편의 MMR를 adaptive policy로 확장해 볼 수 있습니다.

Learned Graph-Text Routing

RouteRAG는 text와 graph retrieval 사이에서 언제 무엇을 검색하고 언제 답할지 reinforcement learning으로 학습하는 adaptive hybrid retrieval을 제안합니다. 23편의 router를 고정 rule에서 learned policy로 발전시키는 흐름입니다.

새 논문을 production에 넣을 때는 benchmark 수치만 복사하지 않습니다. 현재 harness의 task set에서 baseline, ablation, cost, security, pass^k를 다시 측정합니다.

10편을 하나의 Build Order로 정리하기

순서설계 질문
1Agent와 workflow의 경계는?State Loop
2Tool 입출력을 어떻게 계약할까?Tool Calling Contracts
3언제 어떤 retrieval을 쓸까?Adaptive Router
4복합 task를 어떻게 계획할까?Planning Patterns
5근거가 충분한지 어떻게 알까?Evidence Sufficiency
6무엇을 기억하고 잊을까?Agent Memory
7장애 뒤 어떻게 안전하게 재개할까?Durable Execution
8실패를 어떻게 재현할까?Observability
9부작용과 유출을 어떻게 막을까?Security
10전체를 어떻게 검증·릴리스할까?이 글

처음부터 모든 module을 구현할 필요는 없습니다. 위험에 따라 단계적으로 성숙시킵니다.

Level 0  prompt + model
Level 1  typed workflow + tool schema
Level 2  retrieval evidence + component evaluation
Level 3  bounded agent + budget + approval
Level 4  durable runtime + tracing + replay
Level 5  capability + commit authorization + trajectory release gate

흔한 실패 패턴

1. Framework를 Harness라고 부르기

Graph가 있다고 policy·evaluation·durability가 생기지 않습니다.

처방: 제품 invariant의 owner와 framework 기능을 분리합니다.

2. Final Answer만 채점

우연히 맞았거나 금지된 tool을 사용한 run이 성공으로 보입니다.

처방: final state, forbidden effect, trajectory를 함께 검사합니다.

3. Golden Trace와 한 줄이라도 다르면 실패

유효한 대체 경로를 막습니다.

처방: partial order와 invariant 중심으로 평가합니다.

4. pass@1만 보고 Production 투입

반복 실행의 불안정성을 놓칩니다.

처방: 여러 trial의 pass^k와 failure distribution을 봅니다.

5. Live Dependency로만 Regression Test

외부 drift와 코드 regression을 구분하지 못합니다.

처방: snapshot, simulator, virtual clock, fault injector를 둡니다.

6. LLM Judge가 모든 것을 채점

정확한 DB state와 security violation까지 확률적 판단에 맡깁니다.

처방: deterministic checker를 우선하고 judge 사용 범위를 제한합니다.

7. Quality 평균으로 Security 실패 상쇄

Task success가 높아도 한 번의 unauthorized write는 별도 사고입니다.

처방: hard fail과 trade-off metric을 분리합니다.

8. Rollback을 Code Revert로 끝내기

In-flight state, index, memory, schema가 새 version에 남습니다.

처방: stateful dependency까지 포함한 rollback rehearsal을 합니다.

Production 체크리스트

  • model, framework, runtime, harness의 책임을 구분했다.
  • state·action·observation에 versioned typed contract가 있다.
  • 모든 module이 같은 run ID, state version, manifest를 공유한다.
  • final answer보다 canonical final state를 우선 평가한다.
  • forbidden effect와 security invariant는 hard fail이다.
  • route·plan·evidence·tool·memory·runtime을 component별 평가한다.
  • hidden reasoning 대신 structured action·observation trajectory를 기록한다.
  • pass@1과 반복 실행 pass^k를 함께 보고한다.
  • fixed snapshot, simulator, virtual clock, fault injection이 있다.
  • golden exact sequence보다 invariant와 partial order를 사용한다.
  • deterministic checker를 model judge보다 우선한다.
  • evaluator를 mutation test로 검증한다.
  • PR·nightly·pre-release·production evaluation pyramid가 있다.
  • quality·reliability·cost·latency와 security hard gate가 있다.
  • shadow·canary·kill switch·stateful rollback을 rehearsal했다.

스스로 확인하기

  1. Framework와 harness의 책임 차이를 한 문장으로 설명할 수 있는가?
  2. 여러분의 task에서 자연어 답보다 더 강한 final state checker는 무엇인가?
  3. pass@k와 pass^k가 각각 어떤 제품 질문에 답하는가?
  4. Exact golden trajectory 대신 invariant로 검사해야 할 경로는 무엇인가?
  5. Release를 즉시 막아야 하는 hard fail 세 가지는 무엇인가?

이 글로 RAG Agent · Harness 제대로 만들기 10편을 마칩니다. 다음 학습 단계에서는 이 harness를 기준선으로 삼아 graph RAG, multimodal RAG, learned retrieval policy, agent fine-tuning, 최신 논문의 재현과 ablation을 다룹니다.

다음 글에서는 문서를 entity·relation·claim으로 바꾸는 Knowledge Graph의 기본 모델과 vector RAG에 graph가 필요한 조건부터 시작합니다.

참고자료