화면에서 숨겼다고 모델이 안 보는 게 아니다

26년 07월 22일

메시지 주입 3축

내가 이날 발견한 가장 중요한 사실은 “화면에서 숨겼다고 모델이 안 보는 게 아니다”였다.

이날은 pi 확장이 정보를 주입하는 3가지 경로를 정리한 날이다.

핵심 발견은 “화면에서 숨겼다고 모델이 안 보는 게 아니다”였다.

그리고 프롬프트 기반 도구 제어가 확률적이라는 것도 증명했다.

pi 확장이 세션에 정보를 주입하는 경로는 3개다.

각 경로가 “모델이 보는가”, “화면에 표시되는가”, “저장되는가”를 다르게 제어한다.

메시지 축: 항상 모델에 도달한다

메시지 축은 모델 컨텍스트에 항상 도달한다.

근데 여기에 함정이 있다.

화면 숨김을 설정하면 TUI에서 박스가 사라진다.

“숨겼다”고 생각한다.

근데 모델은 여전히 읽고 있다.

화면 숨김 설정은 TUI 박스를 지울 뿐, 모델 컨텍스트에서 제외하지 않는다.

변환 함수가 여전히 사용자 메시지로 매핑해서 모델에 보낸다.

“화면에 안 보이니까 모델도 안 보겠지”라는 가정이 틀렸다.

화면 표시와 모델 컨텍스트는 별개다.

엔트리 축: 모델이 구조적으로 못 본다

모델이 진짜로 못 보게 하려면 엔트리 축을 써야 한다.

엔트리 축은 컨텍스트 변환이 빈 배열을 반환한다.

모델이 구조적으로 절대 볼 수 없다.

이게 진짜 “사용자 전용” 채널이다.

알림 축: 휘발성

알림 축은 상태 표시줄에 잠깐 나타났다 사라지는 토스트다.

모델 컨텍스트에도 안 들어가고 화면에도 잠깐만 나온다.

핵심: 구조적 제외만 믿어라

“화면 숨김” 설정은 표시 제어일 뿐이다.

모델 제외가 아니다.

모델이 정말로 못 보게 하려면 구조적으로 제외되는 경로를 써야 한다.

“꺼져 있다”는 표시와 “없다”는 구조는 다르다.

프롬프트 기반 제어는 확률적이다

같은 날 두 pi 세션이 같은 프롬프트 파일을 반대 방향으로 수정했다.

하나는 코드베이스 검색을 권장하고 다른 하나는 제한했다.

이건 우연이 아니다.

프롬프트 기반 도구 제어는 확률적이다.

프롬프트는 “경향”을 만들 뿐, “강제”를 만들지 않는다.

같은 프롬프트를 읽고도 상황에 따라 다른 결정을 내린다.

제어 계층 모델

그래서 제어를 3계층으로 분류했다.

첫째, 소프트 제어. 프롬프트 설명으로 도구 사용을 권장하거나 제한한다.

확률적이다.

둘째, 미드 제어. 훅으로 도구 실행 전에 개입한다.

프롬프트보다 강하지만 여전히 우회 가능하다.

셋째, 하드 제어. 도구 자체를 제거한다.

강제다.

우회 불가능하다.

“이 도구를 쓰지 마라”라고 프롬프트에 적는 건 소프트 제어다.

확률적으로 줄어들 뿐, 강제가 아니다.

강제가 필요하면 도구를 제거해야 한다.

”실패” 라벨이 거짓말을 했다

ctx 자식 에이전트들이 “사용 불가능한 도구” 라벨로 “실패” 표시가 떴다.

근데 실제로는 세 도구 전부 첫 번째 호출에서 정상 작동했다.

3번이나 독립 검증했다.

탐침 에이전트가 정상 작동했고 작업자가 라벨과 무관하게 파일을 올바르게 수정했다.

“실패” 라벨이 거짓이었다.

라벨이 거짓말을 할 수 있다

“실패” 라벨과 실제 실패는 다르다.

라벨은 진단의 출발점이지, 결론이 아니다.

라벨이 “실패”라고 해서 실제로 실패한 게 아니다.

라벨과 실제 동작을 독립적으로 검증해야 한다.

접근 제어는 발견을 막아야 한다

위키 라이브러리안 스킬을 비공개로 만들었다.

기존에는 모델 호출 비활성화 플래그로 시스템 프롬프트에서 숨기기만 했다.

근데 디렉토리가 여전히 발견 가능했다.

해결은 스킬을 pi의 발견 경로 밖으로 옮기는 거였다.

발견 자체를 차단한다.

플래그 기반 숨김은 “보이지 않을 뿐 찾을 수 있다”다.

경로 기반 차단은 “찾을 수 없다”다.

접근 제어는 가시성 숨김이 아니라 발견 차단이어야 한다.

마무리

이날의 핵심은 “표시와 구조를 구분하라”였다.

화면 숨김 설정은 표시 제어다.

모델 컨텍스트 제외가 아니다.

“화면에 안 보인다”와 “모델이 안 본다”는 다르다.

구조적으로 제외되는 경로만이 모델 제외를 보장한다.

프롬프트 기반 제어도 같다.

“쓰지 마라”고 적는 건 표시다.

강제가 아니다.

같은 프롬프트를 읽고도 반대 결정을 내린다.

강제가 필요하면 구조적으로 도구를 제거해야 한다.

그리고 “실패” 라벨도 같다.

라벨은 표시다.

실제 동작이 아니다.

라벨과 실제를 독립적으로 검증해야 한다.

표시를 믿지 마라. 구조를 확인해라.