diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillScript.cs b/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillScript.cs index c0abc73252..30c6053a80 100644 --- a/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillScript.cs +++ b/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillScript.cs @@ -92,18 +92,50 @@ private static AIFunctionArguments ConvertToFunctionArguments(JsonElement? argum return []; } - if (arguments.Value.ValueKind != JsonValueKind.Object) + var argumentElement = arguments.Value; + using var parsedStringArguments = ParseStringArguments(argumentElement); + if (parsedStringArguments is not null) + { + argumentElement = parsedStringArguments.RootElement; + } + + if (argumentElement.ValueKind != JsonValueKind.Object) { throw new InvalidOperationException( - $"Inline skill scripts expect arguments as a JSON object but received a JSON element of kind '{arguments.Value.ValueKind}'."); + $"Inline skill scripts expect arguments as a JSON object but received a JSON element of kind '{argumentElement.ValueKind}'."); } var dict = new Dictionary(); - foreach (var property in arguments.Value.EnumerateObject()) + foreach (var property in argumentElement.EnumerateObject()) { - dict[property.Name] = property.Value; + dict[property.Name] = parsedStringArguments is null ? property.Value : property.Value.Clone(); } return new AIFunctionArguments(dict); } + + private static JsonDocument? ParseStringArguments(JsonElement arguments) + { + if (arguments.ValueKind != JsonValueKind.String) + { + return null; + } + + var json = arguments.GetString(); + if (string.IsNullOrWhiteSpace(json)) + { + return null; + } + + try + { + return JsonDocument.Parse(json); + } + catch (JsonException ex) + { + throw new InvalidOperationException( + "Inline skill scripts received arguments as a JSON string, but the string did not contain valid JSON.", + ex); + } + } } diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentSkills/AgentInlineSkillScriptTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentSkills/AgentInlineSkillScriptTests.cs index 85521ba4a9..9185247cd8 100644 --- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentSkills/AgentInlineSkillScriptTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentSkills/AgentInlineSkillScriptTests.cs @@ -43,6 +43,22 @@ public async Task RunAsync_WithParameters_PassesArgumentsAsync() Assert.Equal(10, int.Parse(result?.ToString()!)); } + [Fact] + public async Task RunAsync_WithStringEncodedObjectArguments_PassesArgumentsAsync() + { + // Arrange + var script = new AgentInlineSkillScript("add", (int a, int b) => a + b); + var skill = new AgentInlineSkill("calc-skill", "Calc.", "Instructions."); + using var argsDoc = JsonDocument.Parse("\"{\\\"a\\\":3,\\\"b\\\":7}\""); + var args = argsDoc.RootElement; + + // Act + var result = await script.RunAsync(skill, args, null, CancellationToken.None); + + // Assert + Assert.Equal(10, int.Parse(result?.ToString()!)); + } + [Fact] public void ParametersSchema_NoParameters_ReturnsSchema() {