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 23eee53d2..0c10f75fe 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs
@@ -31,10 +31,19 @@ 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);
await routing.InvokeFunction(message.FunctionName, msg, options: new() { From = InvokeSource.Routing });
+ if (msg.StopCompletion)
+ {
+ message = RoleDialogModel.From(msg, role: AgentRole.Assistant);
+ }
}
var agentId = routing.Context.GetCurrentAgentId();
@@ -76,8 +85,8 @@ 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);
}