QA Agent Lane 세션 분리와 Context-Gateway 플러그인 설계

26년 03월 21일

Lane은 세션을 공유하면 안 된다

어제 QA Agent 실행 방식을 CLI에서 서버 세션으로 바꾸기 시작했다.

오늘은 그 구조를 확정하고 컨텍스트 압축 도구를 플러그인으로 다시 설계했다.

전날의 연장선에서 아키텍처를 굳히는 날이었다.

어제 세션 구조를 잡으면서 든 생각이 하나 있었다.

Lane마다 세션을 따로 쓰긴 하는데, 진짜로 분리가 되는 건지 확인해야 했다.

Lane은 QA Agent에서 병렬 실행 단위다.

Planner가 케이스 특성에 맞춰 1~5개 사이에서 Lane 개수를 정하고 각 Lane에서 테스트 케이스를 돌린다.

그런데 Lane들이 하나의 세션을 공유하면 문제가 생긴다.

한 Lane이 브라우저 상태를 바꾸면, 같은 계정으로 테스트하는 다른 Lane이 그걸 밟는다.

한 Lane이 알아낸 정보가 다른 Lane 컨텍스트에 섞여 들어가기도 한다.

그래서 오늘 “Lane 간 세션 공유 금지”를 확정했다.

계획을 담당하는 세션 하나, 그리고 각 Lane마다 각자 세션을 쓴다.

절대 섞지 않는다.

이게 멀티 에이전트 구조의 전제 조건이다.

며칠 뒤에 Planner, Executor, Inspector가 역할을 나눠서 돌아가는데, 그때도 각자의 컨텍스트가 독립적이어야 제 역할을 한다.

오늘 세션 분리 원칙을 굳혀둔 게 그 기반이 됐다.

세션 분리를 하면 컨텍스트가 단절된다는 단점이 있다. 한 Lane이 알아낸 라우팅 정보를 다른 Lane이 못 쓴다거나.

이건 Fixture Knowledge라는 외부 저장소로 보완한다.

프로세스는 분리하되, 알아낸 지식은 SQLite에 저장해서 Lane 간에 공유한다.

분리하되 잃는 건 없게 만드는 구조다.

Context-Gateway를 플러그인으로

두 번째 작업은 Context-Gateway를 다시 설계한 거다.

Context-Gateway는 컨텍스트 압축 프록시다.

LLM 에이전트가 대화를 이어가다

보면 컨텍스트 윈도우가 차는데, 이걸 압축해서 더 긴 대화를 유지할 수 있게 돕는다.

그 전까지는 이걸 독립된 도구로 따로 설치해서 썼다.

근데 독립 도구로 두니까 설정이 귀찮았다.

API 키도 따로 발급받아야 하고 세팅도 따로 해야 했다.

이미 opencode 설정에 API 키가 있는데, Context-Gateway용으로 또 하나 만들어야 하니까 비효율적이었다.

그래서 opencode 플러그인으로 옮기기로 했다.

플러그인으로 만들면, 사용자가 플러그인을 설치하기만 하면 바로 컨텍스트 압축을 쓸 수 있다.

별도 인증 없이 opencode에 이미 설정된 프로바이더를 그대로 재사용한다.

사이드카 아키텍처

설계는 사이드카 방식으로 잡았다.

Context-Gateway 바이너리를 플러그인 안에 같이 묶고 플러그인이 로드될 때 자동으로 실행되게 만들었다.

런타임은 TypeScript에 Bun을 쓴다.

패키지 매니저는 npm, pnpm, bun 어느 쪽이든 지원한다.

플랫폼별 바이너리는 GitHub Releases로 배포하고 postinstall 스크립트가 알아서 플랫폼에 맞는 바이너리를 내려받는다.

macOS arm64, x64, Linux x64, arm64, Windows x64를 다

커버한다.

설정 조회도 SDK 기반으로 했다.

설정 파일을 직접 파싱하는 게 아니라, SDK의 client.provider.list()를 호출해서 프로바이더 정보랑 모델 메타데이터를 가져온다.

API 키도 여기서 재사용하고 컨텍스트 윈도우 크기도 모델 메타데이터에서 계산한다.

그러니까 사용자가 설정할 게 거의 없다.

디폴트로 대부분 커버되고 세부 조정이 필요하면 context-gateway.json으로 잡는다.

opencode 세션 저장소가 바뀐 배경

이 작업을 하면서 opencode 자체의 세션 저장소 마이그레이션도 확인했다.

opencode는 원래 세션을 파일 기반 JSON으로 저장하고 있었다.

근데 이게 1기가바이트를 넘어가면서 무거워졌다.

그래서 최근 버전에서 SQLite DB 하나로 마이그레이션했다.

오늘 한 서버 기반 세션 작업이 이 durable 세션 저장소에 의존한다.

세션이 파일로만 있으면 서버 모드로 유지하기 어려우니까, SQLite로 저장소가 바뀐 게 전제 조건이 됐다.

마무리

두 작업이 전부 아키텍처를 굳히는 일이었다.

Lane 세션 분리는 멀티 에이전트 구조의 전제 조건이고 Context-Gateway 플러그인화는 컨텍스트 압축을 쓰기 쉽게 만드는 일이었다.

Lane 분리 원칙은 이후에도 계속 영향을 줬다.

분리하면 컨텍스트가 단절되는 트레이드오프가 있는데, 이걸 Fixture Knowledge로 보완한 게 핵심이었다.

프로세스는 분리하되 지식은 공유한다.

이 원칙이 이후 QA Agent 설계의 뼈대가 됐다.