Skip to content

OCI Generative AI tool_call_id not found because AIMessage.tool_calls are ignored #42

@jbrown9513

Description

@jbrown9513

Title:
Tool calling: toolCallId not found in 'toolCalls' of previous message when AIMessage.tool_calls is set but additional_kwargs["tool_calls"] is not
Affected package/module:
langchain-oci → chat_models/oci_generative_ai.py messages_to_oci_params

Setup:
chatgpt-5 model
Langchain React Agent
Single MCP tool, called by Agent.

Error:
Error in user chat: {'target_service': 'generative_ai_inference', 'status': 400, 'code': '400', 'opc-request-id': 'message': "Invalid parameter: 'toolCallId' of 'call_EsOkIHqkAwxiuLEifKYpFuiz' not found in 'toolCalls' of previous message.", 'operation_name': 'chat', 'timestamp': '2025-10-10T16:57:01.747572+00:00', 'client_version': 'Oracle-PythonSDK/2.159.1', 'request_endpoint': 'POST https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/chat', 'logging_tips': 'To get more info on the failing request, refer to https://docs.oracle.com/en-us/iaas/tools/python/latest/logging.html for ways to log the request/response details.', 'troubleshooting_tips': "See https://docs.oracle.com/iaas/Content/API/References/apierrors.htm#apierrors_400__400_400 for more information about resolving this error. Also see https://docs.oracle.com/iaas/api/#/en/generative-ai-inference/20231130/ChatResult/Chat for details on this operation's requirements. If you are unable to resolve this generative_ai_inference issue, please contact Oracle support and provide them this full error message."}

Root Cause:
Class: GenericProvider
Function: messages_to_oci_params

The function only forwards tool calls when message.additional_kwargs.get("tool_calls") is truthy, ignoring the standard AIMessage.tool_calls field. This drops the assistant’s toolCalls from the prior message, so the next tool message’s tool_call_id cannot be resolved by OCI.

for message in messages: role = self.get_role(message) if isinstance(message, ToolMessage): # For tool messages, wrap the content in a text content object. tool_content = [ self.oci_chat_message_text_content(text=str(message.content)) ] if message.tool_call_id: oci_message = self.oci_chat_message[role]( content=tool_content, tool_call_id=message.tool_call_id, ) else: oci_message = self.oci_chat_message[role](content=tool_content) elif isinstance(message, AIMessage) and message.additional_kwargs.get( "tool_calls" ... ):
The last line should be something like:
if isinstance(message, AIMessage) and (message.tool_calls or message.additional_kwargs.get("tool_calls")):

I have verified the fix locally, and will post a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions