diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
index 44d41f319..df2d63132 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
@@ -5,6 +5,9 @@ public class RoutingArgs
[JsonPropertyName("function")]
public string Function { get; set; } = "route_to_agent";
+ [JsonPropertyName("function_args")]
+ public string? FunctionArgs { get; set; }
+
///
/// The reason why you select this function or agent
///
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/HFReasoner.cs b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/HFReasoner.cs
index 7af5e63e9..9f1b5fd52 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/HFReasoner.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/HFReasoner.cs
@@ -51,9 +51,21 @@ public async Task GetNextInstruction(Agent router, string m
}
};
var response = await completion.GetChatCompletions(router, dialogs);
-
var inst = response.Content.JsonContent();
+ if (inst != null)
+ {
+ if (!string.IsNullOrEmpty(response.FunctionName))
+ {
+ inst.Function = response.FunctionName;
+ }
+
+ if (!string.IsNullOrEmpty(response.FunctionArgs))
+ {
+ inst.FunctionArgs = response.FunctionArgs;
+ }
+ }
+
// Fix LLM malformed response
await ReasonerHelper.FixMalformedResponse(_services, inst);
@@ -73,7 +85,14 @@ public async Task AgentExecuting(Agent router, FunctionCallFromLlm inst, R
// Set user content as Planner's question
message.FunctionName = inst.Function;
- message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
+ if (!string.IsNullOrEmpty(inst.FunctionArgs))
+ {
+ message.FunctionArgs = inst.FunctionArgs;
+ }
+ else
+ {
+ message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
+ }
}
return true;
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs
index c71d0f07e..ad2d7370c 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs
@@ -31,6 +31,11 @@ await HookEmitter.Emit(_services, async hook => await hook.OnRouti
}
message.FunctionArgs = JsonSerializer.Serialize(inst);
+ if (!string.IsNullOrEmpty(inst.FunctionArgs))
+ {
+ message.FunctionArgs = inst.FunctionArgs;
+ }
+
if (!string.IsNullOrEmpty(message.FunctionName))
{
var msg = RoleDialogModel.From(message, role: AgentRole.Function);
@@ -56,7 +61,7 @@ await HookEmitter.Emit(_services, async hook => await hook.OnRouti
message = RoleDialogModel.From(message, role: AgentRole.Assistant, content: content);
dialogs.Add(message);
}
- else
+ else if (!message.StopCompletion)
{
var state = _services.GetRequiredService();
var useStreamMsg = state.GetState("use_stream_message");
@@ -71,6 +76,7 @@ await HookEmitter.Emit(_services, async hook => await hook.OnRouti
var response = dialogs.Last();
response.Instruction = inst;
+ response.StopCompletion = message.StopCompletion;
return response;
}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/NaiveReasoner.cs b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/NaiveReasoner.cs
index 39e8be430..5cab06725 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/NaiveReasoner.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/NaiveReasoner.cs
@@ -57,6 +57,18 @@ public async Task GetNextInstruction(Agent router, string m
var response = await completion.GetChatCompletions(router, dialogs);
var inst = (response.FunctionArgs ?? response.Content).JsonContent();
+ if (inst != null)
+ {
+ if (!string.IsNullOrEmpty(response.FunctionName))
+ {
+ inst.Function = response.FunctionName;
+ }
+
+ if (!string.IsNullOrEmpty(response.FunctionArgs))
+ {
+ inst.FunctionArgs = response.FunctionArgs;
+ }
+ }
// Fix LLM malformed response
await ReasonerHelper.FixMalformedResponse(_services, inst);
@@ -68,7 +80,14 @@ public Task AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDia
{
// Set user content as Planner's question
message.FunctionName = inst.Function;
- message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
+ if (!string.IsNullOrEmpty(inst.FunctionArgs))
+ {
+ message.FunctionArgs = inst.FunctionArgs;
+ }
+ else
+ {
+ message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
+ }
return Task.FromResult(true);
}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/OneStepForwardReasoner.cs b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/OneStepForwardReasoner.cs
index 3af0614da..49463238f 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/OneStepForwardReasoner.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/OneStepForwardReasoner.cs
@@ -67,8 +67,22 @@ public async Task GetNextInstruction(Agent router, string m
// eliminating format drift where the LLM completes with finishReason=stop and returns
// free text or JSON in Content instead of a structured function call.
var response = await GetChatCompletionsWithScopedState(completion, router, dialogs, "tool_choice", "required");
-
var inst = response.FunctionArgs?.JsonContent();
+
+ if (inst != null)
+ {
+ if (!string.IsNullOrEmpty(response.FunctionName))
+ {
+ inst.Function = response.FunctionName;
+ }
+
+ if (!string.IsNullOrEmpty(response.FunctionArgs))
+ {
+ inst.FunctionArgs = response.FunctionArgs;
+ }
+ }
+
+
_logger.LogInformation("[OneStepForwardReasoner] ConversationId: {ConversationId}, MessageId: {MessageId}, Next instruction: {Instruction}",
_services.GetRequiredService().ConversationId, messageId, response.FunctionArgs);
@@ -82,7 +96,14 @@ public Task AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDia
{
// Set user content as Planner's question
message.FunctionName = inst.Function;
- message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
+ if (!string.IsNullOrEmpty(inst.FunctionArgs))
+ {
+ message.FunctionArgs = inst.FunctionArgs;
+ }
+ else
+ {
+ message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
+ }
return Task.FromResult(true);
}