Skip to content

Conversation

andrewm4894
Copy link

@andrewm4894 andrewm4894 commented Oct 3, 2025

Problem

Tool calls in input messages were being dropped during formatting, causing loss of conversation context when passing multi-turn conversations with tool usage to OpenAI's API.

Solution

Added proper handling to preserve tool_calls in input messages by:

  • Creating a _format_tool_calls_to_content() helper function that handles both object-based tool calls (from API responses) and dict-based tool calls (from user input)
  • Updating format_openai_input() to detect and preserve tool calls alongside text content
  • Maintaining backwards compatibility by keeping simple string content as-is (no behavior change for existing code)

Changes

  • Helper function handles both API response objects and dict formats defensively
  • Input messages with tool calls are formatted into structured content lists
  • Multimodal content (images, etc.) continues to work correctly
  • Simple text-only messages remain unchanged for backwards compatibility

Testing

  • All existing tests pass (16/16)
  • Added test_input_messages_with_tool_calls() to verify tool call preservation in multi-turn conversations
  • Linter checks pass

Tested locally by sending some events using the fix branch of posthog-python:

image

Previously the tool calls were being dropped in the assistant input messages that used tool_calls.

(slack thread here for further context/background)

- Add helper function to format tool calls from both API responses and input messages
- Handle multimodal content and tool calls in structured format
- Maintain backwards compatibility for simple string content
- Add test coverage for messages with tool calls
@andrewm4894 andrewm4894 marked this pull request as ready for review October 3, 2025 22:46
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 1245 to 1249
# Third message should be the tool response
assert props["$ai_input"][2] == {
"role": "tool",
"content": "72 degrees and sunny",
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Missing tool_call_id field validation in the tool message assertion - should verify this field is preserved

Suggested change
# Third message should be the tool response
assert props["$ai_input"][2] == {
"role": "tool",
"content": "72 degrees and sunny",
}
# Third message should be the tool response
assert props["$ai_input"][2] == {
"role": "tool",
"tool_call_id": "call_abc123",
"content": "72 degrees and sunny",
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/test/ai/openai/test_openai.py
Line: 1245:1249

Comment:
**style:** Missing `tool_call_id` field validation in the tool message assertion - should verify this field is preserved

```suggestion
        # Third message should be the tool response
        assert props["$ai_input"][2] == {
            "role": "tool",
            "tool_call_id": "call_abc123",
            "content": "72 degrees and sunny",
        }
```

How can I resolve this? If you propose a fix, please make it concise.

- Extract and preserve tool_call_id from input messages
- Keep simple string content for tool messages (with optional tool_call_id)
- Update test to verify tool_call_id is preserved for tool responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@Radu-Raicea Radu-Raicea requested a review from a team October 6, 2025 12:17
"content": content_value,
}
# Preserve tool_call_id for tool role messages
if tool_call_id:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a tool_call_id if we don't have any tool_calls?

"content": content_items,
}
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to change anything for the responses API format?

}
)
content.extend(
_format_tool_calls_to_content(choice.message.tool_calls)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes it for the chat completions response API format. What about the responses API format?

assert props["$ai_tools"] == tools


def test_input_messages_with_tool_calls(mock_client, mock_openai_response):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think that there are other tests that are testing things with tool_calls? Maybe we can just put some extra assertions there?

We should probably also test some of the edge cases that you have in your code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants