Commit 89755e0
.Net: Fix GeminiChatCompletionClient to invoke IAutoFunctionInvocationFilter during auto function calling (#13397)
### Motivation and Context
Fixes #11245
The Gemini connector was not invoking `IAutoFunctionInvocationFilter`
during the auto function calling loop, diverging from the expected
filter pipeline behavior documented for OpenAI and other SK connectors.
This prevented developers from implementing orchestration patterns over
multiple tool calls (early termination, batch execution, multi-step
planning) when using Gemini.
### Description
Added `IAutoFunctionInvocationFilter` support to
`GeminiChatCompletionClient`, following the same pattern as
`MistralClient`.
**Core changes:**
- Added `ProcessSingleToolCallWithFiltersAsync` - creates
`AutoFunctionInvocationContext` with proper properties
(RequestSequenceIndex, FunctionSequenceIndex, FunctionCount, etc.) and
invokes the filter pipeline
- Added `OnAutoFunctionInvocationAsync` and
`InvokeFilterOrFunctionAsync` helpers for recursive filter chain
execution
- Added `FilterTerminationRequested` flag to `ChatCompletionState` to
distinguish filter termination from max attempts reached
- Updated both `GenerateChatMessageAsync` and
`StreamGenerateChatMessageAsync` to return immediately when filter sets
`Terminate = true`
**Usage example:**
```csharp
kernel.AutoFunctionInvocationFilters.Add(new MyFilter());
public class MyFilter : IAutoFunctionInvocationFilter
{
public async Task OnAutoFunctionInvocationAsync(
AutoFunctionInvocationContext context,
Func<AutoFunctionInvocationContext, Task> next)
{
// Pre-invocation logic
Console.WriteLine($"Invoking {context.Function.Name}");
await next(context);
// Post-invocation logic, can modify result or terminate
if (someCondition)
context.Terminate = true;
}
}
```
### Contribution Checklist
- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>.Net: Bug: GeminiChatCompletionClient does not invoke
IAutoFunctionInvocationFilter during auto function calling
sequence</issue_title>
> <issue_description>**Describe the bug**
> In the current implementation of GeminiChatCompletionClient ([source
link](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/Connectors/Connectors.Google/Core/Gemini/Clients/GeminiChatCompletionClient.cs)),
the connector only invokes the IFunctionInvocationFilter after the
Gemini LLM response, and does not invoke the
IAutoFunctionInvocationFilter interface as part of the auto function
calling loop. This behavior diverges from the expected filter pipeline,
especially as documented for OpenAI and general Semantic Kernel auto
invocation workflows.
>
> As a result:
>
> There is no filter pipeline for managing the entire auto function
invocation loop.
> Patterns requiring orchestration over multiple tool calls (e.g., early
termination, batch function execution, multi-step planning) cannot be
implemented for Gemini.
> Existing workflow code relying on IAutoFunctionInvocationFilter is
ignored when using Gemini.
>
> **To Reproduce**
> 1. Create a Semantic Kernel setup with Gemini as the LLM.
> 2. Register an implementation of IAutoFunctionInvocationFilter with
the kernel.
> 3. Trigger an LLM response from Gemini that includes multiple tool
calls or requires auto invocation.
> 4. Observe that the auto function invocation filter is never executed,
while the standard function invocation filter
(IFunctionInvocationFilter) is.
>
>
> **Expected behavior**
> The connector should invoke IAutoFunctionInvocationFilter in auto
function calling loops, just as it does for other LLM connectors.
> This allows developers to intercept, control, and orchestrate
multi-tool workflows, including terminating the loop early or applying
logic across all planned function calls.
>
> **Actual Behavior**
> IAutoFunctionInvocationFilter is never invoked during tool auto
function calling when using the Gemini connector, making it impossible
to orchestrate, batch, or terminate the multi-step tool
planning/execution loop.
>
> However, the Gemini connector does invoke IFunctionInvocationFilter,
but only after each tool function requested by the LLM is about to be
executed in C# (i.e., post-model response, per-individual-function
basis).
>
> As a result, developers can only perform per-function interception and
logging, not sequence/planning-wide control, within Gemini's auto
function invocation execution.
>
>
> **Platform**
> - Language: C#
> - Source: Microsoft.SemanticKernel.Connectors.Google 1.61.0-alpha
> </issue_description>
>
> <agent_instructions>Fix the issues in the current open
PR</agent_instructions>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
- Fixes #12998
<!-- START COPILOT CODING AGENT TIPS -->
---
✨ Let Copilot coding agent [set things up for
you](https://github.com/microsoft/semantic-kernel/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
---------
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: markwallace-microsoft <[email protected]>
Co-authored-by: Roger Barreto <[email protected]>1 parent 460521a commit 89755e0
File tree
2 files changed
+346
-111
lines changed- dotnet/src/Connectors
- Connectors.Google.UnitTests/Core/Gemini/Clients
- Connectors.Google/Core/Gemini/Clients
2 files changed
+346
-111
lines changedLines changed: 201 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
440 | 440 | | |
441 | 441 | | |
442 | 442 | | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
443 | 629 | | |
444 | 630 | | |
445 | 631 | | |
| |||
465 | 651 | | |
466 | 652 | | |
467 | 653 | | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
468 | 669 | | |
0 commit comments