fix(ai-proxy): validate model tool support at Router init (fail fast)#1452
fix(ai-proxy): validate model tool support at Router init (fail fast)#1452
Conversation
BREAKING CHANGE: isModelSupportingTools is no longer exported from ai-proxy - Add AIModelNotSupportedError for descriptive error messages - Move model validation from agent.addAi() to Router constructor - Make isModelSupportingTools internal (not exported from index) - Error is thrown immediately at Router init if model doesn't support tools This is a bug fix: validation should happen at proxy initialization, not at the agent level. This ensures consistent behavior regardless of how the Router is instantiated. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The function is only used in Router, so it makes sense to keep it there. This simplifies the provider-dispatcher module and keeps related code together. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move model support checking logic to supported-models.ts for better organization and separation of concerns. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… file - Create supported-models.test.ts with direct function tests - Remove duplicate model list tests from router.test.ts - Simplify index.ts exports using export * pattern Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gpt-3.5-turbo actually supports function calling (tools), verified with real OpenAI API integration tests. - Remove gpt-3.5-turbo and gpt-3.5 from blocklist - Add model-tools-support.integration.test.ts to verify tool support - Update unit tests to reflect correct model support Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Test was only used to investigate which models support tools. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Coverage Impact This PR will not change total coverage. Modified Files with Diff Coverage (3)
🛟 Help
|
Add validation in addAi() to fail fast when an unsupported model is configured, rather than waiting until route creation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| }), | ||
| ).toThrow( | ||
| "Model 'gpt-4' does not support function calling (tools). " + | ||
| 'Please use a compatible model like gpt-4o, gpt-4o-mini, or gpt-4-turbo.', |
There was a problem hiding this comment.
This sentence is removed, not really relevant I guess
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Verify all allowed OpenAI models support tool calls with real API. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Include comprehensive model list from OpenAI types: - GPT-4o family (gpt-4o, gpt-4o-mini, audio/search previews) - GPT-4.1 family (gpt-4.1, mini, nano) - GPT-4 turbo variants - GPT-3.5 family - O-series reasoning models (o1, o3, o4-mini) - Future models (gpt-5.x) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All models verified with real OpenAI API: - gpt-4o, gpt-4o-mini - gpt-4.1, gpt-4.1-mini, gpt-4.1-nano - gpt-4-turbo - gpt-3.5-turbo - o1, o3, o3-mini, o4-mini Removed o1-mini and o1-preview (no longer available). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Export SUPPORTED_OPENAI_MODELS from supported-models.ts and use it in both unit tests and integration tests to ensure consistency. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Verified with real API - all gpt-5 variants exist and support tools: - gpt-5 - gpt-5-mini - gpt-5-nano - gpt-5.1 - gpt-5.2 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove hardcoded SUPPORTED_OPENAI_MODELS list - Fetch models dynamically via openai.models.list() in integration tests - Filter models using isModelSupportingTools() blacklist - Add prefix and pattern-based blacklist for unsupported models - Add explicit error message when tests fail with instructions to update blacklist Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Keep only essential test cases: - Known supported model - Unknown model (allowed by default) - Blacklisted model Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove validateModelSupportsTools call from Agent.addAi() - Validation now happens when AiProxyRouter is instantiated during start() - Update test to use real makeRoutes to trigger validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| @@ -0,0 +1,92 @@ | |||
| /** | |||
There was a problem hiding this comment.
To build the list, I ran integration test with all openai model and if the model returns an error, I added it to the blacklist.
| if (failures.length > 0) { | ||
| const failedModelNames = failures.map(f => f.model).join(', '); | ||
| // eslint-disable-next-line no-console | ||
| console.error( |
There was a problem hiding this comment.
This error message is important because I want to tell to the developper to update the blacklist
- Remove -pro pattern that incorrectly blocked o3-pro - Add error handling for OpenAI models.list() API call - Distinguish infrastructure errors from model compatibility errors in tests - Remove unused validateModelSupportsTools export - Add test for multiple AI configurations validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| const errorMessage = String(error); | ||
|
|
||
| // Infrastructure errors should fail the test immediately | ||
| const isInfrastructureError = |
There was a problem hiding this comment.
avoid false positive to add the model to the blacklist. Not really clean but for a test, i guess it's ok.
…mpletions Models like gpt-5-pro, o1-pro only support v1/responses, not v1/chat/completions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| * | ||
| * @see https://platform.openai.com/docs/guides/function-calling | ||
| */ | ||
| const OPENAI_MODELS_WITHOUT_TOOLS_SUPPORT_PREFIXES = [ |
There was a problem hiding this comment.
can you rename it to be more explicit ? something like
| const OPENAI_MODELS_WITHOUT_TOOLS_SUPPORT_PREFIXES = [ | |
| const OPENAI_MODELS_BLACK_LIST = [ |
- UNSUPPORTED_MODEL_PREFIXES (was OPENAI_MODELS_WITHOUT_TOOLS_SUPPORT_PREFIXES) - UNSUPPORTED_MODEL_PATTERNS (was OPENAI_MODELS_WITHOUT_TOOLS_SUPPORT_PATTERNS) - SUPPORTED_MODEL_OVERRIDES (was OPENAI_MODELS_EXCEPTIONS) Clearer naming reflecting that models must support tool calls. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This will identify models that don't support parallel_tool_calls: false. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…_calls O-series reasoning models (o1, o3, o4) don't support parallel_tool_calls parameter which is required for our use case. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5957438 to
516706d
Compare
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## @forestadmin/ai-proxy [1.4.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/ai-proxy@1.4.0...@forestadmin/ai-proxy@1.4.1) (2026-02-06) ### Bug Fixes * **ai-proxy:** validate model tool support at Router init (fail fast) ([#1452](#1452)) ([adf2efd](adf2efd))
## @forestadmin/agent [1.72.4](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent@1.72.3...@forestadmin/agent@1.72.4) (2026-02-06) ### Bug Fixes * **ai-proxy:** validate model tool support at Router init (fail fast) ([#1452](#1452)) ([adf2efd](adf2efd)) ### Dependencies * **@forestadmin/ai-proxy:** upgraded to 1.4.1 * **@forestadmin/forestadmin-client:** upgraded to 1.37.10 * **@forestadmin/mcp-server:** upgraded to 1.7.6

Summary
agent.addAi()toRouterconstructor (fail fast pattern)AIModelNotSupportedErrordedicated error class for better error messagesisModelSupportingToolsinternal (no longer exported from the package)Breaking Change
isModelSupportingToolsis no longer exported from@forestadmin/ai-proxy. This function was never intended to be public API - validation should be handled internally by the Router.Why this is a bug fix
The validation was incorrectly placed in
agent.addAi()instead ofRouterconstructor. This caused:Routeris used directly (without agent)Test plan
AIModelNotSupportedErrorinrouter.test.tsisModelSupportingToolsinprovider-dispatcher.test.tsagent.test.ts🤖 Generated with Claude Code