목록으로
AI

사내 AI 에이전트 권한 설계: 읽기 전용 접근과 사람 승인

사내 AI 에이전트의 DB 조회는 PostgreSQL 읽기 전용 롤과 실행 전 훅으로 묶고, 쓰기는 Slack Block Kit 확인 카드를 사람이 누른 뒤 별도 실행 레인에서만 처리해요. IAM 정책, GitHub 머지 기록을 검사하는 배포 게이트까지 권한을 층으로 나눈 방식을 실제 훅 출력과 함께 소개해요.

2026-09-10

사내 AI 에이전트 권한 설계: 읽기 전용 접근과 사람 승인

사내 AI 에이전트 시리즈 2편. 1편 장기 기억과 온톨로지 · 3편 슬랙·웹·CLI · 4편 문서 공유

TL;DR

마인드로직의 사내 AI 에이전트 인포미는 에이전트 프레임워크 위에서 돌고, 운영 DB·AWS·GitHub·Slack에 손이 닿아요. 조회 경로의 PostgreSQL 롤은 pg_read_all_data + default_transaction_read_only로 묶어 두고, 쓰기는 Slack Block Kit 확인 카드를 사람이 누른 뒤 별도 실행 레인에서만 처리합니다. 프롬프트 규칙 위에 실행 전 훅, IAM 정책, GitHub 머지 기록을 검사하는 배포 게이트를 겹쳐 놓은 구조예요. 은행 창구로 치면 잔액 조회는 창구 직원 누구나 해 주지만 이체에는 고객 서명이 필요한 것과 같습니다.

업무를 맡기려면 프로덕션 데이터가 필요하다

슬랙에서 인포미를 부르면 테넌트 테이블에서 계약 만료일을 조회하고, 구글 시트 매출 원장을 대조하고, 버그를 고쳐 PR을 올려요. 정기 리포트를 만드는 systemd 타이머도 이 에이전트가 돌립니다. 계약이나 사용량 질문에 답하려면 RDS에 있는 실제 사용량·계약 테이블을 읽어야 하죠. 샘플 데이터만 든 데모 계정으로는 지금 업무 상태를 확인할 수 없어요.

읽기 전용 접근만으로도 조회와 분석은 충분히 됩니다. 반면 계정을 만들고 크레딧을 지급하고 코드를 바꾸는 일에는 다른 권한이 필요하죠. 그래서 에이전트에게 프로덕션 접근을 허용할지 한 번에 결정하기보다, 어떤 일을 읽기 롤로 처리하고 어떤 변경을 사람이 승인할지 나눴어요.

프롬프트, 훅, 계정 권한은 다른 층이다

처음부터 시스템 프롬프트에는 쓰기 SQL을 실행하지 말 것, 다른 사람의 데이터에 함부로 접근하지 말 것, 업무 자료를 공개 스토리지에 올리지 말 것 같은 규칙이 있었어요. 에이전트가 업무를 이해하고 행동을 고를 때 필요한 안내입니다.

다만 프롬프트는 계정 권한을 대신하지 못해요. 2026-08-21에 실측해 보니 프롬프트에 "쓰기 SQL 금지"가 적혀 있는 상태에서 회원 행을 지우는 문장이 MCP 도구를 그대로 통과했습니다. 규칙은 있었고 검사는 없었던 거죠. 그날 이후 세 층을 따로 세웠어요.

계정 권한. 조회에 쓰는 DB 계정은 모든 RDS 리더 엔드포인트에서 pg_read_all_data 롤과 default_transaction_read_only 설정만 가져요. 쓰기를 시도하면 PostgreSQL이 cannot execute ... in a read-only transaction으로 거절합니다. 인프라 조사에 쓰는 IAM 사용자도 EC2·RDS·Lambda·CloudWatch의 Describe/Get 계열과 S3 버킷 두 개로 좁혔어요. 봇이 무엇을 결정하든 자격증명이 허용하는 범위가 천장입니다.

실행 전 훅. 에이전트 프레임워크의 실행 전 훅(pre-tool hook)은 도구가 실행되기 직전에 호출 JSON을 받아 거부 결정을 돌려줄 수 있는 셸 스크립트예요. 쓰기 SQL 차단 훅은 MCP 조회 도구에 넘어가는 SQL과 셸에서 DB 클라이언트를 부르는 명령을 같은 규칙으로 검사하고, 스캔 쿼리 검사 훅은 대화 원문에 대한 ILIKE 전체 스캔 쿼리를 기간 조건 없이는 막습니다. 롤이 못 막는 종류의 위험, 즉 읽기이지만 운영 DB CPU를 태우는 쿼리를 여기서 잡아요.

실행 전 훅이 UPDATE 문과 history.text ILIKE 쿼리를 거부하는 실제 터미널 출력

쓰기 SQL 차단 훅과 스캔 쿼리 검사 훅의 실제 출력. 두 훅 모두 종료 코드 2와 deny 결정을 돌려주고, 도구 호출은 실행되지 않아요.

프롬프트. 남은 것이 프롬프트의 역할이에요. 왜 막혔는지, 대신 무엇을 해야 하는지(SQL을 코드 블록으로 사람에게 넘기기)를 설명하는 층입니다. 훅이 돌려주는 안내 메시지도 같은 설명을 담아서, 거부당한 에이전트가 다음 행동을 고를 수 있게 했어요.

읽기 레인, 쓰기 레인, 코드 변경 게이트를 나눈 권한 구조도

세 레인의 구조. 읽기는 훅과 읽기 전용 롤을 지나 바로 조회하고, 쓰기는 Block Kit 카드와 승인자를 거쳐 별도 자격증명으로 실행하고, 코드는 GitHub 머지 기록을 게이트가 확인합니다.

읽기 전용 DB와 승인받는 쓰기 레인

인포미는 제품 DB 12개를 MCP 서버로 조회해요. 각 DB마다 조회 도구가 따로 있어서, 어떤 도구를 불렀는지가 곧 어느 DB를 읽었는지의 기록이 됩니다. 이 경로의 자격증명은 전부 읽기 전용이고, 봇에게 임의의 쓰기 SQL을 실행할 권한을 주는 방식으로 운영 작업을 열지는 않았어요.

쓰기가 필요한 일은 두 갈래로 다뤄요. 특정 데이터를 바로잡는 일회성 작업은 에이전트가 갱신 문장을 코드 블록으로 준비하고 사람이 검토해 실행합니다. 계정 일괄 생성, 크레딧 지급, 테넌트 생성처럼 입력과 결과의 형태가 정해진 반복 작업은 계획 도구(plan 도구)로 보내요. 크레딧 일괄 지급, 계정 일괄 생성, 테넌트 생성 도구는 요청을 검증해 실행 계획만 만들고, 실제 변경은 다음 절의 확인 카드가 눌린 뒤 서버 측 operator API가 처리합니다. 봇의 읽기 롤은 그 어느 단계에도 쓰이지 않아요.

읽기 작업에서도 서비스에 부담을 주지 않도록 조회 범위를 살펴요. 대화 원문처럼 큰 테이블은 기관 조건과 7일 이내 기간 조건이 없으면 훅이 거절하고, MCP 서버 쪽에는 15초 읽기 타임아웃이 걸려 있습니다. 데이터를 바꾸지 않는 쿼리라도 운영 DB의 자원을 쓰기 때문이에요. 인프라 조사도 CloudWatch 지표와 로그, Describe 호출로 원인을 정리하는 데까지 하고, 설정 변경은 사람이 판단합니다.

확인 카드에서 무엇을 검토하나

크레딧 일괄 지급을 예로 들어 볼게요. 사업팀에서 "이 명단에 보상 크레딧 500씩 넣어 주세요"라고 요청하면, 인포미는 첨부된 명단을 읽어 회원 테이블과 대조하고, 지급 대상 수·1인당 quota·유효기간·고객 화면에 표시될 크레딧 이름·영향 범위를 담은 실행 계획을 Slack Block Kit 카드로 올려요. 카드에는 실행과 취소 버튼이 있고, 실행 버튼의 인터랙션 이벤트는 승인자 allowlist에 있는 사람이 눌렀을 때만 실행 레인으로 넘어갑니다.

크레딧 일괄 지급 확인 카드. 테넌트, 대상 수, quota, 유효기간, 영향 범위와 실행·취소 버튼

확인 카드에 담기는 항목. 실제 카드 구조를 그대로 두고 기관명과 이름만 가렸어요.

담당자는 대상을 제대로 골랐는지, 수량이 요청과 맞는지 확인해요. 실행이 눌리면 승인자와 시각이 감사 로그에 남고, 변경은 서버 측 키를 가진 operator API가 처리합니다. 요청자가 곧 승인자가 되지는 않고, 요청을 해석해 계획을 만드는 에이전트와 변경을 승인하는 사람이 이렇게 나뉘어요.

확인 카드의 목적은 바뀔 내용을 실행 전에 보는 것이에요. 담당자가 SQL을 직접 쓰지 않아도 무엇이 바뀌는지 알 수 있어야 하니까요. 카드의 사유 필드가 감사 메모가 아니라 고객 화면에 뜨는 크레딧 이름이라는 것도 카드를 보다가 알게 된 사실입니다.

권한은 작업 단위로 넓혔다

처음에는 읽기 중심으로 시작했어요. 무엇을 자주 조회하고 어디서 사람이 후속 작업을 하는지 보면서 쓰기가 필요한 업무를 골랐어요. 그다음 계정 생성이나 크레딧 지급처럼 형태가 정해진 동작을 계획 도구 하나씩으로 열었습니다. 2026-09 기준 열린 도구는 13개예요.

데이터베이스 전체에 넓은 쓰기 권한을 주면 맡기려던 업무와 관계없는 변경도 가능해져요. 저희는 입력과 변경 범위가 정해진 작업을 만들고, 실행할 내용을 카드로 보여준 뒤 담당자의 승인을 받는 쪽을 택했어요.

작업을 열어준 뒤에도 요청을 해석하는 절차와 접근 범위를 나눠 살펴요. 반복해서 필요한 절차는 스킬 문서로 정리하고, 허용 범위가 넓은 동작은 권한을 다시 좁힙니다. 새 MCP 서버를 붙일 때도 그 서버가 읽거나 바꿀 수 있는 대상을 함께 검토해요. 노션 MCP처럼 쓰기가 가능한 서버는 프롬프트 규칙과 사람 확인을 같이 붙였습니다.

코드 변경에는 머지 기록이 승인이다

인포미는 버그를 조사하고 코드를 수정해 PR을 올려요. 여기서 변경안을 만드는 권한과 프로덕션에 반영하는 권한을 구별합니다. 봇은 자기 홈의 클론에서 브랜치를 만들고 git commit --author로 요청자를 남긴 뒤 gh pr create까지만 해요.

봇의 코드베이스는 특별한 사정이 하나 있어요. 리포지터리의 체크아웃 자체가 프로덕션이고, 스케줄 작업이 그 워킹트리의 스크립트를 .env가 열린 계정으로 실행합니다. 그래서 GitHub의 머지 버튼이 아니라 박스의 동기화 스크립트가 권한 경계예요. 5분마다 도는 이 타이머는 origin/main의 새 커밋이 보호 경로(소스·스크립트·훅·스킬·CI 설정)를 건드리면 GitHub API로 그 커밋이 속한 PR의 머지한 사람을 조회해, 승인된 사람(현재 한 명)이 머지한 경우에만 배포합니다. 봇이 스스로 머지하면 그 커밋과 뒤따르는 커밋이 전부 대기 상태가 되고 운영 채널에 알림이 가요.

배포 게이트가 머지 기록을 확인하고 보호 경로 커밋을 대기시키는 흐름

배포 게이트의 판정 흐름. 스킬 파일도 보호 대상인데, 이후 모든 세션이 따르는 지시문이라 코드로 취급하기 때문이에요.

이 원칙은 에이전트 자신의 권한을 바꾸는 설정에도 적용해요. 훅 스크립트, 스킬, 시스템 프롬프트는 전부 보호 경로라서, 봇이 자기 작업에 필요하다고 판단한 권한 확대도 사람의 머지를 기다립니다. 게이트 스크립트 자체도 보호 경로라, 게이트를 약하게 만드는 커밋은 아직 돌고 있는 이전 게이트가 검사해요.

공유할 파일은 누가 열 수 있을까?

보고서와 대시보드, 분석 결과, 견적서 초안은 만들어진 뒤 어디에 놓이는지도 중요해요. 조회할 권한이 있는 사람이 요청했더라도 결과 파일의 공유 범위가 넓으면 다른 사람이 그 내용을 보게 되죠.

사내 공유 문서는 Cloudflare Access 뒤의 S3 정적 호스팅에 두는 것이 기본이에요. 회사 Google Workspace 계정으로 로그인해야 열리고, 공개가 꼭 필요한 파일만 별도 버킷의 public/ 접두사로 갑니다. 이 구분도 훅이 지켜요. 공개 읽기가 막힌 접두사로 업로드하려 하면 공개 버킷 차단 훅이 업로드 자체를 거부합니다. 개인정보가 든 파일은 어느 티어에도 올리지 않고 Slack 파일 업로드로 받을 사람에게만 붙여요. 자세한 구조는 4편 문서 공유에 있습니다.

사람이 승인해야 끝나는 일

고객이나 외부 기관에 보내는 메일은 인포미가 초안을 준비하고 담당자가 발송해요. 계약이나 크레딧처럼 실제 변경이 필요한 작업은 계획 카드를 거치고, 회사 직인이 필요한 문서도 날인 없는 초안까지만 준비해서 날인은 담당자가 맡아요.

에이전트가 어떤 자료를 보고 무엇을 준비했는지 사람이 확인할 수 있어야 마지막 판단이 가능합니다. 다른 구성원의 대화나 파일이 필요한 경우에도 업무상 필요하다는 설명만으로 접근을 넓히지 않고, 요청자의 권한과 해당 자료의 공유 범위를 확인해요. 봇의 원장 DB에서도 대화 본문은 채널 단위로만 읽을 수 있고, DM 내용은 읽기 롤에서 빠져 있습니다.

인포미가 참고하는 회사 정보에는 제품과 팀, 계약과 담당자의 관계가 정리돼 있어요. 이 관계 지도가 1편에서 다룬 온톨로지인데, 요청의 맥락과 담당자를 찾는 데는 쓰지만 데이터 접근 권한과는 별개로 둡니다. 회사 구조를 아는 것과 그 안의 데이터를 바꿀 수 있는 것은 다른 층의 일이니까요.

사내 AI 에이전트 권한 설계에서 저희가 나눈 것은 읽기 전용 접근과 승인받는 변경 작업이에요. 조회에는 읽기 전용 PostgreSQL 롤과 Describe 전용 IAM을 쓰고, 쓰기는 계획 도구와 Block Kit 카드, operator API로 이어지는 별도 레인에서 사람이 검토합니다. 프롬프트는 이 구분을 설명하고, 실행 전 훅은 실행 직전에 검사하고, 배포 게이트는 머지 기록을 확인해요. 잔액은 누구나 조회하되 이체에는 서명을 받는 창구처럼, 인포미가 준비한 결과를 보고 담당자가 변경 여부를 판단하게 하는 것이 저희가 업무를 맡기는 방식이에요.