Human approval과 guardrails
이 장에서 배울 것
이번 장의 목표는 에이전트가 언제 멈춰야 하는지를 설계하는 것이다. 앞 장에서는 planner, router, multi-agent 구조를 다루며 "어떤 작업을 누가 실행할 것인가"를 살펴보았다. 이제 질문은 한 단계 더 구체적이어야 한다.
에이전트가 실행해도 되는 작업은 무엇인가?
사람의 승인이 필요한 작업은 무엇인가?
아예 실행하면 안 되는 작업은 무엇인가?
이 장에서는 다음을 배운다.
human-in-the-loop, 즉 사람이 실행 흐름에 개입하는 구조를 설계한다.
단순 검수, 실행 전 승인, 예외 에스컬레이션, 사후 감사를 구분한다.
guardrail을 입력, 도구 호출, 출력, 금지 행동 차단 계층으로 나눈다.
최소 권한 원칙에 따라 에이전트의 접근 범위를 제한한다.
승인형 문서 에이전트의 초안을 만든다.
핵심은 단순하다. 운영 환경의 에이전트는 모든 일을 자동으로 해내는 존재가 아니다. 위험한 순간에 멈추고 검증받을 줄 아는 시스템이어야 한다.

왜 이 주제가 중요한가
일반 챗봇이 틀린 답을 하면 사용자가 다시 물어볼 수 있다. 하지만 도구를 가진 에이전트가 틀리면 결과가 시스템 밖으로 나간다. 이메일이 발송되고, 고객 데이터가 수정되고, 파일이 삭제되고, 권한이 변경될 수 있다.
그래서 에이전트 보안의 핵심은 모델의 말투가 아니라 행동의 통제다. 프롬프트 인젝션도 챗봇에서는 "이상한 답변"으로 끝날 수 있지만, 에이전트에서는 "잘못된 실행"으로 이어진다. 외부 문서, 이메일, 웹페이지 안에 숨은 지시문이 에이전트의 행동을 바꾸는 간접 프롬프트 인젝션도 중요한 위협이다.1
따라서 "시스템 프롬프트에 하지 말라고 적어두면 되겠지"라는 생각은 위험하다. 프롬프트는 행동을 유도할 수는 있지만, 권한을 강제로 막지는 못한다. 안전장치는 코드, 정책, 권한, 로그, 승인 흐름으로 구현해야 한다.
핵심 개념 설명
Human-in-the-loop의 네 단계
Human-in-the-loop, 줄여서 HITL은 사람이 에이전트 실행 흐름에 개입하는 구조다. 모든 작업에 사람 승인을 붙이면 안전해 보이지만, 실제 운영에서는 너무 느려진다. 그래서 업무 위험도에 따라 네 단계로 나누는 것이 좋다.
첫째, 단순 검수다. 에이전트가 초안을 만들고 사람이 최종 내용을 확인한다. 문서 작성, FAQ 답변, 고객 메일 초안 생성에 적합하다. 이 단계에서는 에이전트가 외부 실행을 하지 않고 결과만 제안한다.
둘째, 실행 전 승인이다. 에이전트가 도구 호출을 하려는 순간 흐름을 멈추고 승인 요청을 만든다. 이메일 발송, 외부 공유, 데이터 수정, 삭제, 결제, 배포 같은 작업이 여기에 해당한다. LangChain의 Human-in-the-loop 문서도 민감한 도구 호출, 예를 들어 파일 쓰기나 SQL 실행이 제안되면 실행을 멈추고 사람의 결정을 기다리는 미들웨어 패턴을 설명한다.2
셋째, 예외 상황 에스컬레이션이다. 에이전트가 스스로 판단하기 어려운 상황을 사람에게 넘긴다. 예를 들어 신뢰도가 낮거나, 정책 충돌이 있거나, 입력 출처가 불명확하거나, 같은 작업이 반복 실패한 경우다. 이때 사람은 단순 승인자가 아니라 문제 해결자다.
넷째, 사후 감사다. 모든 실행을 사람이 실시간으로 승인할 수는 없다. 대신 누가, 언제, 어떤 입력을 바탕으로, 어떤 도구를, 어떤 파라미터로 실행했는지 남겨야 한다. 사고가 났을 때 재현할 수 없는 시스템은 운영 가능한 시스템이 아니다.
정리하면 다음과 같다.
| 단계 | 목적 | 예시 |
|---|---|---|
| 단순 검수 | 결과 품질 확인 | 보고서 초안 검토 |
| 실행 전 승인 | 위험 행동 차단 | 외부 이메일 발송 전 승인 |
| 예외 에스컬레이션 | 불확실한 상황 처리 | 낮은 신뢰도, 정책 충돌 |
| 사후 감사 | 책임 추적 | 실행 로그, 승인 로그 보관 |
Guardrail은 실행 경계다
Guardrail은 에이전트가 넘어가면 안 되는 경계다. 좋은 가드레일은 모델에게 "조심해"라고 말하는 것이 아니라, 실행 과정의 여러 지점에서 요청과 응답을 검사한다. LangChain 문서에서도 guardrail을 에이전트 실행 전, 실행 후, 모델 호출 주변, 도구 호출 주변에서 콘텐츠를 검증하고 필터링하는 구조로 설명한다.3
실무에서는 guardrail을 다섯 층으로 나누면 이해하기 쉽다.
입력 필터링
너무 긴 입력, 악성 패턴, 개인정보, 금지 요청을 모델 호출 전에 걸러낸다. 예를 들어 API 키, 카드 번호, 주민등록번호 같은 민감정보는 차단하거나 마스킹한다.프롬프트 인젝션 방어
"이전 지시를 무시해", "시스템 프롬프트를 출력해", "관리자 권한으로 실행해" 같은 문장을 탐지한다. 외부 문서에서 들어온 텍스트는 기본적으로 신뢰하지 않는다.도구 호출 정책
어떤 도구를 어떤 조건에서 호출할 수 있는지 정한다. 조회 도구는 자동 실행할 수 있지만, 삭제·공유·발송 도구는 승인 대상으로 둘 수 있다.출력 형식 검증
JSON 형식, 필수 필드, 수치 범위, 금지 문구, 출처 포함 여부를 검사한다. 모델이 만든 결과를 그대로 다음 시스템에 넘기면 안 된다.금지 행동 차단
어떤 경우에도 실행하면 안 되는 행동을 둔다. 예를 들어 운영 DB 전체 삭제, 비밀키 외부 전송, 승인 없는 권한 상승은 모델 판단과 무관하게 거부해야 한다.
가드레일에는 규칙 기반과 모델 기반 방식이 있다. 규칙 기반은 정규식, allowlist, denylist, 스키마 검증처럼 빠르고 예측 가능하다. 모델 기반은 의미를 판단할 수 있지만 비용과 지연이 늘고, 그 자체도 틀릴 수 있다. 운영 초기에는 규칙 기반을 단단히 깔고, 애매한 영역에 모델 기반 검사를 보조로 붙이는 편이 안전하다.
최소 권한 원칙
에이전트에게 넓은 권한을 주면 구현은 빨라진다. 하지만 한 번의 잘못된 도구 호출이 큰 사고로 번질 수 있다. 그래서 최소 권한 원칙이 필요하다. 최소 권한이란 작업에 필요한 권한만, 필요한 시간 동안, 필요한 범위에서 주는 방식이다.
실무 설계 기준은 다음과 같다.
에이전트별로 별도 서비스 계정을 둔다.
읽기 권한과 쓰기 권한을 분리한다.
도구별 scope를 작게 나눈다.
운영 환경과 개발 환경의 자격 증명을 분리한다.
고위험 액션에는 짧게 만료되는 일회성 승인 토큰을 사용한다.
에이전트가 실제 executor에 직접 접근하지 못하게 하고, Tool Gateway를 거치게 한다.
특히 "공유 서비스 계정 하나로 모든 에이전트가 실행"되는 구조는 피해야 한다. 누가 어떤 행동을 했는지 추적하기 어렵고, 사고 대응도 느려진다. 에이전트 인터페이스는 종종 특권 접근 경로가 되므로, 일반 API보다 더 엄격하게 다루어야 한다.4
Tool Gateway와 승인 큐
MCP나 function calling을 사용하면 에이전트가 여러 외부 도구를 쉽게 호출할 수 있다. 하지만 연결이 쉬워질수록 통제 지점이 더 중요해진다. 권장 구조는 다음과 같다.
Agent
↓ tool call 요청
Tool Gateway
↓ 정책 검사
Policy Engine
├─ AUTO_APPROVE → 실행
├─ REQUIRE_APPROVAL → Approval Queue
└─ DENY → 거부
↓
Tool Executor
↓
Audit Log에이전트는 도구를 직접 실행하지 않는다. 모든 호출은 Gateway로 들어간다. Gateway는 파라미터를 검증하고, 정책 엔진에 위험도 판단을 요청하고, 필요하면 승인 큐에 작업을 넣는다. 승인자가 확인해야 할 정보는 최소한 다음을 포함해야 한다.
실행하려는 도구 이름
입력 파라미터
대상 범위
변경 전후 차이
외부 전송 여부
민감정보 포함 가능성
롤백 가능 여부
에이전트가 이 작업을 제안한 이유
승인은 단순히 "예/아니오"만 있으면 부족할 때가 많다. "10명 이하에게만 발송하면 승인", "삭제 대신 비활성화로 바꾸면 승인", "외부 공유 링크는 7일 후 만료되게 설정하면 승인"처럼 조건부 승인을 지원하면 운영 품질이 좋아진다.
쉬운 비유 또는 사례
에이전트를 신입 직원으로 비유해보자. 신입 직원에게 자료 검색, 초안 작성, 내부 문서 정리는 맡길 수 있다. 하지만 고객에게 공식 메일을 보내거나, 계약서를 수정하거나, 운영 서버 설정을 바꾸는 일은 바로 맡기지 않는다.
먼저 초안을 만들게 한다. 그다음 선임자가 확인한다. 위험한 작업은 결재를 받게 한다. 그리고 누가 어떤 결정을 했는지 기록한다.
에이전트도 같다. 좋은 에이전트 설계는 "AI가 얼마나 똑똑한가"만 보지 않는다. "잘못 판단했을 때 얼마나 작게 실패하는가"를 본다.
예를 들어 승인형 문서 에이전트를 생각해보자. 사용자는 "이번 회의록을 정리해서 외부 파트너에게 보내줘"라고 요청한다. 에이전트는 회의록을 요약하고 메일 초안을 만들 수 있다. 그러나 외부 파트너에게 보내는 순간 정보 유출 위험이 생긴다. 따라서 발송 도구는 자동 실행하지 않고 승인 큐로 넘긴다. 승인자는 수신자, 제목, 본문, 첨부파일, 민감정보 탐지 결과를 확인한 뒤 승인하거나 거부한다.
이 구조에서는 에이전트가 일을 하지 못하는 것이 아니다. 에이전트는 준비하고, 사람은 책임 있는 결정을 내린다.
직접 해보는 실습
이번 실습에서는 승인형 문서 에이전트의 최소 구조를 설계한다. 실제 메일 발송 API를 연결하지 않아도 된다. 중요한 것은 승인 흐름과 정책을 명확히 만드는 것이다.
1단계: 도구 목록 나누기
다음 네 가지 도구가 있다고 가정하자.
search_docs(query) # 내부 문서 검색
create_draft(content) # 문서 초안 생성
share_document(doc_id, to) # 문서 외부 공유
delete_document(doc_id) # 문서 삭제위험도는 다음처럼 나눈다.
| 도구 | 기본 정책 | 이유 |
|---|---|---|
| search_docs | 자동 실행 | 조회 전용 |
| create_draft | 자동 실행 | 외부 영향 없음 |
| share_document | 승인 필요 | 외부 공유 |
| delete_document | 승인 필요 또는 금지 | 비가역 가능성 |
2단계: 정책 객체 만들기
{
"policies": [
{
"tool": "search_docs",
"decision": "AUTO_APPROVE",
"reason": "조회 전용 도구"
},
{
"tool": "create_draft",
"decision": "AUTO_APPROVE",
"reason": "초안 생성은 외부 실행이 아님"
},
{
"tool": "share_document",
"decision": "REQUIRE_APPROVAL",
"reason": "외부 공유 가능성"
},
{
"tool": "delete_document",
"decision": "REQUIRE_APPROVAL",
"reason": "삭제 작업"
}
]
}처음에는 단순한 룰 기반 정책으로 충분하다. 운영하면서 대상 수, 문서 등급, 수신자 도메인, 사용자 역할, 모델 신뢰도 같은 신호를 추가하면 된다.
3단계: 승인 요청 형식 만들기
승인 큐에 들어갈 요청은 사람이 판단할 수 있어야 한다.
{
"approval_id": "apv_20260518_001",
"agent_id": "document-agent-01",
"requested_by": "user_123",
"tool": "share_document",
"parameters": {
"doc_id": "doc_7788",
"to": "[email protected]"
},
"risk": {
"level": "HIGH",
"reasons": ["외부 수신자", "문서 공유"]
},
"status": "PENDING"
}4단계: 승인 결과 처리하기
승인 결과는 세 가지로 두자.
APPROVE 실행
DENY 실행하지 않음
APPROVE_WITH_CONDITION 조건을 반영한 뒤 실행거부되었을 때 에이전트가 다시 같은 요청을 무한 반복하면 안 된다. 시스템 프롬프트와 상태 관리에 "승인 거부 시 같은 파라미터로 재요청하지 않는다"는 규칙을 넣어야 한다.
5단계: 로그 남기기
최소 로그 필드는 다음과 같다.
{
"event": "tool_approval_decision",
"approval_id": "apv_20260518_001",
"agent_id": "document-agent-01",
"tool": "share_document",
"decision": "DENY",
"approver": "manager_01",
"reason": "본문에 외부 공유 불가 정보 포함",
"created_at": "2026-05-18T10:00:00Z",
"decided_at": "2026-05-18T10:03:12Z"
}다음 장에서 이 로그는 tracing과 eval의 재료가 된다.
흔한 실수와 오류 분석
첫 번째 실수는 프롬프트만으로 안전을 보장하려는 것이다. "삭제하지 마", "외부 전송하지 마"라고 적어도 도구 권한이 열려 있으면 사고가 날 수 있다. 정책 엔진과 권한 시스템으로 막아야 한다.
두 번째 실수는 모든 도구에 같은 승인 정책을 적용하는 것이다. 조회 도구까지 매번 승인하면 사용자는 우회 경로를 찾는다. 반대로 삭제 도구를 자동 실행하면 작은 오류가 큰 사고가 된다. 도구별 위험도를 나눠야 한다.
세 번째 실수는 승인 메시지가 부실한 것이다. "이 작업을 승인하시겠습니까?"만 보여주면 승인자는 판단할 수 없다. 무엇을, 누구에게, 어떤 데이터로, 어떤 결과를 만들지 보여줘야 한다.
네 번째 실수는 에이전트 권한이 너무 넓은 것이다. 특히 read/write가 섞인 계정, 만료되지 않는 API 키, 여러 에이전트가 공유하는 토큰은 위험하다.
다섯 번째 실수는 감사 로그를 나중에 붙이려는 것이다. 로그는 운영 후에 덧붙이는 장식이 아니다. 승인형 에이전트의 핵심 데이터 구조다. Microsoft Agent Framework의 middleware처럼 실행, 함수 호출, 모델 호출의 중간 지점을 가로채는 구조를 두면 보안 검증과 로깅을 핵심 로직과 분리해 구현할 수 있다.5
요약
에이전트 안전성은 모델의 선의에 맡길 수 없다. 운영 가능한 에이전트는 위험한 행동을 실행하기 전에 멈추고, 정책을 확인하고, 필요하면 사람에게 승인받고, 모든 과정을 기록한다.
이번 장의 핵심은 다음과 같다.
HITL은 단순 검수, 실행 전 승인, 예외 에스컬레이션, 사후 감사로 나눌 수 있다.
Guardrail은 입력, 프롬프트 인젝션, 도구 호출, 출력 형식, 금지 행동 차단 계층으로 설계한다.
최소 권한 원칙에 따라 에이전트별 계정, 도구별 scope, read/write 분리, 일회성 승인 토큰을 사용한다.
Tool Gateway는 정책, 승인, 실행, 감사를 모으는 중앙 통제 지점이다.
승인형 문서 에이전트에서는 외부 전송, 삭제, 공유 작업을 approval queue로 보내야 한다.
퀴즈
Human-in-the-loop을 모든 도구에 적용하면 어떤 문제가 생길 수 있는가?
실행 전 승인과 사후 감사의 차이는 무엇인가?
프롬프트 인젝션 방어를 시스템 프롬프트에만 의존하면 왜 위험한가?
조회 도구와 삭제 도구의 권한을 분리해야 하는 이유는 무엇인가?
승인 요청 메시지에 반드시 포함해야 할 정보 세 가지를 적어보라.
Tool Gateway를 두면 어떤 운영상 이점이 있는가?
체크리스트
도구를 조회, 생성, 수정, 삭제, 외부 전송으로 분류했다.
도구별 AUTO_APPROVE, REQUIRE_APPROVAL, DENY 정책을 정의했다.
외부 발송, 삭제, 권한 변경, 비용 발생 작업은 승인 대상으로 지정했다.
에이전트별 서비스 계정을 분리했다.
read 권한과 write 권한을 분리했다.
승인 요청에 도구 이름, 파라미터, 대상 범위, 위험 사유를 포함했다.
승인 거부 시 에이전트의 행동을 정의했다.
승인 로그와 실행 로그를 남긴다.
민감정보 마스킹 또는 차단 정책을 두었다.
에이전트가 executor에 직접 접근하지 못하게 했다.
다음 장 연결
이번 장에서는 에이전트가 위험한 행동을 하기 전에 멈추는 방법을 다뤘다. 하지만 운영에서는 "멈췄는가"만큼 "왜 그렇게 판단했는가"도 중요하다.
다음 장에서는 tracing과 evals를 다룬다. 에이전트가 어떤 입력을 받았고, 어떤 계획을 세웠고, 어떤 도구를 호출했고, 어떤 승인 과정을 거쳤고, 결과가 맞았는지 측정하는 방법을 배운다. 승인 로그와 guardrail 위반 기록은 다음 장에서 평가 데이터가 된다.
참고
1From prompts to privileges: Securing the age of AI agents
2Human-in-the-loop - Docs by LangChain
3Guardrails - Docs by LangChain
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.