에이전트가 도구를 구매했을 때, 누가 당신의 데이터를 얻게 되는가?
요약
에이전트가 외부 도구를 사용할 때, 데이터 유출 위험을 최소화하는 것이 중요합니다. 본문은 읽기 전용(read-only) 호출이라도 내부 정보가 외부 제공업체에게 노출될 수 있음을 지적하며, 특정 호출이 무엇을 공개할지 제어하는 게이트 메커니즘의 필요성을 강조합니다.
핵심 포인트
- 에이전트 도구 사용 시 데이터 유출 위험을 경계해야 합니다.
- 읽기 전용(read-only) 호출이라도 내부 정보가 외부로 노출될 수 있습니다.
- 데이터 공개 범위는 API 키나 모델 호출과 별개로 제어되어야 합니다.
Composio Instant는 2026년 10월 8일에 출시되었습니다. 새로 사용할 수 있는 도구 앞에 제가 배치할 애플리케이션 경계입니다.
당신의 에이전트는 공급업체를 조사해야 합니다. 그리고 하나의 도구를 찾습니다. 이 도구는 아주 저렴합니다. 에이전트가 비용을 지불하고 검색을 실행한 후, 유용한 답변을 가지고 돌아옵니다.
멋지네요.
하지만 그 검색에는 당신의 내부 갱신 노트도 포함되어 있었습니다. 당신은 공급업체 조사를 승인했습니다. 그런데 어떻게 그것이 외부 제공업체에게 당신의 협상 전략을 브리핑할 수 있는 승인으로 변질되었을까요?
그 도구는 읽기 전용(read-only)이었습니다. 그럼에도 불구하고 당신의 데이터는 건물 밖으로 유출되었습니다.
2026년 10월 8일, Composio Instant에 따르면, 별도의 제공업체 가입 없이 100개 이상의 지원되는 유료 도구에 접근할 수 있습니다. 이 발표에는 리서치, 정보 보강(enrichment), 전사(transcription), 미디어 생성 등이 포함됩니다. 이것은 오늘 발표된 것이 아니라 10월 8일 출시 내용입니다.
설정 마찰을 제거하는 것은 유용합니다. 하지만 이는 한 엔지니어링 질문을 미루기 어렵게 만듭니다:
이 특정 호출(call)이 무엇을 공개하도록 허용되는가?
저는 의도적으로 좁은 워크플로우에 대해 이 질문에 답하는 작은 TypeScript 게이트를 만들었습니다. API 키도, 모델 호출도, 돈도 필요 없습니다. 스물다섯 가지 결정론적(deterministic) 검사만 거칩니다.

읽기 전용 호출이라도 데이터를 내보낼 수 있다
검색 도구는 정보를 공개하기 위해 send_email 권한을 가질 필요가 없습니다. 그 입력은 제공업체에게 보내는 메시지입니다.
다음 두 요청을 생각해 보세요:
Research Example Robotics at example.com.
Research Example Robotics. Our private renewal notes say
...
작업 이름(operation name)은 동일할 수 있습니다. 하지만 데이터 경계는 다릅니다.
위의 회사와 협상 세부 정보는 가상의 것입니다. 핵심 차이점은 이것입니다: 도구가 원격 시스템에 미치는 영향과 당신의 정보에 미치는 영향은 별개의 질문입니다.

예산 통제(budget control)는 해당 호출을 감당할 수 있는지 여부를 묻고, 도구 허용 목록(tool allowlist)은 해당 작업이 사용 가능한지 여부를 묻습니다. 어느 쪽도 이 수신자가 이 작업을 위해 이러한 필드를 받을 수 있는지 여부는 확립하지 못합니다.
출시가 변경하는 것과 그렇지 않은 것
Composio의 현재 Instant 문서는 제공자 계정에서 실행되는 지원되는 작업(supported actions)을 설명하며, 이는 조직의 잔액으로 청구됩니다. 사용자는 여전히 개인적이거나 계정별 액세스를 위해 자체 연결이 필요합니다. 문서는 입력값이 제공자에게 도달한다고 명시하며, Instant가 데이터 보존 제로를 의미하지는 않습니다.
이는 Composio가 어떤 것을 유출했다는 주장이 아닙니다. 이는 경계를 의도적으로 구축해야 하는 이유입니다.
10월 10일 기준으로 확인했을 때, 해당 문서는 Instant 실험적(experimental)이라고 표시되어 있습니다. 또한 세션(Session)의 도구 사용 가능 여부를 Instant 계정 사용과 구분합니다. 프로젝트가 Instant를 활성화하면, 세션의 instant 설정을 생략하는 것이 적격한 사용을 허용하며, instant: false는 해당 세션에 대한 Instant 비용 지불을 방지합니다. 연결된 계정은 계속 사용할 수 있습니다.
이것들은 제품 제어(product controls)입니다. 아래의 게이트는 별도의 애플리케이션 정책입니다. 이는 Composio SDK를 구성하거나 테스트하지 않으며, 그 가상의 도구 ID는 Composio 슬러그가 아닙니다.
모델이 재작성하는 것이 아니라 선택하도록 하라
유용한 설계 선택은 이 작은 제안에서 원시(raw) 인수를 제외하는 것입니다:
const proposal = {
tool: 'companySearch',
recordIds: ['vendor'],
...
모델은 알려진 도구, 레코드 ID, 필드 이름을 제안할 수 있습니다. 애플리케이션이 세 가지 신뢰할 수 있는 입력값을 제공합니다.
- 인증된 작업 범위: 테넌트(tenant), 허용되는 도구, 수신자 및 필드.
- 검토된 도구 레지스트리: 수신자, 자격 증명 출처 및 승인된 데이터 클래스.
- 기록 저장소: 값, 테넌트 소유권 및 필드 분류.
모델은 비공개 단락에 label: 'public'을 붙일 수 없습니다. 또한 자유 형식의 query 인수를 추가할 수 없습니다. 파서는 키를 조용히 무시하는 대신 추가 키를 거부합니다.
이는 의도적으로 제한적입니다. 만약 모델이 어떤 단락이든 제한 없는 검색 문자열로 복사할 수 있다면, 깔끔한 필드 레이블은 더 이상 무엇이 외부로 나갈지 제어하지 못하게 됩니다.
fixture의 companySearch 경로는 공개 필드를 허용합니다. 이의 crmLookup 경로는 공개 및 내부 필드를 허용합니다. 해당 작업은 두 수신자를 명시적으로 허용합니다. 이러한 CRM 권한은 연결된 계정이 안전하다는 보편적인 규칙이 아니라 예시 정책 결정입니다.
제한된 필드는 두 경로 모두에서 거부됩니다. 요청된 필드가 공개 필드라 할지라도, 다른 테넌트의 기록은 투영(projection) 전에 거부됩니다. '공개' 분류가 소유권을 지우지는 않습니다.
페이로드를 반환하기 전에 모든 필드를 확인하세요
다음은 gate.ts에서 가져온 핵심 루프입니다:
const rows: Record<string, string>[] = [];
for (const id of recordIds) {
if (!own(records, id)) return deny('unknown-record');
...
이 루프가 실행되기 전에, 함수는 제안된 구조를 검증하고, 알 수 없는 도구를 거부하며, 작업의 도구 및 수신자 범위를 확인하고, 필드 범위도 확인합니다. 식별자 목록은 10개 항목 제한이 있으며 중복을 포함할 수 없습니다. 레지스트리 조회는 자체 속성(own properties)을 요구하므로 toString과 같은 이름은 객체 프로토타입을 통해 해결될 수 없습니다.
함수는 전체 배치(batch)가 통과된 후에만 나가는 프로젝션(outgoing projection)을 반환합니다. 공개 기록(public record) 다음에 다른 테넌트(tenant)의 기록이 오면, 첫 번째 페이로드(payload)의 절반이 아닌 거부(denial)를 반환합니다.
허용 결정(allow decision)에는 검토된 수신자(reviewed recipient)와 자격 증명 출처(credential source)가 포함됩니다. 이 예시는 이를 신뢰할 등록소 사실(trusted registry facts)로 간주합니다. 실제 어댑터(adapter)는 전송 시간(dispatch time)에 실제 계정 및 목적지를 해석하고 강제해야 합니다. 친근한 도구 이름이 그 증거가 될 수는 없습니다.
로컬에서 실행하기
검토 번들(review bundle)에는 gate.ts, fixtures.ts, test.ts, 그리고 package.json이 포함되어 있습니다. 이 파일들을 함께 저장하세요. Node.js 22.20.0 이상 버전 사용 시:
git clone https://github.com/bobbyhalljr/agent-data-release-gate.git
cd agent-data-release-gate
npm test
설치해야 할 패키지 종속성(package dependencies)은 없습니다. 이 명령어는 node --experimental-strip-types test.ts를 실행합니다. Node의 TypeScript 문서에서 지원되는 구문을 설명합니다. 타입 스트리핑(Type stripping)은 이러한 파일을 실행할 뿐, 타입 검사(type-check)를 수행하지 않습니다.
테스트는 각 명명된 확인 사항을 출력한 다음, 정확히 다음과 같은 줄들을 출력합니다:
25/25 checks passed
publicSearch: ALLOW recipient=research-provider credential=instant fields=company,domain
privateSearch: DENY data-class-not-approved
...
이것들은 관찰된 Composio 응답(observed Composio responses)이 아니라 로컬 정책 결정입니다. 테스트는 비공개 입력(private inputs), 제한된 필드(restricted fields), 작업 범위(task scope), 수신자, 혼합 테넌트 배치(mixed-tenant batches), 알 수 없는 기록(unknown records), 추가 인자(extra arguments), 중복 항목(duplicates), 그리고 잘못 구성된 제안(malformed proposals)을 다룹니다. 또한 선택되지 않은 메모(notes)와 합성 토큰(synthetic token)이 누락되었는지 확인하기 위해 허용된 프로젝션(allowed projection)도 검사합니다.
공개 소스: bobbyhalljr/agent-data-release-gate.
이 작은 게이트가 증명할 수 없는 것
이는 자연어에서 비밀 정보를 검사하지 않습니다. 잘못 레이블링된 공개 필드라도 여전히 사적인 정보를 포함할 수 있습니다. 또한 데이터를 분류하거나, 테넌트를 인증하거나, 제공업체의 보존 기간을 확인하거나, 실제 자격 증명을 해결하거나, 네트워크 트래픽을 가로채지 않습니다.
임의 모델이 작성한 쿼리, 파생된 요약, 첨부 파일, URL 또는 도구 결과가 다른 호출에 직접 공급되는 것도 지원하지 않습니다. 그러한 것들은 자체적인 출처(provenance)와 공개 규칙이 필요합니다. 내부 메모의 요약본이라고 해서 더 짧다고 해서 공공이 되는 것은 아닙니다.
신뢰할 수 있는 작업, 레지스트리 및 기록 저장소는 애플리케이션 상태에서 와야 합니다. 절대 검사하고 있는 것과 같은 모델 출력으로부터 이들을 채우지 마십시오. 이 예시는 그러한 구조가 유효하다고 가정하며, 런타임에 신뢰할 수 없는 제안을 검증합니다.
운영 환경(production)에서는 도구를 실행할 수 있는 유일한 디스패처에 검사를 배치하십시오. 허용된 투영(projection)으로부터 아웃고잉 인자들을 구성하고 정확히 그 인자들을 전송하십시오. 디스패치 전에 오래된 정책이나 계정 매핑을 다시 확인하십시오. 감사 로그에 민감한 값을 복사하지 않고 식별자, 정책 버전, 해결된 경로, 결정 및 실행 증거를 기록하십시오.
마지막 단계가 중요합니다. ALLOW라고 말하는 함수는 어떤 계정이 도구를 실행했는지, 어댑터가 어떤 데이터를 보냈는지, 또는 외부 호출이 완료되었는지를 증명하지 못합니다.
저는 실제 작업을 수행하는 AI 직원들을 중심으로 Roster를 구축하고 있습니다. 도구들은 사용하기 더 쉬워져야 합니다. 정보를 공개할 수 있는 권한은 애플리케이션의 결정으로 남아 있어야 합니다.
새로운 도구는 새로운 역량입니다. 고객의 사적인 메모가 온보딩 비용이 되어서는 안 됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
