{"record":{"id":"fac72ca349127b6c","repo":"microsoft/semantic-kernel","slug":"nameof-executionsettings-toolcallbehavior-and","errorCode":null,"errorMessage":"{nameof(executionSettings.ToolCallBehavior)} and {nameof(executionSettings.FunctionChoiceBehavior)} cannot be used together.","messagePattern":"(.+?) and (.+?) cannot be used together\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Connectors/Connectors.OpenAI/Core/ClientCore.ChatCompletion.cs","lineNumber":1258,"sourceCode":"        }\n\n        s_promptTokensCounter.Add(usage.InputTokenCount);\n        s_completionTokensCounter.Add(usage.OutputTokenCount);\n        s_totalTokensCounter.Add(usage.TotalTokenCount);\n    }\n\n    private ToolCallingConfig GetFunctionCallingConfiguration(Kernel? kernel, OpenAIPromptExecutionSettings executionSettings, ChatHistory chatHistory, int requestIndex)\n    {\n        // If neither behavior is specified, we just return default configuration with no tool and no choice\n        if (executionSettings.FunctionChoiceBehavior is null && executionSettings.ToolCallBehavior is null)\n        {\n            return new ToolCallingConfig(Tools: null, Choice: null, AutoInvoke: false, AllowAnyRequestedKernelFunction: false, Options: null);\n        }\n\n        // If both behaviors are specified, we can't handle that.\n        if (executionSettings.FunctionChoiceBehavior is not null && executionSettings.ToolCallBehavior is not null)\n        {\n            throw new ArgumentException($\"{nameof(executionSettings.ToolCallBehavior)} and {nameof(executionSettings.FunctionChoiceBehavior)} cannot be used together.\");\n        }\n\n        IList<ChatTool>? tools = null;\n        ChatToolChoice? choice = null;\n        bool autoInvoke = false;\n        bool allowAnyRequestedKernelFunction = false;\n        FunctionChoiceBehaviorOptions? options = null;\n\n        // Handling new tool behavior represented by `PromptExecutionSettings.FunctionChoiceBehavior` property.\n        if (executionSettings.FunctionChoiceBehavior is { } functionChoiceBehavior)\n        {\n            (tools, choice, autoInvoke, options) = this.ConfigureFunctionCalling(kernel, requestIndex, functionChoiceBehavior, chatHistory);\n        }\n        // Handling old-style tool call behavior represented by `OpenAIPromptExecutionSettings.ToolCallBehavior` property.\n        else if (executionSettings.ToolCallBehavior is { } toolCallBehavior)\n        {\n            (tools, choice, autoInvoke, int maximumAutoInvokeAttempts, allowAnyRequestedKernelFunction) = this.ConfigureFunctionCalling(kernel, requestIndex, toolCallBehavior);\n","sourceCodeStart":1240,"sourceCodeEnd":1276,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Connectors/Connectors.OpenAI/Core/ClientCore.ChatCompletion.cs#L1240-L1276","documentation":"Thrown by GetFunctionCallingConfiguration when BOTH executionSettings.FunctionChoiceBehavior and executionSettings.ToolCallBehavior are non-null. These are two mutually exclusive ways to configure tool/function calling (FunctionChoiceBehavior is the newer model; ToolCallBehavior is the legacy one). Specifying both is ambiguous, so the connector refuses rather than guess which wins.","triggerScenarios":"Code (or merged settings) that sets both ToolCallBehavior (e.g. KernelFunctionFactory/ToolCallBehavior.AutoInvokeKernelFunctions) and FunctionChoiceBehavior (e.g. FunctionChoiceBehavior.Auto()) on the same OpenAIPromptExecutionSettings.","commonSituations":"Migrating from ToolCallBehavior to FunctionChoiceBehavior but forgetting to clear the old one; cloning settings that carry a legacy default; mixing snippets from docs of different vintages.","solutions":["Use only FunctionChoiceBehavior (preferred) or only ToolCallBehavior, never both.","When migrating, set ToolCallBehavior = null after assigning FunctionChoiceBehavior.","If settings are merged/serialized, ensure only one survives the merge."],"exampleFix":"// before\nsettings.ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions;\nsettings.FunctionChoiceBehavior = FunctionChoiceBehavior.Auto();\n// after\nsettings.ToolCallBehavior = null;\nsettings.FunctionChoiceBehavior = FunctionChoiceBehavior.Auto();","handlingStrategy":"validation","validationCode":"static void EnsureSingleToolBehavior(OpenAIPromptExecutionSettings s) { if (s.FunctionChoiceBehavior is not null && s.ToolCallBehavior is not null) throw new ArgumentException(\"Set only one of FunctionChoiceBehavior or ToolCallBehavior\"); }","typeGuard":"static bool HasSingleToolBehavior(OpenAIPromptExecutionSettings s) => (s.FunctionChoiceBehavior is null) || (s.ToolCallBehavior is null);","tryCatchPattern":"try { await client.GetChatCompletionAsync(...); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"cannot be used together\")) { settings.ToolCallBehavior = null; /* retry with FunctionChoiceBehavior */ }","preventionTips":["Prefer FunctionChoiceBehavior; null out ToolCallBehavior when migrating.","Audit settings merge logic so only one survives."],"tags":["openai","function-calling","settings-conflict","tool-behavior"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}