에이전트 로그를 모두 남기면 관측성이 좋아질까
AI 에이전트의 실행을 추적할 때 무엇을 구조화해 남기고 어떤 원문은 수집하지 않을지, OpenTelemetry의 GenAI 의미 규약과 프라이버시 경계를 바탕으로 AKM 운영 원칙을 제안한다.

이 글의 개념을 표현하기 위해 GPT Image 2로 생성한 이미지이며, 실제 관측 시스템 화면이나 운영 데이터를 재현한 것이 아니다.
문서 갱신 에이전트가 밤사이 멈췄다고 해 보자. 마지막 화면에는 "도구 실행 실패"만 남았다. 어느 문서를 읽었는지, 같은 호출을 몇 번 반복했는지, 외부 저장소에 일부라도 썼는지 알 수 없다. 다음 날 운영자는 원인보다 먼저, 이 일을 다시 돌려도 되는지부터 추측한다. 기록이 너무 적어서 생기는 실패다.
기록을 늘리면 다른 문제가 생긴다. 디버깅을 쉽게 만들겠다는 이유로 사용자의 질문, 검색한 문서, 시스템 지시, 도구 인자와 결과를 통째로 저장한다. 장애는 더 자세히 보일지 모르지만 인사 문서, 고객 정보, 접근 토큰, 아직 공개하지 않은 원고가 관측 저장소에 복제될 수 있다. 운영 권한보다 넓은 사람이 그 내용을 읽거나, 원래 업무보다 훨씬 긴 보존 기간이 적용될 수도 있다. 기록량을 늘린다고 관측성과 안전이 함께 좋아지지는 않는다.
에이전트 관측성은 모든 생각을 보관하는 일과 다르다. 실행을 다시 설명할 수 있도록 단계와 관계, 시간, 상태, 오류, 비용, 산출물 증거를 남기는 일에 가깝다. 원문 payload는 그 목적에 꼭 필요한 범위에서 별도로 다뤄야 한다. 이 글은 OpenTelemetry의 GenAI 의미 규약과 W3C Trace Context, AgentOps 연구를 함께 읽고, 그 경계를 AKM 업무에 적용하는 방법을 제안한다. 아래 AKM 설계는 공개 표준의 구현 성과가 아니라 DEXA의 운영 제안이다.
트레이스는 실행의 관계를 보여 주는 지도다
일반 로그는 "무슨 일이 있었다"는 개별 사건을 시간순으로 적는 데 강하다. 트레이스는 한 요청이 모델 호출, 검색, 도구 실행, 사람 승인 같은 여러 단계를 어떻게 통과했는지 관계로 묶는다. 하나의 실행을 trace로 두고 그 안의 논리적 작업을 span으로 나누면, 어느 단계가 오래 걸렸고 어떤 오류에서 경로가 갈렸는지 볼 수 있다. 같은 오류 문자열이 여러 번 찍혔더라도 한 번의 논리적 작업 안에서 자동 재시도된 것인지, 별도 실행이 중복으로 시작된 것인지 구분할 수 있다.
OpenTelemetry의 현재 GenAI span 문서는 span이 호출자가 관찰한 논리적 작업을 나타내며, 작업 시작부터 응답을 모두 받거나 오류·취소로 종료될 때까지를 덮어야 한다고 설명한다.[1] 자동 재시도가 있었다면 각각을 서로 무관한 성공처럼 세지 않고, 재시도를 포함한 논리적 작업의 지속 시간을 span에 담도록 권한다. 문서는 모델 추론뿐 아니라 retrieval, memory, tool execution을 위한 span 형태도 제시한다.
여러 도구를 섞어 쓸수록 이런 공통 어휘가 필요하다. gen_ai.operation.name, 요청·응답 모델, 종료 이유, 토큰 사용량, error.type 같은 필드를 일정하게 남기면 공급자별 로그 문자열을 매번 해석하지 않아도 된다.[1][2] 도구 호출에는 도구 이름과 호출 ID를 연결하고, 에이전트에는 안정적인 식별자와 버전을, workflow에는 낮은 cardinality의 안정적인 이름을 붙일 수 있다. 다만 문서의 GenAI 규약은 현재 Development 상태다. 필드와 요구 수준이 바뀔 수 있으므로, 이를 변하지 않는 데이터베이스 계약처럼 고정하면 안 된다.
W3C Trace Context가 해결하는 범위는 더 좁고 분명하다. traceparent는 분산된 요청이 같은 trace의 어느 위치에 있는지 전달하고, 선택적인 tracestate는 공급자별 정보를 함께 운반한다.[3] 이는 여러 서비스 사이에서 trace가 끊어지지 않게 하는 전파 규약이지, 프롬프트 원문이나 업무 결과를 저장하라는 규약이 아니다. 문맥 식별자를 전달하는 일과 내용 전체를 수집하는 일은 분리해야 한다.
원문 payload는 기본값이 아니라 별도 선택이다
OpenTelemetry GenAI 규약은 입력·출력 메시지, 시스템 지시, prompt 변수, tool definition, 도구 호출 인자와 결과를 표현할 필드를 마련해 두었다.[1][2] 그러나 해당 필드가 존재한다는 사실은 모두 수집하라는 뜻이 아니다. gen_ai.input.messages, gen_ai.output.messages, gen_ai.system_instructions, gen_ai.tool.definitions는 Opt-In으로 표시되어 있다.[1] 속성 레지스트리는 입력과 출력 메시지에 사용자 정보나 개인정보가 들어갈 가능성이 높다고 경고하며, memory query와 memory record도 기본 수집을 피하고 명시적 opt-in으로 열도록 권한다.[2]
에이전트에서는 이 구분이 더 절실하다. 일반 웹 요청의 body에도 민감한 값이 들어갈 수 있지만, 에이전트의 입력과 도구 결과는 긴 대화, 내부 문서, 파일 내용, 검색 결과를 한꺼번에 담는다. 도구 인자에는 파일 경로나 수신자, 쿼리, 계정 식별자가 섞일 수 있다. 결과 payload에는 문서 본문이나 API 응답이 그대로 돌아온다. 전체를 수집하면 원래 시스템보다 관측 저장소가 더 큰 비밀 저장소가 된다.
그래서 설계는 "무엇을 더 기록할까"보다 "어떤 운영 질문에 답해야 할까"에서 시작해야 한다. 지연 원인을 찾으려면 span 이름, 시작·종료 시각, 상태, 재시도 횟수, 공급자와 모델, 토큰 사용량이면 충분할 수 있다. 중복 부작용을 확인하려면 tool call ID, idempotency key, 대상의 불투명 식별자, 전후 상태를 읽은 receipt가 필요하다. 검색 품질을 분석할 때도 문서 원문 대신 검색기 버전, 자료 집합 ID, 반환 문서 ID, 순위와 점수를 우선 남길 수 있다.
원문이 꼭 필요한 경우도 있다. 특정 입력에서만 발생하는 파서 오류를 재현하거나, 안전 필터가 어떤 문장을 잘못 처리했는지 검토하려면 제한된 표본이 필요할 수 있다. 그때도 전역 기본값을 켜기보다 해당 실행과 기간, 접근 주체를 좁힌다. 수집 전에 비밀값과 개인정보를 제거하고, 관측 데이터의 보존 기간을 업무 원본보다 짧게 정한다. 내용 접근 기록도 남겨야 한다. "디버깅용"이라는 이름은 무기한 복제를 허용하는 보존 근거가 아니다.
관측 기록과 완료 증거는 같은 물건이 아니다
트레이스가 자세하면 실행 경로는 잘 보인다. 그렇다고 작업의 성공까지 증명되는 것은 아니다. 모델 호출 span이 성공했고 도구가 200 응답을 돌려줘도, 잘못된 문서를 수정했거나 외부 시스템이 요청을 접수만 했을 수 있다. span status는 관찰한 작업의 종료 상태를 말한다. 업무 세계가 의도한 상태로 바뀌었다는 판정은 별도 증거가 필요하다.
여기서 완료 증거와 재시도 설계의 경계가 다시 드러난다. 관측 트레이스는 어떤 호출이 언제 일어났는지 설명한다. 완료 증거는 목표 파일의 해시, 게시된 URL의 응답, 데이터베이스 read-back, 승인자의 판정처럼 결과 상태를 확인한다. 둘을 연결하되 합치지 않아야 한다. trace ID만으로 성공을 선언하지 않고, 완료 증거에는 어느 실행이 만들었는지 trace ID와 작업 ID를 참조하게 한다.
AgentOps 연구는 에이전트 관측 도구를 tracing, prompt management, 비용·지연 측정, 평가와 guardrail 등으로 분류해 비교한다.[4] 이 연구는 2024년에 작성된 도구 생태계의 mapping study다. 특정 제품이 장애를 줄인다는 인과 효과나 하나의 표준 구현을 증명하지 않는다. 다만 모델 호출 하나만 봐서는 에이전트 운영을 설명하기 어렵고, prompt, tool, evaluation, 비용과 지연까지 관측 범위가 넓어진다는 점은 선명하게 정리한다. 문제는 이 기능 목록을 모두 켜는 것이 아니라, 각 기록이 어떤 판단과 복구에 쓰이는지 정하는 일이다.
AKM에서는 내용보다 계약을 먼저 기록한다
AKM의 검색·요약·문서 갱신 흐름이라면 기본 trace에 원문부터 넣을 이유가 없다. 먼저 작업 계약을 남긴다. 예를 들어 runId, workItemId, 입력 revision, workflow 버전, 실행 주체, 시작·종료 시각, 단계 상태, 재시도 번호, 오류 분류를 기록한다. 검색 단계에는 query 원문보다 query hash나 분류, data source ID, 반환 문서 ID와 점수를 남긴다. 문서 갱신 단계에는 본문 전체보다 대상의 안정적 ID, 변경 전후 hash, 변경된 필드 목록, 검증 결과를 기록한다.
식별자도 그대로 노출하지 않는다. 이메일 주소나 로컬 파일 경로를 span 이름과 label에 넣으면 검색과 집계가 쉬워지는 대신 모든 관측 화면에 퍼진다. 사람이 읽는 이름과 내부 ID를 분리하고, 관측용 ID는 다른 데이터와 결합하지 않으면 개인을 바로 가리키지 않도록 설계한다. 임의의 내용을 hash했다고 자동으로 익명이 되는 것도 아니다. 입력 후보가 적으면 사전 대입으로 원문을 추정할 수 있으므로, hash는 무결성 확인과 동일성 비교에 쓰고 개인정보 익명화 수단으로 과장하지 않는다.
span 이름과 label은 낮은 cardinality를 유지한다. 문서 제목이나 질문 전체를 이름에 넣으면 같은 종류의 작업을 묶어 보기 어렵고 저장 비용도 커진다. retrieve, summarize, validate, publish처럼 안정된 작업 이름을 두고, 대상은 제한된 속성으로 분리한다. 오류도 전체 메시지를 집계 key로 쓰지 않고 timeout, permission_denied, validation_failed처럼 관리 가능한 분류와 제한된 상세 정보를 나눈다.
같은 trace를 본다고 모든 사람이 원문까지 볼 이유는 없다. 구조 메타데이터, 제한된 진단 payload, 완료 증거를 서로 다른 저장소나 접근 계층에 둘 수 있다. 운영자는 단계와 상태를 보고, 승인된 조사자만 짧은 기간 동안 원문 표본을 연다. 보존 기간도 나눈다. 집계 지표는 추세 비교를 위해 오래 남길 수 있지만, 원문 payload와 도구 결과는 재현에 필요한 기간 뒤 삭제하거나 접근 불가능하게 만든다.
먼저 답할 질문 다섯 개
작은 에이전트 흐름부터 다음 질문을 적어 두면 된다.
- 이 trace가 답해야 할 운영 질문은 무엇인가?
- 기본 수집 필드만으로 그 질문에 답할 수 있는가?
- 원문이 필요하다면 어떤 실행, 기간, 역할에만 허용할 것인가?
- trace 상태와 실제 업무 완료를 어떤 독립 증거로 대조할 것인가?
- 규약 버전이 바뀌거나 삭제 요청이 들어오면 어떤 기록을 다시 해석하거나 지울 수 있는가?
처음부터 거대한 관측 플랫폼을 만들 이유도 없다. 한 workflow를 골라 단계 이름과 상태, 상관 ID, 지연, 오류 분류, 최소 완료 증거만 남긴다. 그 기록으로 실제 장애 하나를 복구해 보고, 답하지 못한 질문이 있을 때 필드를 추가한다. 원문 payload는 마지막 수단으로 둔다.
로그가 많아질수록 보이는 것이 늘어날 수는 있다. 동시에 복제되는 비밀과 비용, 접근해야 할 사람이 늘어난다. 좋은 관측성의 기준은 저장한 글자 수가 아니라, 필요한 사람이 실패 경로를 설명하고 안전하게 재개할 수 있는가에 있다. 에이전트의 모든 내용을 남기지 않아도 실행은 충분히 설명할 수 있어야 한다.
참고 자료
- OpenTelemetry, Semantic conventions for generative client AI spans, 2026-09-25 확인. GenAI span의 범위, 상태, 재시도, payload opt-in 요구 수준을 확인했다.
- OpenTelemetry, Gen AI attribute registry, 2026-09-25 확인. 메시지·memory·도구 인자 속성의 민감정보 경고와 필드 정의를 확인했다.
- W3C, Trace Context Level 1, W3C Recommendation, 2021-11-23.
traceparent와tracestate의 전파 범위를 확인했다. - AgentOps: Enabling Observability of LLM Agents, arXiv:2411.05285 v2, 2024. 에이전트 관측 도구의 기능 범주를 정리한 mapping study로 참고했다.