Skip to content

Commit fb5e102

Browse files
committed
.NET: accept JSON string inline skill args
1 parent edcc786 commit fb5e102

2 files changed

Lines changed: 62 additions & 7 deletions

File tree

dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillScript.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,42 @@ private static AIFunctionArguments ConvertToFunctionArguments(JsonElement? argum
9292
return [];
9393
}
9494

95-
if (arguments.Value.ValueKind != JsonValueKind.Object)
95+
JsonDocument? parsedStringArguments = null;
96+
var argumentElement = arguments.Value;
97+
98+
if (argumentElement.ValueKind == JsonValueKind.String)
9699
{
97-
throw new InvalidOperationException(
98-
$"Inline skill scripts expect arguments as a JSON object but received a JSON element of kind '{arguments.Value.ValueKind}'.");
100+
string? rawArguments = argumentElement.GetString();
101+
try
102+
{
103+
parsedStringArguments = JsonDocument.Parse(rawArguments ?? string.Empty);
104+
argumentElement = parsedStringArguments.RootElement;
105+
}
106+
catch (JsonException ex)
107+
{
108+
throw new InvalidOperationException("Inline skill scripts received arguments as a JSON string, but the string did not contain valid JSON.", ex);
109+
}
99110
}
100111

101-
var dict = new Dictionary<string, object?>();
102-
foreach (var property in arguments.Value.EnumerateObject())
112+
if (argumentElement.ValueKind != JsonValueKind.Object)
103113
{
104-
dict[property.Name] = property.Value;
114+
throw new InvalidOperationException(
115+
$"Inline skill scripts expect arguments as a JSON object but received a JSON element of kind '{argumentElement.ValueKind}'.");
105116
}
106117

107-
return new AIFunctionArguments(dict);
118+
try
119+
{
120+
var dict = new Dictionary<string, object?>();
121+
foreach (var property in argumentElement.EnumerateObject())
122+
{
123+
dict[property.Name] = parsedStringArguments is null ? property.Value : property.Value.Clone();
124+
}
125+
126+
return new AIFunctionArguments(dict);
127+
}
128+
finally
129+
{
130+
parsedStringArguments?.Dispose();
131+
}
108132
}
109133
}

dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentSkills/AgentInlineSkillScriptTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,37 @@ public async Task RunAsync_WithParameters_PassesArgumentsAsync()
4343
Assert.Equal(10, int.Parse(result?.ToString()!));
4444
}
4545

46+
[Fact]
47+
public async Task RunAsync_WithJsonStringObjectArguments_PassesArgumentsAsync()
48+
{
49+
// Arrange
50+
var script = new AgentInlineSkillScript("add", (int a, int b) => a + b);
51+
var skill = new AgentInlineSkill("calc-skill", "Calc.", "Instructions.");
52+
using var argsDoc = JsonDocument.Parse("\"{\\\"a\\\":3,\\\"b\\\":7}\"");
53+
var args = argsDoc.RootElement;
54+
55+
// Act
56+
var result = await script.RunAsync(skill, args, null, CancellationToken.None);
57+
58+
// Assert
59+
Assert.Equal(10, int.Parse(result?.ToString()!));
60+
}
61+
62+
[Fact]
63+
public async Task RunAsync_WithInvalidJsonStringArguments_ThrowsInvalidOperationExceptionAsync()
64+
{
65+
// Arrange
66+
var script = new AgentInlineSkillScript("noop", () => "ok");
67+
var skill = new AgentInlineSkill("test-skill", "Test.", "Instructions.");
68+
using var argsDoc = JsonDocument.Parse("\"not json\"");
69+
var args = argsDoc.RootElement;
70+
71+
// Act & Assert
72+
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
73+
() => script.RunAsync(skill, args, null, CancellationToken.None));
74+
Assert.Contains("did not contain valid JSON", ex.Message);
75+
}
76+
4677
[Fact]
4778
public void ParametersSchema_NoParameters_ReturnsSchema()
4879
{

0 commit comments

Comments
 (0)