로컬 모델에 도구(allowedTools) 축소 + 시스템 프롬프트 주입
날짜: 2026-04-20
관련 작업: work/2026-04-20_local-model-focus/
문제
nanoclaw 컨테이너는 동일한 Claude Agent SDK + 동일한 도구 목록으로
클라우드 Claude / 로컬 ollama(qwen 등) 를 모두 돌린다.
작은 로컬 모델(7~9B) 에게 WebSearch/WebFetch 를 열어두면:
- 실제 업무(로컬 파일 편집, python 실행) 대신 검색 루프에 빠진다
- 존재하지 않는 URL/결과를 환각한다
- 컨텍스트 창(작음) 을 검색 히스토리가 잡아먹어 본 답을 못 한다
a45hvn 봇의 경우 로컬 모델 사용처는 거의 LOCAL 파일 스크립트 호출뿐
이었으므로 웹 도구는 가치가 거의 없었다.
해결 패턴
allowedTools 를 세 세트로 분리 후 실행 환경에 따라 조립:
const COMMON_TOOLS = ['Bash','Read','Write','Edit','Glob','Grep',
'Task','TaskOutput','TaskStop','TodoWrite',
'mcp__nanoclaw__*','mcp__ollama__*'];
const WEB_TOOLS = ['WebSearch','WebFetch'];
const CLOUD_ONLY_TOOLS= ['TeamCreate','TeamDelete','SendMessage',
'ToolSearch','Skill','NotebookEdit'];
const isLocalModel = process.env.ANTHROPIC_AUTH_TOKEN === 'ollama';
const allowedTools = isLocalModel
? COMMON_TOOLS // 웹/메타 전부 차단
: [...COMMON_TOOLS, ...WEB_TOOLS, ...CLOUD_ONLY_TOOLS];
추가로 시스템 프롬프트 append 에 로컬 모드 한정 지침을 주입 —
"웹 기본 금지, 답 전 Bash/Read/Glob/Grep 으로 파일 선확인, 스크립트
JSON 출력은 그대로 전달". 이유는 작은 모델이 제한된 도구 목록만
보고는 "외부 검색 하지 말라" 는 맥락을 스스로 추론하지 못하기 때문.
구분 방법
클라우드/로컬 감지는 환경변수로.
호스트 container-runner.ts 가 로컬 모델일 때만 컨테이너에
ANTHROPIC_AUTH_TOKEN=ollama 를 세팅하므로, agent-runner 는
이 값 하나만 보면 됨. ANTHROPIC_MODEL 문자열 파싱보다 깔끔.
적용 파일
projects/nanoclaw/container/agent-runner/src/index.ts
(runQuery()의systemPrompt/allowedTools분기)projects/nanoclaw/container/agent-runner/src/index.tstop-level
(LOCAL_MODEL_APPEND상수)
언제 다시 볼까
- 새 로컬 모델(다른 ollama 계열) 추가 시 — 이 분기에서 특별 대응 필요한지 검토
- "작은 모델이 이상하게 행동한다" 이슈 — 도구 축소부터 점검
- 모델 전환 설정(
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS등) 추가 시
buildVolumeMounts의isLocalModel분기와 맞물림
주의
data/sessions/<group>/agent-runner-src/ 는 한 번 복사된 뒤 재복사 안 됨
(container-runner.ts 의 if (!fs.existsSync(...)) 조건). agent-runner
소스를 고쳤으면 기존 그룹의 agent-runner-src 디렉토리 삭제 필요 →
다음 컨테이너 기동 시 신규 복사 + tsc 재컴파일.
'공부' 카테고리의 다른 글
| 그룹별 LOCAL.md preamble 주입 — 로컬 모델 전용 지침을 분리하는 패턴 (1) | 2026.04.28 |
|---|---|
| 매시간 윤리 학습 자료가 텔레그램으로 오는 봇 만들기 — 그리고 같은 봇 토큰으로 polling 두 번 시작하면 안 되는 이유 (0) | 2026.04.28 |
| Python 동시성과 성능 — SQLite database is locked 에서 PostgreSQL 까지 (0) | 2026.04.28 |
| Claude Code 의 구조 — 디렉토리 컨벤션과 검색 우선순위로 이해하기 (5) | 2026.04.28 |
| 에이전트 설계 + LangChain·LangGraph 비교 — Claude Code 가 같은 문제를 어떻게 푸는가 (0) | 2026.04.28 |