microsoft/semantic-kernel · error · ArgumentException

and cannot be used together.

Error message

{nameof(executionSettings.ToolCallBehavior)} and {nameof(executionSettings.FunctionChoiceBehavior)} cannot be used together.

What it means

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.

Solutions

  1. Use only FunctionChoiceBehavior (preferred) or only ToolCallBehavior, never both.
  2. When migrating, set ToolCallBehavior = null after assigning FunctionChoiceBehavior.
  3. If settings are merged/serialized, ensure only one survives the merge.

Example fix

// before
settings.ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions;
settings.FunctionChoiceBehavior = FunctionChoiceBehavior.Auto();
// after
settings.ToolCallBehavior = null;
settings.FunctionChoiceBehavior = FunctionChoiceBehavior.Auto();
Defensive patterns

Strategy: validation

Validate before calling

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"); }

Type guard

static bool HasSingleToolBehavior(OpenAIPromptExecutionSettings s) => (s.FunctionChoiceBehavior is null) || (s.ToolCallBehavior is null);

Try / catch

try { await client.GetChatCompletionAsync(...); }
catch (ArgumentException ex) when (ex.Message.Contains("cannot be used together")) { settings.ToolCallBehavior = null; /* retry with FunctionChoiceBehavior */ }

Prevention

When it happens

Trigger: Code (or merged settings) that sets both ToolCallBehavior (e.g. KernelFunctionFactory/ToolCallBehavior.AutoInvokeKernelFunctions) and FunctionChoiceBehavior (e.g. FunctionChoiceBehavior.Auto()) on the same OpenAIPromptExecutionSettings.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/fac72ca349127b6c. Report an issue: GitHub.

Appendix: source

Thrown at dotnet/src/Connectors/Connectors.OpenAI/Core/ClientCore.ChatCompletion.cs:1258

        }

        s_promptTokensCounter.Add(usage.InputTokenCount);
        s_completionTokensCounter.Add(usage.OutputTokenCount);
        s_totalTokensCounter.Add(usage.TotalTokenCount);
    }

    private ToolCallingConfig GetFunctionCallingConfiguration(Kernel? kernel, OpenAIPromptExecutionSettings executionSettings, ChatHistory chatHistory, int requestIndex)
    {
        // If neither behavior is specified, we just return default configuration with no tool and no choice
        if (executionSettings.FunctionChoiceBehavior is null && executionSettings.ToolCallBehavior is null)
        {
            return new ToolCallingConfig(Tools: null, Choice: null, AutoInvoke: false, AllowAnyRequestedKernelFunction: false, Options: null);
        }

        // If both behaviors are specified, we can't handle that.
        if (executionSettings.FunctionChoiceBehavior is not null && executionSettings.ToolCallBehavior is not null)
        {
            throw new ArgumentException($"{nameof(executionSettings.ToolCallBehavior)} and {nameof(executionSettings.FunctionChoiceBehavior)} cannot be used together.");
        }

        IList<ChatTool>? tools = null;
        ChatToolChoice? choice = null;
        bool autoInvoke = false;
        bool allowAnyRequestedKernelFunction = false;
        FunctionChoiceBehaviorOptions? options = null;

        // Handling new tool behavior represented by `PromptExecutionSettings.FunctionChoiceBehavior` property.
        if (executionSettings.FunctionChoiceBehavior is { } functionChoiceBehavior)
        {
            (tools, choice, autoInvoke, options) = this.ConfigureFunctionCalling(kernel, requestIndex, functionChoiceBehavior, chatHistory);
        }
        // Handling old-style tool call behavior represented by `OpenAIPromptExecutionSettings.ToolCallBehavior` property.
        else if (executionSettings.ToolCallBehavior is { } toolCallBehavior)
        {
            (tools, choice, autoInvoke, int maximumAutoInvokeAttempts, allowAnyRequestedKernelFunction) = this.ConfigureFunctionCalling(kernel, requestIndex, toolCallBehavior);

View on GitHub (pinned to c028a0c7dc)