-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Description
[.NET] Expose configurable MaximumAutoInvokeAttempts for ToolCallBehavior
The .NET SDK does not expose a way to configure MaximumAutoInvokeAttempts
for function/tool calling, while the Python SDK provides this capability through the public maximum_auto_invoke_attempts
property. This limits users' ability to control execution time and costs for agentic scenarios.
Motivation
When building agents that perform research tasks or other multi-step operations, developers need fine-grained control over the maximum number of auto-invoke attempts to:
- Control execution time: Research tasks can take too long if the model makes excessive tool calls
- Manage costs: Each auto-invoke attempt incurs API costs
- Prevent runaway loops: Custom limits help prevent scenarios where the agent gets stuck in inefficient patterns
- Match business requirements: Different use cases require different thresholds (e.g., 5 for quick searches, 20 for deep research)
Real-World Use Case
I'm building an agent that performs research tasks. Sometimes I want to limit it to 5 auto-invoke attempts for quick responses, while other times I might allow more for deeper research. Currently, I'm forced to use the hardcoded defaults (128 for OpenAI) with no ability to customize per scenario.
Current State
Python SDK ✅ (Has this feature)
The Python SDK exposes maximum_auto_invoke_attempts
as a public, configurable property:
Location: python/semantic_kernel/connectors/ai/function_choice_behavior.py
@experimental
class FunctionChoiceBehavior(KernelBaseModel):
enable_kernel_functions: bool = True
maximum_auto_invoke_attempts: int = DEFAULT_MAX_AUTO_INVOKE_ATTEMPTS # Default: 5
# ... other properties
Usage Examples:
# Direct configuration
behavior = FunctionChoiceBehavior.Auto(maximum_auto_invoke_attempts=5)
# Runtime modification
behavior.maximum_auto_invoke_attempts = 10
# Via kwargs in factory methods
behavior = FunctionChoiceBehavior.Required(
auto_invoke=True,
maximum_auto_invoke_attempts=3
)
.NET SDK ❌ (Missing this feature)
The .NET SDK has MaximumAutoInvokeAttempts
as an internal, read-only property with no public configuration API:
Locations:
dotnet/src/Connectors/Connectors.OpenAI/ToolCallBehavior.cs
dotnet/src/Connectors/Connectors.Google/GeminiToolCallBehavior.cs
dotnet/src/Connectors/Connectors.MistralAI/MistralAIToolCallBehavior.cs
dotnet/src/Agents/OpenAI/Internal/ResponseThreadActions.cs
Current Implementation:
// OpenAI/Google Connectors
private const int DefaultMaximumAutoInvokeAttempts = 128;
internal int MaximumAutoInvokeAttempts { get; } // Internal, read-only
private ToolCallBehavior(bool autoInvoke)
{
this.MaximumAutoInvokeAttempts = autoInvoke ? DefaultMaximumAutoInvokeAttempts : 0;
}
// MistralAI Connector
private const int DefaultMaximumAutoInvokeAttempts = 5;
// Agents
private const int MaximumAutoInvokeAttempts = 128;
Current Defaults (Hardcoded):
- OpenAI Connector: 128
- Google/Gemini Connector: 128
- MistralAI Connector: 5
- OpenAI Agents: 128
Proposed Solution
Make MaximumAutoInvokeAttempts
configurable in the .NET SDK to match Python SDK capabilities.
Constructor Parameter
public abstract class ToolCallBehavior
{
public static ToolCallBehavior AutoInvokeKernelFunctions => new KernelFunctions(autoInvoke: true);
public static ToolCallBehavior AutoInvokeKernelFunctions(int maximumAutoInvokeAttempts)
=> new KernelFunctions(autoInvoke: true, maximumAutoInvokeAttempts);
// Property remains internal but value can be set
internal int MaximumAutoInvokeAttempts { get; }
}
Usage:
var settings = new OpenAIPromptExecutionSettings
{
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions(maximumAutoInvokeAttempts: 5)
};
Benefits
- Feature Parity: Brings .NET SDK to parity with Python SDK
- User Control: Developers can optimize for their specific use cases
- Cost Management: Better control over API costs
Additional Context
From docs/decisions/0061-function-call-behavior.md
, the design principle states that function call behavior should be:
"connector/model-agnostic function call behavior classes, enabling their use by all SK connectors that support function calling"
Making MaximumAutoInvokeAttempts
configurable aligns with this principle by giving users consistent control across all connectors.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status