모델이 보는 도구 목록은 샘플 한 번으로 계산됩니다
같은 대화, 같은 설정인데도 다음 샘플에는 MCP 이름, 협업 입구, 또는 tool_search가 더 붙을 수 있어요. 바뀌는 건 이번 요청이 광고해도 되는 handler입니다.
tool_search만 남습니다.
- 이번 step의 MCP 바인딩을 해석mcp.rs L310
- MCP 목록을 모아 계획 함수에 넘김turn.rs L1494
- 신분으로 전체 출처를 탈지 정함spec_plan.rs L889
- shell, 리소스, 유틸, 협업을 등록spec_plan.rs L930
- MCP를 붙이고 노출 정책을 씌움spec_plan.rs L148
- deferred가 있을 때만 tool_search를 걺spec_plan.rs L335
- is_direct인 spec만 모델에 보냄spec_plan.rs L484
- StepContext.tool_router에 얼림step_context.rs L44
- build_prompt가 보이는 표를 읽음turn.rs L1320
build_tool_router에 맞춰 있어요. 논리 궤적 오른쪽 행 번호는 openai/codex 저장소 commit 4f39251a01에 대응합니다.방금 MCP filesystem을 붙였는데, 모델은 이번 라운드를 아직 달리고 있어요. 사용자 대화 한 턴 단위로 도구 표를 얼리면, 새로 붙은 서버는 다음 사용자 메시지를 기다려야 메뉴에 들어갑니다. 도구를 부를 때마다 얼리면, 같은 샘플 안의 병렬 호출 둘이 서로 다른 표를 볼 수 있어요.
광고한 표와 실행하는 표가 다르거나, 실행 중에 표가 바뀌는 것이 도구 표가 가장 자주 뒤집히는 방식이에요.
Codex는 이번 샘플의 모델, 승인, 환경, MCP 바인딩, 이미 계산된 tool_router를 함께 StepContext에 넣어요. 주석은 request-scoped라고 적습니다. 샘플 요청 사이에는 바뀌어도, 한 샘플 안에서는 안 바뀌어요. tool_router는 this exact sampling request의 계획입니다.
샘플이 도는 동안 모델이 보는 이름과 dispatch할 runtime은 모두 이 스냅샷을 읽어요. MCP 서버가 이번 샘플 도중에 떨어져도 이미 계산된 표는 안 바뀝니다. 다음 샘플은 mcp_runtime_for_step을 다시 타고, 바인딩은 재사용되거나 빈 바인딩으로 바뀔 수 있어요.출처:codex-rs/core/src/session/step_context.rs 17–47행;codex-rs/core/src/session/mcp.rs 348–357행
그래서 동결 단위는 step이지 turn이 아니에요. 한 turn 안에 샘플이 여러 번 있을 수 있고, 매번 StepContext를 다시 만듭니다.출처:codex-rs/core/src/session/turn.rs 1318–1320행
보이는 것과 실행 가능한 것이 스냅샷 하나를 공유하고, 다음 라운드가 새 연결을 흡수해요. 다른 언어로 다시 써도 최소 형태는 함수 하나입니다. 스위치, MCP 목록, 신분을 넣고, 보이는 표와 실행 표를 내놓으며, 요청이 시작할 때 한 번 계산하고 끝나면 얼립니다.
승인 모델이 작업 모델의 MCP와 협업 도구 표 전체를 보면 spawn_agent를 하거나 외부 자원을 읽을 수 있어, 승인 자체가 우회됩니다. 전체를 등록한 뒤 걸러내면, 분기 하나만 빠져도 주면 안 되는 이름이 나갑니다.
계획 함수는 신분으로 어떤 출처를 탈지 정해요. Guardian 심사원 라벨은 정확히 guardian이어야 합니다. 권한 프로필이 Managed가 아니면 함수는 바로 돌아가고 레지스트리는 비어 있어요. Managed이고 환경이 있으면 최대 세 점입니다. exec_command, write_stdin, 선택 view_image. 일반 세션만 shell, MCP 리소스, 유틸, 협업 네 묶음을 타고, 그다음 MCP, 확장, 동적 도구를 붙입니다.출처:codex-rs/core/src/guardian/review.rs 212–220행;codex-rs/core/src/tools/spec_plan.rs 144–164행、889–934행
디스크 읽기에도 일등 입구가 없어요. handlers 디렉터리에 ReadFileHandler가 없습니다. 모델이 파일을 읽으려면 exec_command, MCP filesystem, 또는 view_image 안의 exec-server API를 탑니다.
신분이 바뀌면 출처 묶음 전체를 안 타요. 기본으로 문을 닫는 곳은 심사원, 환경 없음, 기능 끔이고, 다른 언어에도 그대로 씁니다.
MCP 도구 schema는 비싸요. 전부 걸면 첫 요청의 토큰을 설명 텍스트가 먹습니다. 서버 둘이 모두 read_file을 주면, 이름을 가리지 않으면 충돌해요.
노출 상태가 레지스트리를 보이는 면 몇 갈래로 나눕니다. Direct는 초기 표에 들어가요. Deferred는 tool_search에만 남기고, Hidden은 dispatch에만 남깁니다. 검색이 켜져 있으면 MCP 도구는 기본 Deferred라 초기 가시 표에 안 들어가요.출처:codex-rs/tools/src/tool_executor.rs 51–80행;codex-rs/core/src/mcp_tool_exposure.rs 90–94행
finalize_tool_router는 두 가지가 동시에 성립할 때만 tool_search를 겁니다. 모델이 search tool을 지원하고, 레지스트리에 deferred이면서 search_info가 있는 도구가 하나라도 남아 있어야 해요. deferred가 없으면 표에 안 들어갑니다.출처:codex-rs/core/src/tools/spec_plan.rs 335–370행、578–580행
MCP 서버 둘의 같은 이름 도구는 정규화 단계에서 가려요. 기본은 mcp__ 접두사고, sanitize 뒤에도 부딪히면 12자리 해시 접미사를 붙입니다. 외부 도구가 이미 쓰인 핵심 이름과 부딪히면 그냥 건너뛰어요. 저장소 루트 AGENTS.md는 아직 mcp_connection_manager.rs를 적지만, 지금 트리에는 그 파일이 없고 이름 가리기는 tools.rs에 있습니다.출처:codex-rs/codex-mcp/src/tools.rs 1–5행、113–151행;AGENTS.md 35행
보이는 것, 검색 가능한 것, 실행 가능한 것은 집합 셋이에요. 토큰 예산이 빠듯하면 발견을 미루고, 핵심 이름은 지키며 외부가 길을 양보합니다. 이건 Rust에 매이지 않아요.
DeepSeek Harness: 플러그인이 조립기에 schema를 던짐
DSH에는 중앙 계획 함수가 없어요. 도구 팩마다 assemble 때 systemPrompt.tools()로 schema를 던지고, 조립기가 배포 설정의 toolOrder로 자리를 잡습니다. 이름이 안 불린 도구는 예약 표시 <unlisted-tools>에 이름 사전순으로 끼어요. 이 표시를 빼먹으면 assemble이 바로 실패합니다.
@deepseek-ai/dsh-tool-fs를 얹으면 모델이 일등 도구 read를 봐요. 설명은 텍스트를 이걸로 읽으라고 합니다. Codex는 디스크 읽기를 shell, MCP, 내부 API에 맡기고, 계획 함수에는 read_file 입구가 없어요.
Claude Code: 정적 기본 표 더하기 MCP, 내장이 우선
getAllBaseTools는 박아 둔 배열이고 FileReadTool은 일등 멤버예요. 요청 때 assembleToolPool이 먼저 deny 규칙을 걸러, 내장과 MCP를 이름순으로 각각 정렬한 뒤 이어 붙입니다. 내장이 앞이고, 이름이 부딪히면 내장이 이겨요. 주석은 이 순서가 prompt cache 때문이라고 적습니다. MCP를 내장 가운데 끼우면 뒤 cache key가 전부 죽어요.
Claude Code 기본 표는 파일 하나만 열면 셀 수 있어요. Codex 목록을 세려면 add_core_tool_sources를 끝까지 걸어야 합니다. 같은 계획이 신분과 예산으로 자를 수 있어요.
이번 라운드 메뉴에 뭐가 남나
먼저 MCP와 검색을 켜고, mcp__filesystem__read_file이 회색 구역에, tool_search가 메뉴에 있는지 확인하세요. 그다음 세 박자를 추론합니다. 검색은 켠 채 MCP가 전부 Hidden이 되고, 샘플 도중에 끊기고, 다음 샘플을 탑니다. 박자마다 가시 표, 회색 구역, tool_search가 있는지를 적으세요.
심화 한 질문: 신분을 Guardian 심사원으로 바꾸고, 권한은 먼저 Managed였다 다른 값으로 바꿉니다. 메뉴는 각각 무엇이고, 왜 도구를 몇 개 덜 거는 게 아닌가요.
StepContext가 그것들을 샘플 경계에 얼립니다. 표에 read_file이 없어도 모델은 exec_command로 파일을 읽을 수 있어요.