Client or integration
Codex App
Area
Proxy / routing / tool-name normalization
Summary
A routed non-OpenAI model can emit the Codex view_image tool as default.view_image, which OpenCodex rejects as undeclared and aborts the stream:
stream disconnected before completion: routed provider emitted undeclared client tool "default.view_image"; only request-declared tools may be called
This still reproduces on OpenCodex 2.48.0.
The observed failure is similar to #3402 / #3403, but appears to be a different alias case.
#3403 fixed a declared namespaced tool whose provider echo used a different spelling:
default__apply_patch <-> default.apply_patch
This report is about a bare Codex tool being returned with an invented/default namespace:
view_image -> default.view_image
If the request declares bare view_image but does not declare default.view_image / default__view_image, the existing dotted ns.name alias support does not necessarily identify these as the same tool.
Current behaviour
- Codex exposes/uses the local
view_image tool.
- A routed custom/non-OpenAI model or upstream compatibility layer returns the function call name as
default.view_image.
responses-undeclared-tool-guard treats it as a different, undeclared client tool.
- The SSE stream is aborted.
- Codex App shows reconnect attempts (
reconnecting /5) and the turn fails.
Expected behaviour
OpenCodex should safely normalize a provider-added default. namespace back to the unique bare request-declared tool when that mapping is unambiguous.
For example, if the request-declared tool catalog contains exactly one bare tool named:
and does not contain a real namespaced tool whose canonical/alias name is default.view_image, then a provider echo of:
could be restored to:
before the undeclared-tool guard rejects it.
This should remain fail-closed when the mapping is ambiguous or the bare tool is not actually declared.
Suggested safety constraints
A conservative normalization could apply only when all of the following are true:
- The returned name has the form
default.<name>.
<name> is present as a request-declared bare tool.
default.<name> / the corresponding namespaced identity is not itself a declared tool.
- The mapping resolves to exactly one declared tool identity.
Otherwise preserve the current undeclared-tool rejection.
This would avoid broadly stripping arbitrary namespaces while handling providers that serialize un-namespaced function calls under a synthetic default namespace.
Reproduction
- Run OpenCodex 2.48.0 with Codex App routed through a custom/non-OpenAI provider.
- Use a task that causes the model to inspect an image through Codex
view_image.
- The routed provider returns
default.view_image.
- Observe:
stream disconnected before completion: routed provider emitted undeclared client tool "default.view_image"; only request-declared tools may be called
Codex App then attempts to reconnect repeatedly.
Version
OpenCodex 2.48.0
Operating system
Windows
Provider and model
Custom / non-OpenAI routed model. The issue appears to be at the tool-call naming/compatibility boundary rather than in Codex's native OpenAI model path.
Related issues
Additional context
Prompt-level guidance in AGENTS.md was added to tell non-OpenAI models to use only request-declared tools and exact tool names, including explicitly avoiding invented prefixes such as default.. The failure still occurs, suggesting the default. prefix may be introduced by the model/provider tool-call serialization path rather than being reliably preventable through prompt instructions alone.
Checks
Client or integration
Codex App
Area
Proxy / routing / tool-name normalization
Summary
A routed non-OpenAI model can emit the Codex
view_imagetool asdefault.view_image, which OpenCodex rejects as undeclared and aborts the stream:This still reproduces on OpenCodex 2.48.0.
The observed failure is similar to #3402 / #3403, but appears to be a different alias case.
#3403 fixed a declared namespaced tool whose provider echo used a different spelling:
This report is about a bare Codex tool being returned with an invented/default namespace:
If the request declares bare
view_imagebut does not declaredefault.view_image/default__view_image, the existing dottedns.namealias support does not necessarily identify these as the same tool.Current behaviour
view_imagetool.default.view_image.responses-undeclared-tool-guardtreats it as a different, undeclared client tool.reconnecting /5) and the turn fails.Expected behaviour
OpenCodex should safely normalize a provider-added
default.namespace back to the unique bare request-declared tool when that mapping is unambiguous.For example, if the request-declared tool catalog contains exactly one bare tool named:
and does not contain a real namespaced tool whose canonical/alias name is
default.view_image, then a provider echo of:could be restored to:
before the undeclared-tool guard rejects it.
This should remain fail-closed when the mapping is ambiguous or the bare tool is not actually declared.
Suggested safety constraints
A conservative normalization could apply only when all of the following are true:
default.<name>.<name>is present as a request-declared bare tool.default.<name>/ the corresponding namespaced identity is not itself a declared tool.Otherwise preserve the current undeclared-tool rejection.
This would avoid broadly stripping arbitrary namespaces while handling providers that serialize un-namespaced function calls under a synthetic
defaultnamespace.Reproduction
view_image.default.view_image.Codex App then attempts to reconnect repeatedly.
Version
OpenCodex 2.48.0
Operating system
Windows
Provider and model
Custom / non-OpenAI routed model. The issue appears to be at the tool-call naming/compatibility boundary rather than in Codex's native OpenAI model path.
Related issues
default.apply_patchrejected when the declared namespaced spelling wasdefault__apply_patchns.namealongsidens__nameAdditional context
Prompt-level guidance in
AGENTS.mdwas added to tell non-OpenAI models to use only request-declared tools and exact tool names, including explicitly avoiding invented prefixes such asdefault.. The failure still occurs, suggesting thedefault.prefix may be introduced by the model/provider tool-call serialization path rather than being reliably preventable through prompt instructions alone.Checks
view_image -> default.view_imagecase from the namespaced spelling fix in fix(proxy): accept dotted ns.name tool echo alongside ns__name #3403.