AI 에이전트가 환자 기록을 내보냈습니다. 하지만 당신의 로그는 누가 그렇게 시켰는지 말해주지 못합니다.
요약
LLM 에이전트가 수행한 작업의 실제 주체(인간)를 식별하지 못하는 감사 로그 문제를 다룹니다. EU AI Act 등 규제 대응을 위해 모델의 출력이 아닌 런타임 수준에서 신원을 기록하는 Crumb 솔루션을 제안합니다.
핵심 포인트
- 에이전트의 공유 자격 증명 사용 시 실제 명령자를 추적하기 어려움
- EU AI Act는 고위험 시스템에서 관련 자연인의 식별을 요구함
- 프롬프트 기반 신원 기록은 프롬프트 인젝션에 취약하여 신뢰할 수 없음
- 런타임 게이트웨이를 통해 검증된 세션에서 신원을 직접 기록해야 함
당신은 LLM 에이전트(LLM agent)를 프로덕션 환경에 배포했습니다. 소프트웨어 자격 증명(credentials)을 부여하는 방식에 따라, 에이전트는 서비스 계정(service account) 또는 공유 API 키(shared API key) 하에서 실행됩니다. 에이전트는 기록을 읽고, 파일을 내보냅니다. 때로는 돈을 옮기기도 합니다. 당신의 감사 로그(audit log)는 그 동작을 충실히 기록합니다. 로그에는 _에이전트가 수행했다_라고 기록됩니다.
하지만 _어떤 사람이 에이전트에게 그렇게 시켰는지_는 말해주지 않습니다.
문제가 생기기 전까지는 괜찮을 것입니다. 만약 에이전트가 해서는 안 될 행동을 했을 때, "서비스 계정이 수행했습니다"라는 말은 누구도 조치를 취할 수 없는 답변입니다. 서비스 계정을 징계할 수는 없습니다. 규제 기관에 봇이 책임자였다고 말하고 그냥 넘어갈 수도 없습니다.
이 문제를 구체화하는 마감 기한
EU AI Act(유럽 AI 법) 제12조가 2026년 8월 2일에 발효됩니다. 고위험 시스템(High-risk systems)은 이벤트에 "관련된 자연인(natural persons)의 식별"을 허용하는 로그를 유지해야 합니다. 자연인 말입니다. 서비스 계정도, 에이전트 ID도 아닙니다. 실제 사람이어야 합니다.
공유 자격 증명을 기반으로 구축된 로그는 그 질문에 답할 수 없습니다. 신원(identity)이 결코 캡처되지 않았기 때문에, 아무리 로그 보존 기간을 늘려도 이를 되살릴 수 없습니다.
프롬프트만으로는 이 문제를 해결할 수 없습니다
당연한 본능은 모델이 누구를 위해 행동하고 있는지 보고하도록 만드는 것입니다. 시스템 프롬프트(system prompt)에 사용자를 넣고, 에이전트가 도구 호출(tool call)에 이를 포함하게 하는 방식입니다.
여기에는 두 가지 문제가 있습니다.
네트워크 상의 도구 호출은 {"name": "export_record", "arguments": {...}} 형태입니다. _누가(who)_에 대한 필드가 없습니다. OpenAI의 함수 호출(function-calling) 기능에는 네이티브 신원 슬롯(identity slot)이 없습니다. MCP(Model Context Protocol)는 이를 전달하는 것을 허용하지만, 거의 아무도 이를 구현하지 않습니다. 따라서 프로토콜 수준에서 "누가"에 해당하는 정보가 머물 곳은 없습니다.
더 심각한 것은, 모델이 생성하는 모든 것은 프롬프트 인젝션(prompt-injected)될 수 있다는 점입니다. 만약 신원이 모델_로부터_ 나온다면, 에이전트가 도구로부터 읽어온 데이터가 그 신원을 다시 써버릴 수 있습니다. 저는 동일한 페이로드를 두 가지 방식으로 전달하여 테스트해 보았는데, 도구의 _출력(output)_보다 도구의 _설명(description)_이 더 많은 모델을 하이재킹(hijacked)했습니다. 모델의 출력은 신원을 위해 절대 신뢰할 수 없는 유일한 표면입니다. 모델이 관여하기 전에, 에이전트의 추론 외부에서 런타임(runtime)에 의해 신원이 찍혀야(stamped) 합니다.
그래서 저는 이를 기록(stamp)하는 런타임(runtime)을 구축했습니다. 이름은 Crumb입니다. 모든 에이전트의 행동은 하나의 '부스러기(crumb)'를 남기며, 이 흔적은 해당 행동을 지시한 인간에게로 거슬러 올라갑니다.
그 구조 (The shape of it)
단 하나의 게이트웨이(gateway)를 통해 모든 도구 호출(tool call)이 통과합니다.
이 게이트웨이는 로그인 시 한 번 캡처되어 모델로부터는 절대 가져오지 않는, 검증된 세션(verified session)으로부터 인간의 신원을 추출합니다. 그리고 두 신원을 모두 담은 수명이 짧은 위임 토큰(delegation token)을 발행합니다. 이때 인간은 RFC 8693의 sub로, 에이전트는 호출되는 단일 리소스에 한정된 act로 포함됩니다. 그런 다음, 각 항목이 Ed25519로 서명된 추가 전용(append-only) 해시 체인 원장(hash-chained ledger)에 부스러기를 기록하고, 해당 토큰과 함께 도구를 호출합니다. 도구는 유효한 토큰을 지니지 않은 모든 호출을 거부하므로, 이를 건너뛰고 데이터에 접근할 수 있는 경로는 존재하지 않습니다.
이 위임 토큰은 임의로 만들어진 것이 아닙니다. 이는 ID 제공자(identity provider)를 대상으로 하는 실제 RFC 8693 토큰 교환(token exchange) 방식입니다. 인간의 세션이 subject_token으로 입력되면, RS256 방식으로 제공자가 서명한 복합 토큰(composite)이 반환되며, 리소스는 제공자가 공개한 JWKS를 통해 이를 검증합니다. 공유 비밀(shared secret)은 필요하지 않습니다. Okta, Keycloak 또는 Zitadel을 대상으로 지정하더라도 동일한 코드 경로가 유지되는데, 이는 이것이 커스텀 복제본이 아닌 표준(standard)이기 때문입니다.
실제로 문제가 발생하는 부분: 하나 이상의 에이전트
단일 에이전트가 도구를 호출하는 것은 쉬운 사례입니다. 실제 시스템은 그렇게 작동하지 않습니다. 인간이 오케스트레이터(orchestrator)를 지시하고, 오케스트레이터는 하위 에이전트(sub-agent)에게 권한을 위임하며, 하위 에이전트가 도구를 호출합니다. 그렇다면 인간이 행동으로부터 두 단계(two hops) 떨어져 있을 때, 누가 책임을 져야 하며 이를 어떻게 증명할 수 있을까요?
이 지점에서 대부분의 귀속(attribution) 관련 이야기들은 조용히 멈춰버립니다. 표준화 기구들조차 이 문제를 완전히 해결하지 못했습니다. 하지만 RFC 8693의 4.1절에는 숨겨진 메커니즘이 있습니다. 바로 act 클레임(claim)이 중첩(nest)될 수 있다는 점입니다. 각 새로운 행위자(actor)는 이전 행위자를 감싸며(wrap), 인간은 전체 과정의 루트(root)에서 sub로 남습니다. 이 중첩 구조를 역으로 따라가면, 누가 누구를 위해 행동했는지에 대한 전체 체인을 얻을 수 있으며, 이는 이 모든 것을 시작한 사람에게서 끝납니다.
따라서 Crumb는 이를 엔드 투 엔드 (end-to-end)로 구현합니다. 각 홉 (hop)은 이전 행위자를 중첩합니다. 제공자는 개발 편의를 위한 지름길이 아닌, 실제 토큰 교환을 통해 중첩을 수행합니다. Crumb는 전체 체인을 기록합니다. 그리고 전체 중첩 구조가 하나의 토큰으로 서명되기 때문에, 각 홉마다 위조할 수 있는 이음새가 존재하지 않습니다. 제가 직접 테스트해 보았습니다: 체인 중간의 행위자를 다시 쓰고 키 없이 재서명해 보았으나, 검증 과정에서 서명 오류로 거부되었습니다. 체인이 온전하게 유지되지 않으면 검증을 통과할 수 없습니다.
Alice가 로그인할 때 read_record라는 하나의 동작을 승인합니다. 플래너 에이전트 (planner agent)가 그녀의 요청을 받아 리서처 서브 에이전트 (researcher sub-agent)에게 위임합니다. 리서처는 기록을 읽습니다. Crumb는 이를 두 에이전트를 거쳐 Alice에게까지 역추적하며, 이는 검증됩니다.
그 후, 하나의 홉이 탈주하여 Alice가 승인한 적 없는 export_record를 호출합니다. 기술적으로 해당 동작은 실행될 수 있습니다. 하지만 Crumb는 그 뒤에 숨겨진 인간의 지시가 없음을 기록합니다. Crumb는 해당 동작을 승인되지 않은 것으로 표시하고, 이를 수행한 에이전트 체인을 명시합니다. 기록에는 Alice가 남아 있지만, 그녀가 책임자라는 사실은 증명될 수 없습니다.
서비스 계정 (service-account) 로그는 그렇게 할 수 없습니다. 로그는 봇이 기록을 내보냈다고 말하고 거기서 멈춥니다. 반면 Crumb는 Alice의 이름을 통해 그녀의 결백을 증명하고, 대신 에이전트들을 지목합니다.
스스로에 대한 공격을 포함한 변조 방지 (Tamper-evidence)
서명된 해시 체인 (hash-chained) 로그는 서명 키를 누가 보유하고 있는지를 기억하기 전까지는 변조가 불가능해 보입니다. 바로 당신이 보유하고 있습니다. 만약 당신이 재서명을 할 수 있다면, 역사를 새로 쓰고 전체 체인을 재서명할 수 있으며, 각 항목별 검증 (per-entry verification)은 위조를 통과하게 됩니다. 모든 항목이 당신에 의해 유효하게 서명되었기 때문입니다.
그래서 이 원장 (ledger)은 머클 루트 (Merkle root)를 체크포인트로 생성하고, 이를 Sigstore의 공개 Rekor 투명성 로그 (transparency log)에 게시합니다. 이제 운영자 롤백 공격 (operator-rollback attack)은 무너집니다. 당신이 Crumb를 새로 쓰고 전체 체인을 재서명하더라도, 항목별 검증은 여전히 통과할 것입니다. 하지만 새로 작성된 루트는 당신의 수정 이전에 타임스탬프가 찍혀 Rekor에 이미 공개되어 있는 루트와 더 이상 일치하지 않습니다. 위조는 당신이 통제할 수 없는 무언가에 의해 적발됩니다. 라이브 데모에는 정확히 이 과정을 실행하여 앵커 (anchor)가 이를 잡아내는 모습을 보여주는 버튼이 있습니다.
이것이 아닌 것
이 부분은 제가 명확히 짚고 넘어가고 싶은 부분입니다. 왜냐하면 귀속 (attribution) 분야는 과장하기 쉬운 영역이기 때문입니다.
Crumb는 비행 기록 장치 (flight recorder)이지, 제어 평면 (control plane)이 아닙니다. 무언가를 중단시키는 것은 별개의 영역이며 충분한 자금이 투입되는 작업입니다. Cerbos, Capsule, Astrix가 이미 그 역할을 수행하고 있습니다. Crumb는 기록하고 증명합니다. 그 외의 나머지 작업은 이들을 지목할 뿐입니다.
귀속 (attribution)의 강도는 게이트웨이 (gateway)의 강도와 동일합니다. 게이트웨이를 우회하면 기록 (crumb)이 남지 않으므로, 게이트웨이는 선택 사항이 아니라 실제로 존재하며 강제되어야 합니다.
멀티 홉 체인 (multi-hop chain)은 이제 두 개의 ID 제공자 (identity provider)에 걸쳐 있으며, 명확히 언급할 주의 사항이 있습니다. 어떤 RFC도 교차 발행자 위임 (cross-issuer delegation)을 정의하지 않으므로, Crumb는 하나의 관례 (convention)로 이를 해결합니다. 즉, 각 발행자의 토큰이 그 이전의 토큰을 스테이플 (staple)하며, 검증 과정은 체인을 따라 인간에게까지 거슬러 올라가며 각 세그먼트를 해당 발행자의 키로 확인합니다. 이는 데모에서 실행되며, 다섯 가지 서로 다른 위조 (forgery)를 이름별로 거부합니다. 이것이 기반을 두는 것은 명시적인 연합 신뢰 집합 (explicit federation trust set)입니다. 어떤 발행자를 수락할지는 여전히 당신이 결정합니다. 저는 그 결정을 숨기는 대신 명시적으로 만들었습니다. 이를 해결된 표준 (solved standard)이라고 부르는 것이야말로 제가 피하고자 하는 과장일 것입니다.
원시 데이터 (sensitive data)가 로그에 남지 않도록, 원장 (ledger)에는 인자 (arguments)의 해시 (hash)를 저장하며 원시 인자 자체를 저장하지는 않습니다. 이로 인한 트레이드오프 (tradeoff)는 어떤 동작이 발생했는지와 누가 이를 지시했는지는 증명할 수 있지만, 수정된 정확한 바이트 (bytes) 데이터는 알 수 없다는 점입니다.
MCP 귀속 (attribution)은 스펙 (spec)에 의해 허용되지만 업스트림 (upstream)에서 구현되는 경우는 드뭅니다. 따라서 Crumb는 기록에 도장을 찍을 수는 있지만, 규정을 준수하지 않는 서버가 인간의 신원 (human identity)을 존중하도록 강제할 수는 없습니다.
이것이 구축된 것과 마케팅 사이의 간극입니다. 이 분야에서 그 간극이 곧 전부입니다.
깨뜨려 보세요
데모는 crumb.alexlaguardia.dev에서 라이브로 확인할 수 있습니다. 몇 개의 기록 (crumbs)을 생성하고, 행 (row)을 조작하여 검증이 뒤집히는 것을 확인해 보세요. 운영자 롤백 (operator rollback)을 실행하여, 항목별 서명 (per-entry signing)을 통과한 위조 (forgery)를 외부 앵커 (external anchor)가 잡아내는 모습을 지켜보세요. 코드는 GitHub에 있습니다.
만약 당신이 에이전트 인프라 (agent infrastructure)를 구축하고 있으며 이 문제에 부딪혔거나, 제가 틀린 부분이 있다고 생각한다면, 의견을 듣고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기