-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat(agent): make responseFormat.strict configurable to support optional tool parameters #9535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(agent): make responseFormat.strict configurable to support optional tool parameters #9535
Conversation
|
|
Hi! Please let me know if any changes are needed. |
|
Hi, thanks for your PR! I will make some time later to go through it fully. Some initial comments:
|
|
Thanks a lot for the detailed review! Really appreciate the guidance.
I'll update the PR accordingly and push a revised version soon. |
cdf9827 to
c6a64e2
Compare
|
Hi! Iβve pushed the updated changes, keeping the PR focused and applying the strict logic update in the responses API as suggested. |
|
Small note in general: make sure to follow contributing guidelines. (linting, formatting, testing, ...). |
|
Thank you sir for the feedback i will follow the contributing guidelines from now. |
| include: options?.include, | ||
| tools: options?.tools?.length | ||
| ? this._reduceChatOpenAITools(options.tools, { | ||
| stream: this.streaming, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow the steps here https://github.com/langchain-ai/langchainjs/blob/main/CONTRIBUTING.md#linting, to properly format/lint your code :)
| strict = options.strict; | ||
| } else if (this.supportsStrictToolCalling !== undefined) { | ||
| } | ||
| if (strict === undefined && this.supportsStrictToolCalling !== undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you try to run the tests? I would be interested to know if this is a breaking change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution @Nitinref! Two requests:
- can we resolve the formatting?
pnpm run format:check:fixshould do that for you. - Can we have some unit tests for this?
533f3c9 to
5d0249d
Compare
|
All requested changes have been addressed, the branch is updated with main, |
|
@MartijnLeplae any last thoughts? |
|
Yes actually @christian-bromann. Am I right that the change does not actually do anything? Why did you add this extra check @Nitinref? |
|
Thanks for the clarification @MartijnLeplae const useStrict = And pass strict: useStrict to the OpenAI tool definition. |
|
I think your reasoning is not completely right @Nitinref Writing const useStrict = options?.strict ?? options?.supportsStrictToolCalling ?? false;Is not the same as saying overriding is possible. The Perhaps to clarify more, my initial issue is that the langchainjs/libs/langchain/src/agents/nodes/AgentNode.ts Lines 839 to 849 in 8a77e9a
therefore options?.strict is never undefined or null when using agentNode, unless the agentNode code would be changed. What do you think @christian-bromann ? |
|
@MartijnLeplae since AgentNode always sets strict: true, options.strict never ends up undefined, so the fallback to supportsStrictToolCalling can't actually happen. I missed that connection earlier.Iβll update the AgentNode logic so user-provided strict truly overrides, and only fall back when it's not set. Will push the fix shortly. Thanks for catching this! |
β¦rategy and update strict tool-calling tests
|
@Nitinref @MartijnLeplae I just realized that this conflicts with a PR I put up last week that would allow to overwrite |
|
@christian-bromann Thanks for pointing that out! |
Let's do that, I am happy to close out my PR if we can incorporate that idea here as well. Let's recap: by default we maintain a strict type validation. User can disable that by setting it explicitly to // json schema / using default strategy
const agent = createAgent({
model: new ChatOpenAI({ model: "gpt-4o-mini" }),
tools: [myToolWithOptionalParams],
responseFormat: {
// your output schema...
strict: false,
},
});// tool/provider strategy explicitly defined
const agent = createAgent({
model: new ChatOpenAI({ model: "gpt-4o-mini" }),
tools: [myToolWithOptionalParams],
responseFormat: toolStrategy({ // or providerStrategy
schema: z.object({ ... }), // or json schema
strict: false
}),
});Right? |
|
@christian-bromann Thanks for the clarification!
Once I push the update, we can fully replace the logic from your PR. |
|
I've updated the PR to move strict resolution entirely into AgentNode as suggested.
|
How do you set responseFormat: providerStrategy({
schema: z.object({ ... })
strict: false
}) |
|
I can go ahead and merge this change once pipeline passes and then merge my PR after. |
|
@christian-bromann Thanks for the review! Just to clarify β the strict resolution priority you described is already implemented in this PR inside
const resolvedStrict =
preparedOptions?.modelSettings?.strict ??
structuredResponseFormat?.strategy?.strict ??
true; |
|
But it currently doesn't allow to define the strict value for a specific response format strategy, right? |
|
You've outlined this example: which I assume uses JSON schema. But what happens if I want to use a Zod schema? |
|
@Nitinref it seems like the current PR is not complete: ? |
|
Embedding this PR in #9578 |
|
Thanks for the clarification! |

π What this PR does
This patch makes the
strictbehavior ofresponseFormatconfigurable when usingcreateAgent.createAgentalways setstrict: trueinternally β this caused agents using tools or optional parameter schemas to break withinvalid_function_parameters.responseFormat.strict = false, the agent honors it and does not enforce strict validation β enabling use of optional fields or more flexible tool parameter schemas.β Why this matters
strictis omitted, the default remainstrue.π§ What changed
AgentNode.ts,strict: trueis replaced with logic that readsresponseFormat.strictif supplied, else defaults totrue.π§ͺ Verification
Tested locally with real OpenAI model.
Example usage that works with optional tool parameters:
Under this configuration, agent interacts successfully; no
invalid_function_parameterserror β the fix works as intended.strict: falseshould be used consciously β disabling strict validation may reduce safety guarantees (e.g. tool parameter validation).strictor explicitly set it totrue.