Bug: Tool Calling Conversations Fail Due to Missing tool_call_id in Tool Messages
Summary
OpenBalancer currently fails when handling long-running conversations that include tool calls (e.g. GitHub Copilot Chat / GHCP agent workflows).
The issue does not affect normal chat completions. Short conversations and non-tool-calling requests work correctly.
However, once the conversation contains tool invocation history, downstream providers reject the request because tool messages are missing the required tool_call_id field.
Impact
This prevents reliable use of:
- GitHub Copilot Chat (GHCP)
- Agentic workflows
- Multi-step tool execution loops
- Long-running conversations containing tool history
As a result, OpenBalancer is currently not fully compatible with OpenAI-style tool calling conversations.
Observed Behavior
When GHCP sends a conversation containing tool messages, OpenBalancer forwards the request to multiple providers.
All providers fail with validation errors.
Groq
{
"error": {
"message": "'messages.14' : for 'role:tool' the following must be satisfied [('messages.14.tool_call_id' : property 'tool_call_id' is missing)]",
"type": "invalid_request_error"
}
}
HuggingFace
{
"message": "messages.14.tool.tool_call_id: Field required",
"type": "invalid_request_error",
"code": "wrong_api_format"
}
Cerebras
{
"message": "messages.14.tool.tool_call_id: Field required",
"type": "invalid_request_error",
"code": "wrong_api_format"
}
Additional Provider Error
OpenRouter also fails, but for a different reason:
{
"code": 402,
"message": "This request requires more credits, or fewer max_tokens."
}
This appears unrelated to the schema issue and is likely caused by large requested output lengths.
Expected Behavior
Tool messages should preserve the OpenAI Chat Completions format.
Example:
{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "..."
}
When forwarding requests, OpenBalancer should:
- Preserve
tool_call_id fields from upstream requests.
- Validate tool message structures before provider dispatch.
- Ensure compatibility with OpenAI-compatible providers that enforce tool schema validation.
Suspected Root Cause
Somewhere in the request normalization / provider translation layer, tool messages appear to lose their associated tool_call_id.
The resulting payload contains:
{
"role": "tool",
"content": "..."
}
instead of:
{
"role": "tool",
"tool_call_id": "call_xyz",
"content": "..."
}
Providers that strictly validate OpenAI tool-calling semantics reject the request.
Reproduction
- Configure OpenBalancer as a custom OpenAI-compatible endpoint.
- Connect GitHub Copilot Chat (GHCP).
- Start a conversation that triggers one or more tool calls.
- Continue the conversation for several turns.
- Observe provider failures once tool history is included.
Environment
Possible Areas to Investigate
- Request normalization pipeline
- Message schema translation
- Tool call serialization/deserialization
- Provider adapter implementations
- OpenAI-compatible request validation layer
Help Wanted
Contributions are welcome. This issue is likely a protocol compatibility bug related to OpenAI tool-calling message handling.
Bug: Tool Calling Conversations Fail Due to Missing
tool_call_idin Tool MessagesSummary
OpenBalancer currently fails when handling long-running conversations that include tool calls (e.g. GitHub Copilot Chat / GHCP agent workflows).
The issue does not affect normal chat completions. Short conversations and non-tool-calling requests work correctly.
However, once the conversation contains tool invocation history, downstream providers reject the request because tool messages are missing the required
tool_call_idfield.Impact
This prevents reliable use of:
As a result, OpenBalancer is currently not fully compatible with OpenAI-style tool calling conversations.
Observed Behavior
When GHCP sends a conversation containing tool messages, OpenBalancer forwards the request to multiple providers.
All providers fail with validation errors.
Groq
{ "error": { "message": "'messages.14' : for 'role:tool' the following must be satisfied [('messages.14.tool_call_id' : property 'tool_call_id' is missing)]", "type": "invalid_request_error" } }HuggingFace
{ "message": "messages.14.tool.tool_call_id: Field required", "type": "invalid_request_error", "code": "wrong_api_format" }Cerebras
{ "message": "messages.14.tool.tool_call_id: Field required", "type": "invalid_request_error", "code": "wrong_api_format" }Additional Provider Error
OpenRouter also fails, but for a different reason:
{ "code": 402, "message": "This request requires more credits, or fewer max_tokens." }This appears unrelated to the schema issue and is likely caused by large requested output lengths.
Expected Behavior
Tool messages should preserve the OpenAI Chat Completions format.
Example:
{ "role": "tool", "tool_call_id": "call_abc123", "content": "..." }When forwarding requests, OpenBalancer should:
tool_call_idfields from upstream requests.Suspected Root Cause
Somewhere in the request normalization / provider translation layer, tool messages appear to lose their associated
tool_call_id.The resulting payload contains:
{ "role": "tool", "content": "..." }instead of:
{ "role": "tool", "tool_call_id": "call_xyz", "content": "..." }Providers that strictly validate OpenAI tool-calling semantics reject the request.
Reproduction
Environment
OpenBalancer: Multi-user branch
Deployment: Railway / Local
Providers tested:
Client:
Possible Areas to Investigate
Help Wanted
Contributions are welcome. This issue is likely a protocol compatibility bug related to OpenAI tool-calling message handling.