Skip to content

Conversation

@BenjaminDavidPinter
Copy link
Contributor

@BenjaminDavidPinter BenjaminDavidPinter commented Sep 24, 2025

Fixes Issue 552

I'm actually surprised this hasn't come up more often, the FileSearch/CodeGen combo allows for really simple data analysis.

Anyway; I discovered the root cause, and here what I changed.

Root cause

The file_search tool definition in the spec (models.tsp) is shared between Assistant creation and Message tool serialization.

The generated serializer (FileSearchToolDefinition.Serialization.cs) force emits a "file_search" object when serializing the tool, which ends up injected into the message attachment payload (an unsupported property for that request).

Solution

I did not edit the generated FileSearchToolDefinition.Serialization.cs. Instead I intercepted message-level tool serialization in MessageCreationAttachment.cs.

I buffer the generated JSON for each tool, parse it, remove any "file_search" property, then write the cleaned JSON into the message attachment payload. This prevents the unwanted property from being sent.

Why this approach: generated code can’t be changed directly, so post-processing the generated output in the custom serializer is the safest fix that keeps generated behavior intact while preventing invalid request payloads.

Testing

I was able to recreate the issue with the added test.
After implementing the fix, the test passes.

All tests with Category "Assistant" pass.

Recommendation

Split the spec definition so assistant-level tool properties (like file_search) are not shared with message-level tool representations. Use separate types for tools used in assistant creation vs tools embedded in messages, or mark server-only/readOnly fields so the generator will not emit them into request models. If the Responses API already addresses this separation, consider aligning the assistants spec with that approach.

@jsquire
Copy link
Collaborator

jsquire commented Oct 1, 2025

@BenjaminDavidPinter: Thanks very much for your contribution and your interest in improving the OpenAI developer experience. We appreciate the efforts that you put into investigating and writing this up as well. It sounds like the long-term solution would be to fix the spec such that the models are distinct. In the short-term, I think your approach here makes sense.

I'm going to ask @ShivangiReja and @christothes to add some additional perspective.

@jsquire jsquire requested a review from christothes October 1, 2025 17:31
@jsquire
Copy link
Collaborator

jsquire commented Oct 1, 2025

@joseharriaga: Would you please take a look at the investigation write-up here and then let's sync on thoughts to push upstream for spec changes?

@BenjaminDavidPinter
Copy link
Contributor Author

@jsquire thanks! I'll fix up the conflicts when I get home tonight, and we can wrap this one up (for now), until we get those models split out in the spec.

@jsquire
Copy link
Collaborator

jsquire commented Oct 3, 2025

Thanks, @BenjaminDavidPinter! I'm going to run the tests and then wait for Jose to get back for final approval.

using OpenAI.Tests.Utility;
using OpenAI.Tests.Utility;
using OpenAI.VectorStores;
using OpenAI.VectorStores;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you fix the duplicated namespaces?

{
// First, we need to upload a simple test file.
OpenAIFileClient fileClient = GetTestClient<OpenAIFileClient>(TestScenario.Files);
OpenAIFile testFile = fileClient.UploadFile(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Switch to the async version of this method: UploadFileAsync


AssistantClient client = GetTestClient();

var thread = client.CreateThread();
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Switch to the async version of this method: CreateThreadAsync.
  2. Then call Validate(thread);

AssistantClient client = GetTestClient();

var thread = client.CreateThread();
var assistant = client.CreateAssistant("gpt-4o-mini");
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Switch to the async version of this method: CreateAssistantAsync
  2. Then call Validate(assistant);

var assistant = client.CreateAssistant("gpt-4o-mini");

var message = await client.CreateMessageAsync(
thread.Value.Id,
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Add indentation.

new MessageCreationAttachment(testFile.Id, new List<ToolDefinition>() { ToolDefinition.CreateFileSearch() }),
new MessageCreationAttachment(testFile.Id, new List<ToolDefinition>() { ToolDefinition.CreateCodeInterpreter() })
]
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Call Validate(message);

@joseharriaga
Copy link
Collaborator

I approved the PR. Just added a few comments. 🙂

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.

3 participants