Custom OpenAI-compatible providers don't send tools parameter for function calling
Summary
OpenClaw doesn't send the tools parameter to custom OpenAI-compatible API providers (e.g., SiliconFlow, together.ai) even when those providers fully support function calling according to OpenAI API spec. This prevents tool execution on otherwise compatible models.
Environment
- OpenClaw Version: 2026.2.2-3
- Provider: SiliconFlow (custom openai-completions provider)
- Model: deepseek-ai/DeepSeek-V3
- Configuration Type: Custom provider with
"api": "openai-completions"
Expected Behavior
When using a custom OpenAI-compatible provider that supports function calling:
- OpenClaw should send the
tools parameter in API requests
- The model should receive tool definitions and return
tool_calls in responses
- OpenClaw should execute the requested tools
Actual Behavior
- OpenClaw does NOT send the
tools parameter to custom providers
- Models output JSON text instead of structured
tool_calls
- Tools are never executed
Configuration Used
{
"models": {
"providers": {
"siliconflow": {
"baseUrl": "https://api.siliconflow.cn/v1",
"apiKey": "sk-***",
"api": "openai-completions",
"models": [
{
"id": "deepseek-ai/DeepSeek-V3",
"name": "DeepSeek V3",
"reasoning": false,
"contextWindow": 65536,
"maxTokens": 8192
}
]
}
}
},
"agents": {
"defaults": {
"model": {
"primary": "siliconflow/deepseek-ai/DeepSeek-V3"
}
}
},
"tools": {
"web": {
"search": {
"apiKey": "BSA***"
}
}
}
}
Steps to Reproduce
- Configure a custom OpenAI-compatible provider (SiliconFlow, together.ai, etc.)
- Enable web_search tool with valid Brave API key
- Ask the agent to search for information: "查询理想汽车股价"
- Observe that the model outputs JSON text like
{"name": "web_search", "arguments": {...}} instead of executing the tool
Verification That Provider Supports Function Calling
Direct API test proves the provider DOES support function calling:
curl https://api.siliconflow.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-***" \
-d '{
"model": "deepseek-ai/DeepSeek-V3",
"messages": [{"role": "user", "content": "查询北京天气"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}'
Response (correctly returns tool_calls):
{
"choices": [{
"message": {
"role": "assistant",
"content": "",
"tool_calls": [{
"id": "019c2955cdbef92d6b516011cd3ae407",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"北京\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}
Root Cause Analysis
After investigating OpenClaw's source code in @mariozechner/pi-ai/dist/providers/openai-completions.js:
if (context.tools) {
params.tools = convertTools(context.tools, compat);
params.tool_choice = options.toolChoice;
}
The code DOES support sending tools, but context.tools is empty for custom providers.
OpenClaw appears to use a capabilities system (similar to supportsReasoning, supportsVision) to determine which features each model supports. Custom providers don't have capability metadata, so OpenClaw doesn't populate context.tools even when tools are available.
Impact
- Users cannot use cost-effective Chinese API providers (SiliconFlow, Volcengine, etc.) with tool calling
- Restricts users to only official/known providers despite API compatibility
- Contradicts the purpose of supporting
openai-completions API type
Proposed Solutions
Option 1: Add capability override in model config
{
"models": [{
"id": "deepseek-ai/DeepSeek-V3",
"capabilities": {
"supportsTools": true,
"supportsVision": false,
"supportsReasoning": false
}
}]
}
Option 2: Default to enabling tools for openai-completions providers
Since openai-completions is an API standard, assume tool support by default unless explicitly disabled.
Option 3: Provider-level capability declaration
{
"providers": {
"siliconflow": {
"api": "openai-completions",
"capabilities": {
"tools": true,
"vision": false,
"reasoning": false
}
}
}
}
Workaround
Currently, the only workaround is to use officially supported providers (OpenAI, DeepSeek official API), which may not be cost-effective or accessible in all regions.
Additional Context
- This issue was discovered through extensive debugging including strace, API testing, and source code analysis
- Multiple models confirmed to support function calling: DeepSeek-V3, Qwen2.5-Coder-32B, QwQ-32B
- The issue is specific to OpenClaw's capability detection, not the underlying pi-ai library
References
Custom OpenAI-compatible providers don't send
toolsparameter for function callingSummary
OpenClaw doesn't send the
toolsparameter to custom OpenAI-compatible API providers (e.g., SiliconFlow, together.ai) even when those providers fully support function calling according to OpenAI API spec. This prevents tool execution on otherwise compatible models.Environment
"api": "openai-completions"Expected Behavior
When using a custom OpenAI-compatible provider that supports function calling:
toolsparameter in API requeststool_callsin responsesActual Behavior
toolsparameter to custom providerstool_callsConfiguration Used
{ "models": { "providers": { "siliconflow": { "baseUrl": "https://api.siliconflow.cn/v1", "apiKey": "sk-***", "api": "openai-completions", "models": [ { "id": "deepseek-ai/DeepSeek-V3", "name": "DeepSeek V3", "reasoning": false, "contextWindow": 65536, "maxTokens": 8192 } ] } } }, "agents": { "defaults": { "model": { "primary": "siliconflow/deepseek-ai/DeepSeek-V3" } } }, "tools": { "web": { "search": { "apiKey": "BSA***" } } } }Steps to Reproduce
{"name": "web_search", "arguments": {...}}instead of executing the toolVerification That Provider Supports Function Calling
Direct API test proves the provider DOES support function calling:
Response (correctly returns
tool_calls):{ "choices": [{ "message": { "role": "assistant", "content": "", "tool_calls": [{ "id": "019c2955cdbef92d6b516011cd3ae407", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"北京\"}" } }] }, "finish_reason": "tool_calls" }] }Root Cause Analysis
After investigating OpenClaw's source code in
@mariozechner/pi-ai/dist/providers/openai-completions.js:The code DOES support sending tools, but
context.toolsis empty for custom providers.OpenClaw appears to use a
capabilitiessystem (similar tosupportsReasoning,supportsVision) to determine which features each model supports. Custom providers don't have capability metadata, so OpenClaw doesn't populatecontext.toolseven when tools are available.Impact
openai-completionsAPI typeProposed Solutions
Option 1: Add capability override in model config
{ "models": [{ "id": "deepseek-ai/DeepSeek-V3", "capabilities": { "supportsTools": true, "supportsVision": false, "supportsReasoning": false } }] }Option 2: Default to enabling tools for openai-completions providers
Since
openai-completionsis an API standard, assume tool support by default unless explicitly disabled.Option 3: Provider-level capability declaration
{ "providers": { "siliconflow": { "api": "openai-completions", "capabilities": { "tools": true, "vision": false, "reasoning": false } } } }Workaround
Currently, the only workaround is to use officially supported providers (OpenAI, DeepSeek official API), which may not be cost-effective or accessible in all regions.
Additional Context
References