모델 탓하기 전에 확인해야 할 것: 설정, 경로, 상태 격리

26년 06월 23일

빈 출력이 모델 탓이 아니다

이날은 “모델 탓”을 세 번이나 뒤집은 날이다.

에이전트가 실패하면 모델을 탓하기 쉽다.

근데 원인이 설정이거나 경로이거나 상태 격리일 때가 많다.

이날 세 가지 사건이 전부 “모델이 아니라 인프라”였다.

첫 번째 사건은 가장 극적이었다.

여러 서브에이전트가 동시에 빈 출력을 냈다.

토큰 0, 1초 만에 종료. 이전에 같은 증상을 “모델 환경 장애”로 진단했었다.

근데 원인이 달랐다.

rtk 확장의 파일 경로가 바뀌었다.

단일 파일에서 디렉토리 구조로 바꿨다.

근데 12개 에이전트 정의가 여전히 옛 경로를 참조하고 있었다.

자식 프로세스가 존재하지 않는 파일을 로드하려다가 부팅 단계에서 크래시가 난 거다.

모델은 호출조차 안 됐다.

진단 지문

이걸 구분하는 지문이 있다.

부팅 크래시는 토큰이 0이고 1초 만에 종료되고 events.jsonl에 stderr가 있고 session.jsonl이 안 만들어진다.

모델 장애는 토큰이 부분적으로 있고 수십 초 걸리고 session.jsonl이 만들어진다.

이 지문을 안 쓰면, “여러 에이전트가 동시에 실패했으니까 모델 환경 장애”라고 단정한다.

근데 공유 설정 결함도 똑같이 여러 에이전트가 동시에 실패하게 만든다.

“동시 실패 = 모델 문제”라는 가정이 틀린 거다.

프로세스 격리가 상태 격리는 아니다

두 번째는 Playwright 다중 세션 간섭이었다.

두 개 이상의 pi 세션을 동시에 돌리면, 한 세션이 다른 세션의 브라우저 창을 닫았다

열었다

했다.

마치 하나의 Chrome을 공유하는 것처럼. 프로세스는 격리되어 있었다.

각 세션이 별도의 자식 프로세스를 띄운다.

근데 상태가 격리되어 있지 않았다.

Playwright MCP가 프로필을 디스크에 저장한다.

프로필 경로가 머신 기반 해시로 만들어진다.

같은 머신에서 같은 작업 디렉토리를 쓰면, 같은 해시가 나온다.

같은 프로필을 공유한다.

같은 Chrome을 쓰는 거다.

해결은 --isolated 플래그를 추가하는 거였다.

프로필을 메모리에만 두고 프로세스가 끝나면 버린다.

각 세션이 독립적인 브라우저를 가진다.

프로세스 격리랑 상태 격리는 다르다.

프로세스가 분리되어 있어도, 디스크 상태를 공유하면 간섭이 생긴다.

“프로세스가 분리되어 있으니까 괜찮겠지”라는 가정이 틀린 거다.

깃 커밋 가드가 사라져 있었다

세 번째는 가장 충격적이었다.

서브에이전트가 깃 커밋을 못 한다고 믿고 있었다.

근데 못 하는 게 아니었다.

리팩터링하면서 훅이 통째로 지워졌다.

설정 키는 남아 있었다.

근데 아무도 그 키를 안 읽고 있었다.

설정 키가 존재한다고 동작하는 건 아니다.

소비하는 코드가 있어야 동작한다.

이건 보안에서 치명적이다.

“막혀 있다”고 믿고 있는데 실제로는 안 막혀 있다.

안전망이 있다고 가정하고 설계하면, 안전망이 없을 때 무방비 상태가 된다.

해결은 모든 서브에이전트의 깃 커밋을 차단하는 거였다.

설정 한 줄로 메인 에이전트만 커밋할 수 있게 만들었다.

16개 시나리오를 테스트해서 전부 통과했다.

독립 검증이 공유 컨텍스트보다 낫다

마지막으로 검증 철학에 대한 논의가 있었다.

검증 에이전트들이 각자 독립적으로 조사하는 게 좋은가, 아니면 하나의 컨텍스트를 공유하는 게 좋은가. 공유 컨텍스트의 문제는 맹점이 공유된다는 거다.

컨텍스트를 만든 에이전트가 잘못 읽으면, 모든 검증 에이전트가 같은 잘못을 물려받는다.

독립 검증은 에러가 상관관계가 없다.

세 개의 검증 에이전트가 같은 문제를 찾으면 강한 신호다.

하나만 찾으면 약한 신호다.

공유 컨텍스트는 이 구별력을 파괴한다.

“효율적이니까 컨텍스트를 공유하자”는 함정이다.

효율적이지만 맹점을 공유한다.

검증의 가치는 독립성에서 온다.

마무리

이날의 교훈은 “모델 탓하기 전에 인프라를 확인하라”다.

빈 출력은 모델이 안 불린 거였다.

브라우저 간섭은 상태 격리 문제였다.

커밋 가드는 설정 키만 남고 코드가 사라진 거였다.

이런 문제를 빨리 잡으려면 진단 지문을 쓴다.

토큰이 0이면 모델이 안 불린 거다.

프로세스가 분리되어 있어도 디스크 상태를 확인한다.

설정 키가 있으면 소비하는 코드가 있는지 확인한다.

“당연히 되겠지”라고 가정하지 마라. 당연히 막혀 있을 거라고 믿은 커밋 가드가 사라져 있었다.

당연히 격리되어 있을 거라고 믿은 브라우저가 프로필을 공유하고 있었다.

가정을 확인하지 않으면, 안전망이 없는 상태로 돌아가는 거다.