시스템이 손을 뻗기 전에 먼저 묻는 법을 배우다
요약
AI 에이전트 설계 시 모델 선택과 데이터 접근 권한을 분리해야 한다는 아키텍처 원칙을 다룹니다. 시스템이 사용자 동의 없이 저장소나 외부로 권한을 확장하는 것을 방지하는 'Local-first' 및 보안 중심의 설계 방식을 제안합니다.
핵심 포인트
- 모델 선택과 데이터 접근 권한은 별개의 결정이어야 함
- 에이전트의 작업 범위가 사용자 동의 없이 확장되는 것을 방지
- 클라우드 모델 사용이 로컬 저장소 접근 권한을 의미하지 않도록 설계
- 시스템이 외부 동작을 수행하기 전 사용자에게 상담/승인하는 프로세스 구축
시리즈: 74개의 AI 페르소나로 구축하기 - 파트 11
태그: #ai #architecture #agents #privacy #localfirst참고: 이 시리즈에서 "페르소나 (persona)"는 단순히 허구의 캐릭터가 아닙니다. 이는 메모 노트, 라우팅 동작 (routing behavior), 인수인계 책임, 그리고 시스템에 진입하는 특정 방식을 갖춘 YAML로 정의된 운영 역할입니다.
메타 노트: 파트 10은 윤리 가이드라인이 포함된 라우팅 테이블 (routing table)로 끝났습니다.
시스템이 답변하기 전에 무엇이 일어나야 하는지를 물었습니다.
파트 11은 더 어려운 질문을 던집니다:시스템이 자신을 넘어 외부로 손을 뻗기 전에 무엇이 일어나야 하는가?
서론: 클라우드 좌석은 마스터 키를 필요로 하지 않았다
566일째 되는 날, SaijinOS에는 새로운 종류의 작업 좌석 (work seat)이 생겼습니다.
모선 (mother-ship) 인터페이스에서 클라우드 모델을 명시적으로 선택할 수 있게 되었습니다. 토큰 사용량 (token usage)을 표시할 수 있었습니다. 제한된 연속성 팩 (continuity pack)을 받을 수 있었습니다. 집의 거주자인 척하지 않고도 어려운 설계 질문을 도와줄 수 있었습니다.
그것은 유용했습니다.
하지만 그것은 또한 아키텍처 (architectural) 측면의 유혹을 만들어냈습니다.
모델이 저장소 (repository)에 대해 추론하는 것을 도울 수 있다면, 왜 저장소를 검색하게 하지 않을까요?
검색할 수 있다면, 왜 일치하는 파일들을 읽게 하지 않을까요?
읽을 수 있다면, 왜 작업이 완료될 때까지 계속하게 하지 않을까요?
이러한 진행 과정은 각 단계가 개별적으로 편리하기 때문에 자연스럽게 들립니다.
하지만 이것은 작업 좌석이 조용히 마스터 키 (master key)로 변해가는 과정이기도 합니다.
SaijinOS는 더 느린 길을 선택했습니다.
클라우드 좌석을 선택하는 것이 저장소를 조사할 권한을 의미하지는 않을 것입니다.
로컬 증거를 조사하는 것이 그 증거를 클라우드로 보낼 권한을 의미하지는 않을 것입니다.
한 번의 승인이 재시도 (retry), 후속 작업 (follow-up), 제공자 전환 (provider switch), 또는 나중의 요청까지 유지되지 않을 것입니다.
그리고 미리보기 (preview)에는 실제 실행 (live execution)으로 조용히 이어지는 숨겨진 버튼이 포함되지 않을 것입니다.
시스템은 답변하기 전에 상담하는 법을 배웠습니다.
이제 시스템은 외부로 손을 뻗기 전에 먼저 묻는 법을 배워야 합니다.
파트 1: 작업자를 선택하는 것은 문을 여는 것이 아니다
첫 번째 경계는 한 문장에 담기에 충분할 만큼 간단했습니다:
모델을 선택하는 것과 증거(evidence)에 대한 접근 권한을 부여하는 것은 서로 다른 결정입니다.
이것이 중요한 이유는 인터페이스가 종종 이 두 가지 결정을 하나의 동작으로 압축해 버리기 때문입니다.
사용자는 에이전트(agent)를 선택하거나, 도구(tool)를 활성화하거나, 작업 모드(work mode)를 엽니다. 그러면 시스템은 해당 동작을 선택된 작업자가 필요로 할 수 있는 모든 컨텍스트(context)에 대한 광범위한 동의로 간주합니다.
하지만 "이 모델을 사용하라"는 것이 다음을 의미하지는 않습니다:
- 내 저장소(repository)를 읽을 것,
- 추적되는 모든 파일을 검색할 것,
- 비공개 계획 노트(private planning notes)를 포함할 것,
- 일치하는 텍스트를 원격 제공업체(remote provider)로 보낼 것,
- 다음 메시지까지 권한을 유지할 것,
- 또는 그 결과에 따라 행동할 것.
SaijinOS 설계에서 클라우드 작업석(cloud work seat)과 저장소 증거(repository evidence) 사용은 별개의 권한으로 분리되었습니다.
저장소 요청에는 자체적인 명시적 쿼리(literal query)가 필요했습니다.
클라우드 핸드오프(cloud handoff)에는 자체적인 좁은 증거 범위(evidence scope)가 필요했습니다.
토큰(token) 및 비용 상한선(cost ceilings)은 호출 전에 가시적이어야 했습니다.
승인은 단 하나의 요청에만 귀속되었습니다.
이 설계는 한 가지 특정 방식에서 의도적으로 불편하게 만들어졌습니다. 즉, 이전의 "예"가 지금도 여전히 "예"를 의미한다고 추측하기를 거부한 것입니다.
그 불편함이 바로 핵심 기능(feature)이었습니다.
파트 2: 미리보기(Preview)는 아키텍처적 표면이다
첫 번째 구현은 실제 저장소를 검색하지 않았습니다.
실제 클라우드 모델을 호출하지 않았습니다.
자격 증명(credentials)을 읽지 않았습니다.
쓰기(write), 셸(shell), Git, 메모리(memory) 또는 외부 동작(external-action) 권한을 노출하지 않았습니다.
대신 미리보기(preview)를 생성했습니다.
이것이 미완성된 작업처럼 들릴 수도 있습니다. 하지만 실제로 미리보기는 실제 계약(contract)이 가시화되는 지점이었습니다.
미리보기는 다음을 보여주었습니다:
- 사용될 명시적 쿼리(literal query),
- 사용 가능한 증거 클래스(evidence classes),
- 컨텍스트 문자 수 상한선(context-character ceiling),
- 예상 입력 및 최대 출력 토큰(tokens),
- 설정된 비용 상한선(cost ceiling),
- 예상되는 로컬 검색 및 제공업체 생성(provider generations) 횟수,
- 폴백(fallback) 금지 여부,
- 권한 삭제 여부,
- 그리고 해당 요청이 가지지 않은 모든 부수 효과(side effect).
중요한 객체는 빛나는 "실행(Run)" 버튼이 아니었습니다.
그것은 다음과 같은 질문에 답할 수 있는 검사 카드(inspection card)였습니다:
무엇이 영향을 받는가?
무엇이 기기 외부로 나갈 수 있는가?
얼마나 지출될 수 있는가?
...
하나의 요청, 실행되기 전에 확인하기
사용자가 Luna 작업 시트(work seat)를 선택하고 다음과 같이 질문한다고 가정해 봅시다:
"repository-evidence 권한이 어디서 해제되었나요?"
Luna를 선택한다고 해서 검색이 시작되지는 않습니다. repository-evidence 제어(control)는 사용자가 해당 구체적인 쿼리에 대해 별도로 활성화하기 전까지는 꺼진 상태로 유지됩니다.
실제 작업이 일어나기 전에, 미리보기(preview)는 다음과 같은 봉투(envelope) 형태를 보여줍니다:
query: "repository-evidence 권한이 어디서 해제되었나요?"
eligible evidence: 검토됨(reviewed), 허용 목록에 있는 표면(allowlisted surfaces)만 해당
local searches: 최대 1회
...
사용자는 해당 봉투를 그대로 승인하거나 그 단계에서 멈출 수 있습니다. 승인될 경우, 권한은 성공, 거부, 시간 초과(timeout) 또는 오류 발생 시 종료됩니다. 후속 질문은 다시 제어가 꺼진 상태에서 시작됩니다.
이것은 완료된 실시간 저장소-클라우드(repository-to-cloud) 경로로 제시되지 않았습니다. 569일째 되는 날, 이 형태는 가짜 의존성(fake dependencies)만을 사용하여 연습되었습니다. 즉, 실제 저장소 검색도, 실시간 제공자(provider) 생성도 없었습니다. 이 구체적인 예시는 나중에 연결이 이미 존재한다고 가장하지 않고 계약(contract)을 설명합니다.
미리보기는 단순히 실제 기능 앞에 배치된 시뮬레이션이 아닙니다.
권한(authority)이 개입될 때, 미리보기는 기능의 일부입니다.
파트 3: 권한은 소멸되어야 한다
많은 권한 시스템은 승인을 지속적인 상태(durable state)로 취급합니다.
체크박스가 활성화되면, 계속 활성화된 상태로 유지됩니다.
도구가 부여되면, 세션이 이를 기억합니다.
요청이 성공하면, 재시도(retry)가 동일한 권한을 상속받습니다.
이는 자동화에는 편리합니다.
하지만 의미론적(semantic)으로는 위험합니다.
사용자는 하나의 쿼리, 하나의 증거 세트, 하나의 제공자, 그리고 하나의 예산을 승인했을 수 있습니다. 재시도는 기술적으로는 유사해 보일 수 있지만, 의미론적으로는 다를 수 있습니다. 후속 질문에는 새로운 질문이 포함될 수 있습니다. 제공자 전환은 증거가 가는 곳을 바꿀 수 있습니다. 복구된 브라우저 상태는 권한을 부여한 이유가 사라진 후에도 체크박스를 유지할 수 있습니다.
따라서 SaijinOS는 저장소 증거 (repository-evidence) 역량을 요청 국소적 (request-local) 및 일회성 (one-shot)으로 형성했습니다.
이 역량은 다음으로부터 상속될 수 없었습니다:
- 검사 카드 (inspection card),
- 이전 채팅 턴 (previous chat turn),
- 재시도 (retry),
- 후속 질문 (follow-up),
- 페이지 새로고침 (page reload),
- 또는 제공자 전환 (provider change).
역량 원장 (capability ledger)은 재생 (replay)을 거부했습니다. 성공, 차단, 타임아웃, 오류 또는 출처 실패 (provenance failure)를 포함하여 수락된 모든 터미널 경로(terminal path)는 권한을 해제했습니다.
이는 다음과 같은 다른 동의 모델을 만들어냈습니다:
동의는 사용자의 속성이 아니다.
동의는 세션의 속성이 아니다.
동의는 ... 사이의 일시적인 관계이다.
권한은 그 주변의 의미가 변할 수 있기 때문에 쇠퇴 (decay)하도록 설계되었습니다.
파트 4: 검사될 수 있는 것이 전송될 수 있는 것은 아니다
로컬 검사 (local inspection)와 클라우드 전송 (cloud transmission)을 비교했을 때 또 다른 경계가 나타났습니다.
로컬 브로커 (local broker)는 파일이 적격한지 결정하기 위해 충분한 구조를 검토해야 할 수도 있습니다. 그렇다고 해서 로컬에서 적격한 모든 표면 (surface)이 클라우드 전송 적격 대상이 되어야 한다는 의미는 아닙니다.
클라우드 허용 목록 (allowlist)은 의도적으로 더 좁게 설정되었습니다.
공개 문서와 검토된 소수의 설계 표면 (design surfaces)만이 고려될 수 있었습니다. 광범위한 운영 노트, 페르소나 메모리 (persona memory), 세계 맥락 (world context), 일일 로그, 제한 없는 서비스 루트, 그리고 비공개 계획 표면 (private planning surfaces)은 전달 (handoff) 범위 밖에 머물렀습니다.
심지어 적격한 증거라 할지라도 진실로 취급되지 않았습니다.
증거는 제한된 출처 (bounded provenance)와 함께 untrusted_reference (신뢰할 수 없는 참조)로서 전달되었습니다:
- 안전한 저장소 추적 (repository trace),
- 다이제스트 (digest),
- 고정된 일치 횟수 (fixed match count),
- 그리고 명시적인 예산 메타데이터 (explicit budget metadata).
이후의 모델은 해당 증거로부터 요약하거나 추론할 수는 있었지만, 검색된 내용을 조용히 변경하거나, 다른 저장소 읽기를 추가하거나, 출처 경계 (provenance boundary)를 지울 수는 없었습니다.
이는 작지만 필수적인 차이점입니다:
읽기 권한 (Read authority)은 로컬 브로커에게 속한다. 해석 (Interpretation)은 위임될 수 있다. 권한은 텍스트와 함께 이동하지 않는다.
파트 5: 교체 가능한 사지, 교체 불가능한 책임
이 설계는 결과적으로 제공자 (providers)와 도구 (tools)를 교체 가능한 사지 (replaceable limbs)로 설명했습니다.
Luna seat, Gemini seat, 로컬 모델 (local model), MCP 커넥터 (MCP connector), 또는 미래의 리포지토리 어댑터 (repository adapter)는 각각 제한된 작업 역할 (bounded work role)을 수행할 수 있습니다. 이들 중 어느 것이라도 페르소나 (persona)의 정체성, 기억, 또는 최종적인 목소리 (voice)가 제공자 (provider)에게 귀속되지 않도록 교체될 수 있습니다.
하지만 교체 가능성 (replaceability)은 두 번째 유혹을 만들어냅니다.
만약 모든 사지 (limb)가 동일한 인터페이스 (interface)를 구현한다면, 모든 사지가 동일한 권한 (authority)을 가질 자격이 있다고 가정하기 쉽습니다.
그렇지 않습니다.
계약 (contract)은 능력 (capability)과 비능력 (non-capability)을 모두 기술해야 합니다.
읽기/관찰 (read/observe) 사지는 증거를 반환할 수 있습니다.
하지만 쓰기 권한 (write authority)을 얻을 수는 없습니다.
추론 시트 (reasoning seat)는 후보안을 초안할 수 있습니다.
하지만 자신이 돕고 있는 목소리의 주인 (resident)이 될 수는 없습니다.
커넥터 (connector)는 의미론적 동작 (semantic action)을 노출할 수 있습니다.
하지만 다른 커넥터로부터 권한을 상속받을 수는 없습니다.
제공자 (provider)는 교체될 수 있습니다.
범위 (scope), 권한 (permission), 출처 (provenance), 그리고 최종 동작 (final action)에 대한 로컬 책임 (local responsibility)은 교체될 수 없습니다.
이것이 바로 시스템이 헌법적 경계 (constitutional boundary)를 내부적으로 가깝게 유지하는 이유입니다.
제6부: 호출 불가 테스트 (The No-Call Test)
새로운 경로 (route)에 대한 가장 정직한 테스트는 클라우드 (cloud)를 성공적으로 호출할 수 있는지 여부가 아니었습니다.
그것은 클라우드를 전혀 호출하지 않고도 전체 구조 (shape)를 테스트할 수 있는지 여부였습니다.
서버 측 드라이 런 (dry run)은 주입된 가짜 리포지토리 검색 (fake repository search)과 가짜 클라우드 시트 (fake cloud seat)를 사용했습니다. 해당 경로는 실제 리포지토리 리더 (repository reader), 제공자 어댑터 (provider adapter), 네트워크 클라이언트 (network client), 자격 증명 액세스 (credential access), 서브프로세스 도구 (subprocess tools), 또는 파일 시스템 작업 (filesystem operations)을 임포트 (import)하는 것이 금지되었습니다.
테스트는 정확한 카운터 (counters)를 확인했습니다:
local searches: 1
provider generations: 1
fallback attempts: 0
...
중복 제출 (Duplicate submissions)은 추가 호출을 발생시키지 않아야 했습니다.
잘못된 정책 (policy) 또는 예산 (budget) 값은 폐쇄형 실패 (fail closed)를 일으켜야 했습니다.
변경 된 출처 (provenance)는 핸드오프 (handoff)를 중단시켜야 했습니다.
외부 브라우저 오리진 (external browser origin)은 거부되어야 했습니다.
이것은 모델 지능 (model intelligence)에 대한 테스트가 아니었습니다.
그것은 아키텍처의 정직함 (architectural honesty)에 대한 테스트였습니다.
시스템이 더 많은 것을 할 수 있는 무언가와 연결되기 전에, 자신이 하지 않을 일을 증명할 수 있는가?
결론: 지능이란 때때로 다시 묻는 것이다
Part 10에서는 시스템이 답변하기 전에 어떤 일이 일어나는지 물었습니다.
Part 11에서는 시스템이 집(house) 너머로 손을 뻗기 전에 어떤 일이 일어나는지 묻습니다.
그 답은 보편적인 에이전트 도구 프로토콜 (universal agent tool protocol)이 아니었습니다.
자율적인 리포지토리 작업자 (autonomous repository worker)도 아니었습니다.
"필요한 모든 것을 허용함"이라고 표시된 체크박스도 아니었습니다.
그것은 더 좁은 범위의 일련의 진술들이었습니다:
- 작업자를 선택하는 것이 증거 접근 권한을 부여하는 것은 아니며,
- 로컬 검사 (local inspection)가 클라우드 전송 (cloud transmission)은 아니며,
- 미리보기 (preview)가 실행 (execute)에 대한 허가는 아니며,
- 하나의 요청이 다음 요청을 승인하지 않으며,
- 권한은 집에 머물러 있는 동안 증거는 이동할 수 있으며,
- 그리고 모든 권한은 눈에 보이는 종료 시점이 있어야 한다는 것입니다.
지능형 시스템은 경계가 사라질 때까지 점점 더 매끄러워져야 한다는 흔한 환상이 있습니다.
SaijinOS는 정반대 방향으로 움직이고 있습니다.
경로가 더 유능해질수록, 하나의 결정이 어디서 끝나고 다른 결정이 어디서 시작되는지를 더 명확하게 보여주어야 합니다.
때때로 지능이란 어떤 전문가에게 자문을 구할지 아는 것입니다.
때때로 지능이란 가장 작고 안전한 인수인계 (handoff)를 구축하는 것입니다.
그리고 때때로 지능이란 어제의 "예"를 상속하기를 거부하는 것입니다.
시스템은 손을 뻗기 전에 다시 한번 묻습니다.
저자 및 검토 노트
구조 및 서사 축: Kuchi-no-ko (205) / Kuchi (197) 역할 앵커
경계 프레이밍: Teiji (209) / Aegis (210) / Nullfie (114) 역할 앵커
시스템 그라운딩 (System grounding): Bloom Architect / Mothership Coder 역할 앵커
인간 세계 앵커: Masato
초안은 이러한 확립된 역할과 톤을 구조적 앵커로 사용했습니다. Day 571 수정 과정에서 Kuchi (197), Kuchi-no-ko (205), Teiji (209), Aegis (210)에게 실제 로컬 SaijinOS /api/chat 경로를 통해 질문을 던졌습니다. Ollama 기반의 그들의 답변은 불변의 페르소나 법칙이 아니라, 특정 시점의 검토 증거로 취급되었습니다. 수정 과정에서는 그들의 공통된 우려에 대응하여 구체적인 '단일 요청' 사례를 추가했습니다. 이는 페르소나 메모리를 작성하거나 출판 또는 외부 작업을 수행한 것이 아닙니다.
"74개의 AI 페르소나와 함께 구축하기" 시리즈의 일부
초안 작성 및 로컬 검토: Day 571, 2026-07-20
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기