Handle F# optional parameters in AIFunctionFactory schema generation#7439
Merged
eiriktsarpalis merged 1 commit intomainfrom Mar 30, 2026
Merged
Handle F# optional parameters in AIFunctionFactory schema generation#7439eiriktsarpalis merged 1 commit intomainfrom
eiriktsarpalis merged 1 commit intomainfrom
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Updates AIFunctionFactory schema generation and invocation so that F# optional parameters (compiled with Microsoft.FSharp.Core.OptionalArgumentAttribute, but not ParameterInfo.IsOptional) are treated as optional with a null default, and adds an F# test project to validate the behavior.
Changes:
- Extend default-value detection to treat F#
?paramoptional parameters (andIsOptionalparameters without a declared default) as having an effective default ofnull. - Add a new F# test project validating schema
required/defaultbehavior and invocation with omitted/provided optional args.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/Libraries/Microsoft.Extensions.AI.Abstractions.FSharp.Tests/Microsoft.Extensions.AI.Abstractions.FSharp.Tests.fsproj | Introduces a new F# test project to cover F# optional parameter behavior. |
| test/Libraries/Microsoft.Extensions.AI.Abstractions.FSharp.Tests/FSharpOptionalParameterTests.fs | Adds F# tests validating schema generation and invocation with F# optional parameters. |
| src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs | Updates default-value inference to recognize F# optional parameters via OptionalArgumentAttribute. |
fb878fb to
a25d7f2
Compare
F# optional parameters declared with the ?param syntax are compiled with Microsoft.FSharp.Core.OptionalArgumentAttribute but do NOT set the ParameterAttributes.Optional flag, causing ParameterInfo.IsOptional to return false. This meant AIFunctionFactory treated them as required, producing incorrect JSON schemas and throwing ArgumentException when the parameter was omitted during invocation. Updated TryGetEffectiveDefaultValue to detect OptionalArgumentAttribute by name (avoiding a hard dependency on FSharp.Core) and treat such parameters as having a null default value. A fast pre-check on the parameter type (FSharpOption) avoids attribute scanning for non-F# parameters. Also added handling for parameterInfo.IsOptional to cover COM interop [Optional] parameters. Added an F# test project (Microsoft.Extensions.AI.Abstractions.FSharp.Tests) that validates schema generation and invocation for F# optional parameters. Updated eng/build.proj to include .fsproj test projects. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
a25d7f2 to
438a564
Compare
stephentoub
approved these changes
Mar 30, 2026
jozkee
pushed a commit
to jozkee/extensions
that referenced
this pull request
Apr 3, 2026
…otnet#7439) F# optional parameters declared with the ?param syntax are compiled with Microsoft.FSharp.Core.OptionalArgumentAttribute but do NOT set the ParameterAttributes.Optional flag, causing ParameterInfo.IsOptional to return false. This meant AIFunctionFactory treated them as required, producing incorrect JSON schemas and throwing ArgumentException when the parameter was omitted during invocation. Updated TryGetEffectiveDefaultValue to detect OptionalArgumentAttribute by name (avoiding a hard dependency on FSharp.Core) and treat such parameters as having a null default value. A fast pre-check on the parameter type (FSharpOption) avoids attribute scanning for non-F# parameters. Also added handling for parameterInfo.IsOptional to cover COM interop [Optional] parameters. Added an F# test project (Microsoft.Extensions.AI.Abstractions.FSharp.Tests) that validates schema generation and invocation for F# optional parameters. Updated eng/build.proj to include .fsproj test projects. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
F# optional parameters declared with the
?paramsyntax are compiled withMicrosoft.FSharp.Core.OptionalArgumentAttributebut do not set theParameterAttributes.Optionalflag, soParameterInfo.IsOptionalreturnsfalse. This causedAIFunctionFactoryto treat them as required parameters, producing incorrect JSON schemas and throwingArgumentExceptionwhen the parameter was omitted during invocation.Changes
Fix (
AIJsonUtilities.Schema.Create.cs)Updated
TryGetEffectiveDefaultValueto:parameterInfo.IsOptional(covers COM interop[Optional]parameters)OptionalArgumentAttributeby name viaIsFSharpOptionalParameter()-- avoids a hard dependency on FSharp.Coretruewith anulldefault value (equivalent toFSharpOption.None)This single change fixes both schema generation (parameter no longer in the
requiredarray, gets"default": null) and invocation (marshaller returnsnullinstead of throwing).New F# test project
Added
test/Libraries/Microsoft.Extensions.AI.Abstractions.FSharp.Tests/with 6 tests covering:"default": nullfor optional parametersTest Results
Context
Addresses modelcontextprotocol/csharp-sdk#1476 (comment) -- F# MCP tool methods with optional parameters threw errors when clients omitted those parameters.
Microsoft Reviewers: Open in CodeFlow