AI 에이전트 의사결정 로그: 사고의 흐름(Chain of Thought)을 저장하지 않고 증거 기록하기
요약
AI 에이전트의 의사결정 로그가 중요하며, 단순한 트레이스나 애플리케이션 로그로는 부족합니다. 이 로그는 태스크, 증거, 적용 정책 등 구조화된 형태로 의미 있는 모든 선택을 기록하여 디버깅과 감사에 활용할 수 있습니다. 로그를 작성할 때는 모델의 모든 턴(turn)이 아닌, '의사결정 경계'에서만 기록하는 것이 효율적입니다.
핵심 포인트
- AI 에이전트 의사결정 로그는 구조화된 선택 기록이어야 합니다.
- 단순 트레이스나 앱 로그로는 비즈니스 의도와 정책 판정을 알 수 없습니다.
- 로그는 모델의 모든 토큰 대신, '의사결정 경계'에서만 작성해야 합니다.
- 로그를 통해 행동의 이유, 권한 및 결과를 재구성할 수 있어야 합니다.
에이전트는 고객 레코드를 업데이트하거나, 환불을 처리하거나, 지원 케이스를 라우팅할 수 있으며, 이 모든 과정에서 대시보드는 녹색으로 유지됩니다. 그러다 누군가 가장 중요한 질문을 던집니다: 왜 이 행동이 허용되었으며, 실제로 무엇이 변경되었는가? 트레이스(trace)는 토큰과 지연 시간(latency)을 보여줄 수 있습니다. 애플리케이션 로그는 HTTP 200을 보여줄 수 있습니다. 어느 쪽도 신뢰할 수 있는 답변은 아닙니다.
부족한 부분은 **AI 에이전트 의사결정 로그 (AI agent decision log)**입니다. 이는 의미 있는 모든 선택에 대한 작고 구조화된 기록입니다. 이 로그는 태스크(task), 경계가 설정된 증거(bounded evidence), 적용 중인 정책 및 릴리스(policy and release in force), 선택된 행동, 그리고 독립적으로 검증된 결과와 연결합니다. 이것은 전사(transcript)가 아니며, 숨겨진 추론 아카이브여서는 안 됩니다.
이 가이드는 엔지니어가 사고를 디버깅하고, 운영 담당자가 위험한 행동을 검토하며, 고객 데이터 팀이 모든 프롬프트의 두 번째 사본을 상속받지 않도록 그러한 기록을 구축하는 방법을 보여줍니다.
트레이스는 의사결정 기록이 아니다
둘 다 보관하세요. 둘은 다른 질문에 답합니다.
| 아티팩트 | 최적 용도 | 일반적으로 놓치는 것 |
|---|---|---|
| Trace | 지연 시간, 재시도(retries), 스팬(spans), 모델 호출 | 비즈니스 의도 및 정책 판정 |
| ... |
예를 들어, 지원 담당자가 갱신 상태를 변경한다고 가정해 봅시다. 트레이스는 update_subscription이 180ms 만에 완료되었음을 보여줄 수 있습니다. 유용한 의사결정 로그는 해당 요청이 인증된 계정 소유자로부터 왔으며, 계정이 renewal-policy-v4에 따라 적격했고, 행동이 위험 임계값(risk threshold) 이하를 유지했으며, 예상 버전은 27이었고, 청구 API가 요청된 상태와 함께 버전 28을 확인했음을 말할 수 있습니다.
이는 모델의 사적인 중간 텍스트가 신뢰할 수 있는 감사 아티팩트라고 가정하지 않고도 결정을 조사하고 재현하기에 충분합니다.
모든 모델 턴(model turn)이 아닌, 의사결정만 기록하라
모든 토큰을 로깅하는 것은 비용이 많이 들고, 위험하며, 노이즈가 많습니다. 또한 검토를 더 어렵게 만듭니다. **의사결정 경계 (decision boundary)**를 정의하세요: 에이전트가 해석(interpretation)에서 결과적인 분기 또는 부작용으로 넘어갈 때 로깅합니다.
좋은 경계에는 다음이 포함됩니다:
- 워크플로우 또는 외부 도구 선택;
- 요청을 승인(approval) 또는 위험(risk) 등급으로 분류;
- 기록 변경, 메시지 전송 또는 금액 청구;
- 정책에 의해 차단되어 작업을 거부함;
- 인간에게 에스컬레이션(escalating)함;
- 장시간 실행되는 작업이 완료되었음을 선언함.
각 검색 청크(retrieval chunk), 재시도(retry), 또는 초안의 문장마다 의사결정 로그를 작성하지 마십시오. 그러한 내용은 트레이스(traces)에 넣고, 필요할 때 안정적인 ID와 연결하십시오. 간결한 로그는 사고가 발생했을 때 읽기 쉬워야 합니다.
하나의 질문으로 시작하기
필드를 추가하기 전에 다음을 자문해 보십시오: 부재했던 팀원이 이 단일 기록만 보고도 이 행동의 이유, 권한 및 결과를 재구성할 수 있을까?
답변이 '아니오'라면 누락된 참조(reference)를 추가하십시오. 답변에 전체 프롬프트, 전체 고객 기록 및 생성된 모든 토큰이 필요하다면, 해당 기록이 안전하고 범위가 지정된 증거를 인용할 수 있도록 워크플로우 자체를 재설계해야 합니다.
실질적인 의사결정 로그 스키마
스키마는 거대한 JSON 블롭(blob)이 아니라 안정적인 ID를 필요로 합니다. 다음은 물질적 행동(material action)에 대한 TypeScript 형태입니다:
type DecisionLog = {
id: string;
occurredAt: string;
...
여기서 세 가지 선택 사항이 중요합니다.
첫째, requestRef, targetRef, 및 resultRef는 접근 통제된 데이터(access-controlled data)를 가리키며, 이를 복사하지 않습니다. 지원 스크립트나 송장은 기존 시스템과 그에 맞는 보존 규칙을 가지고 있어야 합니다.
둘째, 릴리스, 모델 및 정책에 대한 버전화된 식별자(versioned identifiers)를 저장해야 합니다. 어떤 답변은 한 정책 버전에서는 허용될 수 있지만 다음 버전에서는 차단될 수 있습니다. ID 없이는 과거의 결정을 정직하게 설명할 수 없습니다.
셋째, account_owner_verified 또는 refund_below_limit와 같이 _판결(verdict)과 그 공적인 이유(public reasons)_를 저장해야 합니다. 숨겨진 추론에 대한 조작된 요약은 저장하지 마십시오. 정책 엔진을 설계하여 운영자에게 노출하기 안전한 명시적 이유 코드(explicit reason codes)를 방출하도록 하십시오.
행동 전에 증거를 포착하고, 후에 검증하라
가장 안전한 형태는 2단계 기록입니다. 외부 부작용(side effect)이 발생하기 전에 계획된 결정을 작성하고, 그 후에 검증된 결과를 추가합니다.
async function changeRenewal(input: RenewalInput) {
const decision = await decide(input); // typed facts + deterministic policy
const record = await decisions.insert({
...
성공했을 때만 기록하면 안 되는 이유는, 타임아웃, 워커 충돌 또는 중복 재시도 자체가 중요하기 때문입니다. 계획된 기록은 내구성 있는 Idempotency Key를 제공합니다. 결과는 불확실성을 성공으로 조용히 바꾸는 대신 시도됨(attempted), 검증됨(verified), 그리고 **알 수 없음(unknown)**을 구별해 줍니다.
고위험 작업의 경우, 승인 대기열에 hold 기록을 전송해야 합니다. 검토자는 작업 요약, 안전한 증거 링크, 정책 이유 코드, 예상 변경 사항 및 만료일을 볼 수 있어야 합니다. 그들의 승인은 이력 수정이 아닌 또 다른 추가 전용(append-only) 이벤트가 됩니다.
기본적으로 개인 데이터를 로그에서 제외하기
결정 로그는 원시 프롬프트, 검색 텍스트, 도구 인자 또는 비밀 정보를 저장할 경우 데이터 유출(data leak)이 될 수 있습니다. 토큰 예산처럼 사생활 보호 예산(privacy budget)을 의도적으로 사용해야 합니다.
| 직접 저장 | 참조 또는 해시로 저장 | 결정 로그에 절대 저장하지 말 것 |
|---|---|---|
| 정책 버전, 판결(verdict), 시간, 작업 유형 | 요청 ID, 문서 ID, 정제된 증거 해시 | API 키, 액세스 토큰, 원시 비밀번호 |
| ... |
지속성(persistence) 전에 레다케이터(redactor)를 실행하고 버전을 지정해야 합니다. 나중에 조사할 때는 어떤 규칙 세트가 필드를 제거하거나 변환했는지 알아야 하기 때문입니다.
Replay는 동일하게 입력된 사실(facts)과 정책이 동일한 판결을 내릴지 테스트하는 것을 의미하며, 실제 도구를 다시 실행하는 것은 아닙니다.
다음 요소들로 재현(replay) 픽스처를 생성합니다:
- 정제된 입력 사실(sanitized input facts);
- 참조된 릴리스 및 정책 버전;
- 예상되는 결정, 사유 코드(reason codes), 그리고 액션 계약(action contract);
- 가짜 도구 응답 또는 기록된 결과 형태.
it("소유권 증거가 누락되었을 때 갱신 변경 사항 유지") , async () => {
const result = await evaluate({
accountOwnerVerified: false,
...
이는 모델에게 이전 사고 과정을 서술하도록 요청하는 것보다 더 안정적입니다. LLM 해석은 상위 단계(upstream)에 두고, 타입이 지정된 출력 스키마로 제약합니다. 가능한 경우 결과적인 판결을 결정론적으로 만드세요. 만약 모델이 분류해야 한다면, 허용되는 레이블, 증거 참조, 진단 신호로서의 신뢰도, 그리고 그 레이블을 액션으로 변환한 정책을 기록하세요.
사고 대응자처럼 쿼리 기록하기
좋은 기록은 모호한 질문들을 경계가 있는 쿼리로 바꿉니다:
- “어떤 정책 버전이 이 액션을 허용했는가?”
- “우리가 외부 변경 사항을 검증했는지, 아니면 단지 응답만 받았는지?”
- “어떤 릴리스가 첫
hold급증의 원인이었는가?” - “재시도(retry)가 동일한 Idempotency 키를 재사용했는가?”
- “결정 과정에서 어떤 증거 참조가 사용 불가능했는가?”
이러한 질문들을 중심으로 작은 운영 뷰(operational view)를 구축하세요. 결정 타임라인, 상태 전환(state transitions), 정책 사유 코드, 릴리스 ID, 그리고 안전 링크들을 보여주세요. 다듬어진 채팅 요약으로 시작하지 말고, 요약을 검증할 수 있는 데이터로 시작하세요.
특히 유용한 경고는 unknown 결과의 증가하는 카운트입니다. 이는 불편한 중간 상태를 포착합니다: 도구 호출이 목적지에 도달했을 수는 있지만, 귀하의 서비스가 아직 무엇이 일어났는지 증명할 수 없는 경우입니다. 이는 자동 재시도(automatic retry)가 아닌 조정(reconciliation)을 필요로 합니다.
일반적인 실패 모드
무한한 프롬프트 블롭 로깅
고객이 삭제를 요청하거나, 컨텍스트에서 비밀 정보가 나타나거나, 운영자가 특정 사실을 빠르게 필요로 할 때까지는 완벽하게 느껴집니다. 제약된 요약과 참조(references)를 저장하고, 원본 데이터는 해당 데이터를 책임지는 시스템에 보관하세요.
모델 신뢰 점수를 권한으로 취급하기
신뢰도는 허가(permission)가 아닙니다. 높은 점수가 소유권 확인, 지출 한도 또는 검토자를 대체하지 못합니다. 정책이 분류가 행동이 될 수 있는지 여부를 결정해야 합니다.
HTTP 응답을 “검증됨”으로 부르기
승인된 요청이라도 나중에 거부되거나, 두 번 적용되거나, 잘못된 버전에 적용될 수 있습니다. 반환되는 버전(returned version), 다운스트림 이벤트 ID(downstream event ID), 읽기 후 쓰기 확인(read-after-write check) 또는 조정 작업(reconciliation job)을 선호하세요.
로그를 편집 가능하게 만들기
수정은 가치가 있지만, 기록 덮어쓰기는 그렇지 않습니다. 원래 레코드, 행위자(actor), 그리고 이유를 명시하는 수정 이벤트를 추가하세요. 이렇게 하면 조사 추적 경로(investigation trail)가 보존됩니다.
팀을 멈추게 하지 않을 배포 계획
티켓 상태 변경이나 외부 메시지 생성과 같이 가치가 높은 도구 액션 하나부터 시작하세요. 해당 액션의 입력 사실, 위험 등급, 정책 이유, Idempotency Key, 그리고 검증 방법을 정의합니다. 대시보드를 추가하기 전에 로그 스키마를 테스트에 넣으세요.
다음으로 hold와 unknown 상태를 추가하세요. 팀들은 종종 성공과 실패만 기록하지만, 이 두 가지 상태는 실제 운영상의 모호성을 포착합니다. 마지막으로 해당 레코드를 기존의 추적(trace) 및 릴리스 매니페스트에 연결하세요. 이렇게 하면 관찰 가능성(observability), 배포(deployments), 또는 접근 제어(access control)를 대체하지 않으면서 설명 계층을 얻게 됩니다.
결과는 자율 데모만큼 화려하진 않지만, 프로덕션에서는 더 유용합니다. 에이전트는 빠르게 행동할 수 있으면서도, 무엇을 할 수 있도록 허가되었는지와 시스템이 나중에 어떻게 증명했는지에 대한 명확하고 개인정보 보호를 고려한 설명을 남길 수 있습니다.
CI에서 계약 테스트하기
의사결정 로그를 API 계약으로 취급하세요. 만약 릴리스가 정책 버전을 제거하거나, 이유 코드를 변경하거나, 원시 이메일 주소를 직렬화(serializing)하기 시작한다면, 그 변화가 프로덕션에 도달하기 전에 빌드가 실패해야 합니다.
세 가지 작은 테스트부터 시작합니다:
- 스키마 테스트 (Schema test): 모든 필수 필드가 존재하고 모든 참조가 허용된 접두사를 사용했는지 확인합니다.
- 삭제(Redaction) 테스트: 현실적인 프롬프트와 도구 응답이 비밀 정보, 직접 식별자 또는 승인되지 않은 필드를 포함할 수 없는지 확인합니다.
- 전환(Transition) 테스트:
unknown상태가verified또는rejected로 변경될 수는 있지만, 최종 결과는 조용히 덮어쓰여질 수 없습니다.
it("raw customer text를 영속시키지 않음", () => {
const record = toDecisionLog({
task: { summary: "invoice 8841에 대해 [email protected]에게 이메일 보내기" },
...
삭제 처리를 거친 사고(incidents) 및 아차사고(near misses)의 테스트 케이스(fixtures)를 사용하세요. 중복된 재시도(retry)가 여전히 독립성 키(idempotency key)를 보존한다는 것을 증명하는 테스트 케이스가 일반적인 성공 경로 예제보다 더 가치가 있습니다. 정책이 의도적으로 변경될 때는 애플리케이션 권한 변경만큼 신중하게 테스트 케이스의 차이점(fixture diff)을 검토해야 합니다.
마지막 규칙 하나는 다중 에이전트 시스템에 도움이 됩니다: 한 에이전트가 다른 에이전트에게 위임할 때 parentDecisionId를 할당하세요. 자식 에이전트는 여전히 자체 정책과 결과를 기록합니다. 이렇게 하면 조사관이 사용자 요청부터 도구 동작까지의 계층 구조(tree)를 검색 가능한 트랜스크립트로 모두 병합하지 않고 추적할 수 있습니다.
FAQ
AI 에이전트 의사결정 로그에는 무엇을 포함해야 하나요?
안정적인 결정 ID, 시간, 작업 참조, 릴리스 및 정책 버전, 안전한 증거 참조, 정책 판정(verdict) 및 이유 코드, 계획된 동작, 독립성 키, 그리고 검증되었거나 알 수 없는 결과가 포함되어야 합니다. 원본 프롬프트와 숨겨진 추론 과정은 피하세요.
AI 에이전트 의사결정 로그는 관측 가능성 트레이스(observability traces)와 동일한가요?
아닙니다. 트레이스는 실행 성능과 호출 경로를 진단합니다. 결정 로그는 비즈니스 및 정책 용어에서 중요한 분기 또는 동작을 설명합니다. 둘 중 하나가 두 가지 역할을 모두 수행하도록 강요하기보다는, 서로 연결하여 사용하세요.
AI 에이전트 의사결정 로그에 사고의 흐름(chain of thought)을 저장해야 하나요?
아닙니다. 대신 명시적이고 검토 가능한 정책 이유와 안전한 증거 참조를 저장하세요. 이는 운영 측면에서 더 신뢰성이 높고, 민감하며 무한한 모델 텍스트를 불필요하게 저장하는 것을 방지합니다.
AI 에이전트의 행동은 실제로 발생했는지 어떻게 확인할 수 있나요?
멱등성 키(idempotency key)와 도메인 레벨 확인(domain-level confirmation)을 사용하세요. 반환된 버전, 영속적인 다운스트림 이벤트(durable downstream event), 쓰기 후 읽기 검사(read-after-write check), 또는 조정 프로세스(reconciliation process)가 될 수 있습니다. 해당 확인이 존재할 때까지 unknown으로 기록하세요.
의사결정 로그는 얼마나 오래 보관해야 하나요?
보존 기간은 기반 비즈니스 프로세스, 계약적 필요성, 그리고 개인정보 보호 정책에 맞춰야 합니다. 가장 작은 유용한 기록을 유지하고, 연결된 민감한 아티팩트(sensitive artifacts)는 자체 통제 하에 별도로 보관하며, 삭제 및 접근 규칙을 테스트하세요.
소규모 팀이 새로운 플랫폼 없이 이것을 구현할 수 있나요?
네. 추가 전용 데이터베이스 테이블(append-only database table) 또는 이벤트 스트림(event stream), 타입 스키마 유효성 검사(typed schema validation), 정책 사유 코드(policy reason codes), 그리고 기존 추적 및 기록에 대한 링크로 시작하세요. 기본적인 계약이 작동한 후에만 전문화된 도구링을 추가하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기