Skip to content

Bug: Tool Calling Conversations Fail Due to Missing tool_call_id in Tool Messages #1

Description

@DevBhuyan

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:

  1. Preserve tool_call_id fields from upstream requests.
  2. Validate tool message structures before provider dispatch.
  3. 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

  1. Configure OpenBalancer as a custom OpenAI-compatible endpoint.
  2. Connect GitHub Copilot Chat (GHCP).
  3. Start a conversation that triggers one or more tool calls.
  4. Continue the conversation for several turns.
  5. Observe provider failures once tool history is included.

Environment

  • OpenBalancer: Multi-user branch

  • Deployment: Railway / Local

  • Providers tested:

    • OpenRouter
    • Groq
    • Cerebras
    • HuggingFace
  • Client:

    • GitHub Copilot Chat (VS Code)

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions