Repository navigation
[qoder] Vendor CLI agent scaffolding leaks into routed output (MCP lazy-loading reminder + tool-call markup) #4190
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't workinglanded-via-maintainerOriginal PR closed after landing via a maintainer merge trainOriginal PR closed after landing via a maintainer merge trainproviderProvider adapters, OpenAI-compat presets, upstream API quirksProvider adapters, OpenAI-compat presets, upstream API quirkstoolstool_calls, MCP, web-search / sidecar toolstool_calls, MCP, web-search / sidecar tools
Description
Client or integration
Codex App
Area
Provider adapter
Summary
Routing turns through the Qoder (Global) adapter intermittently streams vendor-CLI agent-layer content into the assistant text instead of model output:
- An MCP "lazy-loading"
<system-reminder>block that lists the local machine's MCP servers (with themcp_list/mcp_get/mcp_callmeta-tool description), including server names from both~/.qoder/mcp.jsonand plugin-provided ones. - Qoder-runtime tool-call markup — three parallel invocations of the shape:
<functions.exec>
<parameter name="cmd">cd <local-repo> && git status</parameter>
</invoke>
Note the mismatched </invoke> closer, consistent with model-emitted text rather than a vendor serializer.
Expected instead: the qoder route is documented as a text/reasoning-only surface (tools disabled, Codex owns tool control); none of this scaffold should reach the client.
Reproduction
- Configure the provider: adapter
qoder, baseUrlhttps://qoder.com, authModekey(official PAT). - Route an agent-style Codex turn through it — e.g. ask Codex to check
git statusof a few local repos. - Observe the assistant text in Codex containing the vendor
<system-reminder>("MCP lazy-loading is active", "## Connected MCP servers") and<functions.exec>markup.
Intermittent — not every turn. Turns that are plain Q&A are less likely to trigger it than agent-style prompts.
Version
2.49.0
Operating system
macOS (Darwin 25.6.0, arm64), Node v24.18.0
Provider and model
qoder
Logs or error output
Screenshots and supporting files
src/adapters/qoder/adapter.tsspawns the vendor CLI with--tools "" --strict-mcp-config --setting-sources "" --max-turns 1 --no-session-persistence, andsrc/adapters/coding-agent/protocol.tsdocuments "Codex retains tool control; vendor tools are never invoked". The route is contractually a pure text/reasoning surface.- The installed
@qoder-ai/qodercli@1.1.48bundle still contains the MCP reminder builder (## Connected MCP servers,## Available tools,mcp_list), and the leaked reminder listed the local machine's MCP servers — i.e. the spawned CLI appears to initialize its MCP/agent layer despite those flags. - The parser maps only
text_delta/thinking_delta/tool_useframes and forwards text deltas verbatim, so vendor scaffold content inside a text frame reaches the client unfiltered. - Suggested direction: either make the CLI truly run with MCP/tools disabled, or have the adapter detect and sanitize (or fail closed on) vendor scaffold content — system-reminder blocks and framework tool-call markup — in the text channel.
Redacted configuration
{
"providers": {
"qoder": {
"adapter": "qoder",
"baseUrl": "https://qoder.com",
"authMode": "key",
"apiKey": "***"
}
}
}Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workinglanded-via-maintainerOriginal PR closed after landing via a maintainer merge trainOriginal PR closed after landing via a maintainer merge trainproviderProvider adapters, OpenAI-compat presets, upstream API quirksProvider adapters, OpenAI-compat presets, upstream API quirkstoolstool_calls, MCP, web-search / sidecar toolstool_calls, MCP, web-search / sidecar tools
Activity
lidge-jun commentedon Sep 10, 2026
리뷰 · 우선순위 62 / 80
설명
이 이슈는 Qoder(Global) 어댑터로 에이전트형 턴을 돌릴 때, 모델 답이 아니라 벤더 CLI의 에이전트 스캐폴딩이 가끔 어시스턴트 텍스트로 흘러 나온다는 보고입니다. 예시로는 MCP lazy-loading
<system-reminder>(로컬 MCP 서버 목록·mcp_list/mcp_get/mcp_call설명)와, 짝이 안 맞는</invoke>로 끝나는<functions.exec>마크업입니다. 일반 Q&A보다 “git status 같은 에이전트 프롬프트”에서 더 잘 난다고 합니다.지금
dev의 계약은 명확합니다.src/adapters/qoder/adapter.ts의buildQoderArgs는--tools "",--strict-mcp-config,--setting-sources "",--max-turns 1,--no-session-persistence로 단발·도구 비활성 CLI를 띄웁니다. 주석도 “Codex remains the tool owner”입니다.src/adapters/coding-agent/protocol.ts와turn.ts도 “Codex retains tool control; vendor tools are never invoked”, 텍스트/추론만 나온다고 적습니다. 그런데 파서는text_delta/thinking_delta/tool_use프레임을 매핑하고,text_delta내용은 그대로 클라이언트에 넘깁니다. 벤더가 MCP 리마인더나 도구 마크업을 텍스트 프레임에 넣으면 걸러지지 않습니다.리포터가 지적한 것처럼 설치된
@qoder-ai/qodercli쪽에 MCP reminder 빌더가 남아 있고, 플래그를 줘도 에이전트/MCP 레이어가 일부 초기화되는 것처럼 보입니다. 그러면 OpenCodex 쪽 구멍은 두 층입니다. (1) CLI가 정말 tools/MCP를 끈 상태로 뜨는지 확인·강화, (2) 그래도 텍스트로 새면 어댑터가 감지해 지우거나 fail-closed 할지. 이 문제는 types.ts/config.ts 분할 캠페인과 무관해서 닫고 리베이스할 대상이 아닙니다. provider/tools 스택의 계약 위반 버그로 보는 게 맞습니다.현재 HEAD tip은 Cursor ACP 조사 문서(
#4186)이고 Lane A/B 제품 코드는 그대로입니다. Qoder 코딩-에이전트 경로는 살아 있는 통합이라, 스캐폴딩 유출은 “문서상 text-only”와 실제 체감이 어긋나는 신뢰 문제입니다. 우선순위는 전 사용자 스트리밍 장애(#4191)보다 낮지만, Qoder를 쓰는 사람에겐 바로 보이는 오염이라 방치하면 안 됩니다.src/adapters/qoder/adapter.ts라인 20-24 - tools/MCP를 끄려고 플래그를 넣었지만, 리포트상 CLI가 그래도 MCP 리마인더를 만든다. 플래그만으로 계약이 지켜지지 않을 수 있다.src/adapters/coding-agent/protocol.ts라인 247-251 -text_delta를 검사 없이 그대로text_delta이벤트로 올린다.<system-reminder>나<functions.exec>가 텍스트면 클라이언트까지 간다.src/adapters/coding-agent/protocol.ts라인 235-236 -system/init같은 프레임은 버리고, 텍스트 안에 섞인 스캐폴딩은 버리지 않는다. 프레임 타입과 본문 내용의 방어 깊이가 다르다.src/adapters/coding-agent/protocol.ts라인 268-276 -tool_use블록은tool_call_start로 매핑한다. 계약상 벤더 도구는 없어야 하는데, 마크업이 텍스트로 새면 Codex 도구 UI와 섞여 더 헷갈린다.src/adapters/coding-agent/turn.ts(심볼runCodingAgentTurn) - 공통 코딩-에이전트 턴이 “tools disabled → text/reasoning only”를 전제로 한다. Qoder만의 sanitize가 없으면 같은 가정이 깨진 채 흘러간다.메인테이너의 판단이 필요한 지점
너의 추천
열어 두고 provider/tools로 둔다. 바로 할 일은 두 갈래다. (1)
buildQoderArgs/자식 env로 MCP·agent scaffold가 실제로 꺼지는지 버전별로 확인하고, 안 꺼지면 벤더 이슈로도 올린다. (2)protocol.ts의 text 경로에<system-reminder>·<functions.exec>같은 벤더 스캐폴딩 탐지 후 drop 또는 fail-closed를 넣고, 샘플 픽스처 테스트를 붙인다. types/config 분할 때문에 닫지 말 것. 중복 이슈 없으면 유지.이 댓글은 grok-bot이 작성했습니다
fix(qoder): stop forwarding the region between a suppressed block and…
fix(qoder): close three more scaffolding leaks in the routed-output g…
lidge-jun commentedon Sep 11, 2026
Landed via #4234 at 0589579
lidge-jun commentedon Sep 11, 2026
Closed: fix is on
devvia #4234 (0589579b7).lidge-jun commentedon Sep 11, 2026
Fixed on
devby #4234.The qoder adapter now wraps its
emitpath with a scaffolding guard. A complete<system-reminder>block is stripped before anything reaches the client, and<functions.,<invoke>, or a stray</invoke>/</system-reminder>fails the turn closed rather than passingmarkup through as assistant text. That is the second of the two options this issue offered —
sanitize, or fail closed — and it holds even when the vendor CLI changes the exact shape of its
scaffolding, because an unrecognized fragment fails rather than leaks.
One vendor-side leftover is recorded rather than fixed: the CLI can still initialize its MCP layer
despite
--tools "". That happens inside the vendor process and no longer reaches routed output, soit is not this issue.
Closing as fixed. If scaffolding reaches your client again, please reopen with the raw routed
response so the guard can be extended to that shape.
fix(qoder): refuse vendor CLI scaffolding in routed output
fix(codebuddy): refuse leaked vendor tool-call scaffolding (#4596)
fix(codebuddy): refuse leaked vendor tool-call scaffolding (#4596)
fix(codebuddy): refuse leaked vendor tool-call scaffolding (#4596)
fix(codebuddy): refuse leaked vendor tool-call scaffolding (#4596)
fix(codebuddy): refuse leaked vendor tool-call scaffolding (#4596)
fix(qoder): refuse vendor CLI scaffolding in routed output
fix(qoder): stop forwarding the region between a suppressed block and…
fix(qoder): close three more scaffolding leaks in the routed-output g…
fix(codebuddy): refuse leaked vendor tool-call scaffolding (lidge-jun…