Skip to content

Commit 485af07

Browse files
Python: Add GeminiChatClient (#4847)
* Add agent-framework-gemini package * Add AGENTS.md documentation * Add LICENSE file * Add README.md for agent-framework-gemini package * Add Google Gemini API keys to .env.example * Add Google Gemini chat client implementation * Add tests for GeminiChatClient * Add Google Gemini agent examples * Fix client inheritence order * Update Gemini agent examples * Update documentation * Update AGENTS.md * Add tests for JSON string handling in GeminiChatClient * Add final response assembly test in GeminiChatClient * Add tests for handling empty candidates in GeminiChatClient * Improve Pydantic response handling in GeminiChatClient * Add tests for function result resolution and callable tool normalization * Add test for function result resolution when call_id is generated * Refactor GeminiChatClient to correct inheritance order Also updates constructor parameter order for environment file handling * Enhance documentation and clarify Gemini-specific fields * Update ThinkingConfig with new attributes and type * Add tests for GoogleSearch and GoogleMaps configs * Suppress valid-type mypy error on GeminiChatOptionsT * Move service_url method near overrides * Order _prepare_config kwargs by base then Gemini-specific * Use FunctionCallingConfigMode for clarity and type safety * Fix code_execution doc * Add agent-framework-gemini to project dependencies * Remove package from core dependencies Initial release will be done without agent-framework-gemini in core[all]. * Move integration tests into one file * Remove __init__.py file from gemini tests directory * Introduce RawGeminiChatClient as lightweight chat client Updated GeminiChatClient to inherit from RawGeminiChatClient, maintaining full functionality with added features. * Updated variable names from `model_id` to `model` Across the codebase, including environment variables and client initialization. Adjusted related tests and sample scripts to reflect this change, ensuring consistency in the usage of the Gemini model identifier. * Update AGENTS.md * Update Gemini package to alpha status * Fix docstrings in Gemini tests * Change 'model_id' to 'model' in response handling * Fix model property change in response handling * Add built-in tool factory methods to Gemini client Replaces boolean tool options (code_execution, google_search_grounding, google_maps_grounding) with static factory methods that return types.Tool objects: get_code_interpreter_tool, get_web_search_tool, get_mcp_tool, get_file_search_tool, and get_maps_grounding_tool. Simplifies _prepare_tools to a single translation boundary between FunctionTool (framework) and FunctionDeclaration (Gemini API), with types.Tool objects passed through unchanged. * Surface code execution parts _parse_parts now maps executable_code and code_execution_result parts to text Content objects so callers can see the code run and its output. Unknown part types log at debug level rather than being silently dropped. * Update Gemini client documentation * Unify Gemini model name Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com> * Update Agent Framework core version Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com> * Add Python 3.14 in classifiers * Replace kwargs with parameters in tool factories * Refactor chat options handling in Gemini client * Add tests for handling unknown and consumed keys * Update Gemini documentation Now reflects new options and built-in tool factory methods * Change build system to flit Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com> * Fix build system in pyproject.toml * Fix type checking for generate_content_stream --------- Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
1 parent 64c68ca commit 485af07

20 files changed

Lines changed: 2910 additions & 6 deletions

python/.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ COPILOTSTUDIOAGENT__AGENTAPPID=""
3838
# Anthropic
3939
ANTHROPIC_API_KEY=""
4040
ANTHROPIC_MODEL=""
41+
# Google Gemini
42+
GEMINI_API_KEY=""
43+
GEMINI_MODEL=""
4144
# Ollama
4245
OLLAMA_ENDPOINT=""
4346
OLLAMA_MODEL=""

python/PACKAGE_STATUS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Status is grouped into these buckets:
3131
| `agent-framework-durabletask` | `python/packages/durabletask` | `beta` |
3232
| `agent-framework-foundry` | `python/packages/foundry` | `released` |
3333
| `agent-framework-foundry-local` | `python/packages/foundry_local` | `beta` |
34+
| `agent-framework-gemini` | `python/packages/gemini` | `alpha` |
3435
| `agent-framework-github-copilot` | `python/packages/github_copilot` | `beta` |
3536
| `agent-framework-lab` | `python/packages/lab` | `beta` |
3637
| `agent-framework-mem0` | `python/packages/mem0` | `beta` |

python/packages/core/pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,13 @@ all = [
3434
"mcp>=1.24.0,<2",
3535
"agent-framework-a2a",
3636
"agent-framework-ag-ui",
37+
"agent-framework-anthropic",
3738
"agent-framework-azure-ai-search",
3839
"agent-framework-azure-cosmos",
39-
"agent-framework-anthropic",
40-
"agent-framework-openai",
41-
"agent-framework-claude",
4240
"agent-framework-azurefunctions",
4341
"agent-framework-bedrock",
4442
"agent-framework-chatkit",
43+
"agent-framework-claude",
4544
"agent-framework-copilotstudio",
4645
"agent-framework-declarative",
4746
"agent-framework-devui",
@@ -52,6 +51,7 @@ all = [
5251
"agent-framework-lab",
5352
"agent-framework-mem0",
5453
"agent-framework-ollama",
54+
"agent-framework-openai",
5555
"agent-framework-orchestrations",
5656
"agent-framework-purview",
5757
"agent-framework-redis",

python/packages/gemini/AGENTS.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Gemini Package (agent-framework-gemini)
2+
3+
Integration with Google's Gemini API via the `google-genai` SDK.
4+
5+
## Core Classes
6+
7+
- **`RawGeminiChatClient`** - Lightweight chat client without any layers, for custom pipeline composition
8+
- **`GeminiChatClient`** - Full-featured chat client with function invocation, middleware, and telemetry
9+
- **`GeminiChatOptions`** - Options TypedDict for Gemini-specific parameters
10+
- **`GeminiSettings`** - Settings loaded from environment variables
11+
- **`ThinkingConfig`** - Configuration for extended thinking
12+
13+
## Gemini-specific Options
14+
15+
- **`thinking_config`** - Enable extended thinking via `ThinkingConfig`
16+
- **`response_schema`** - Raw JSON schema dict for structured output (alternative to `response_format`)
17+
- **`top_k`** - Top-K sampling parameter
18+
19+
## Built-in Tool Factory Methods
20+
21+
- **`get_web_search_tool()`** - Google Search grounding for up-to-date web answers
22+
- **`get_code_interpreter_tool()`** - Sandboxed code execution
23+
- **`get_maps_grounding_tool()`** - Google Maps grounding for location and mapping
24+
- **`get_file_search_tool()`** - Retrieval from Gemini file search stores
25+
- **`get_mcp_tool()`** - Model Context Protocol server integration
26+
27+
## Usage
28+
29+
```python
30+
from agent_framework import Content, Message
31+
from agent_framework_gemini import GeminiChatClient
32+
33+
client = GeminiChatClient(model="gemini-2.5-flash")
34+
response = await client.get_response([Message(role="user", contents=[Content.from_text("Hello")])])
35+
```

python/packages/gemini/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Microsoft Corporation.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE

python/packages/gemini/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Get Started with Microsoft Agent Framework Gemini
2+
3+
Install the provider package:
4+
5+
```bash
6+
pip install agent-framework-gemini --pre
7+
```
8+
9+
## Gemini Integration
10+
11+
The Gemini integration enables Microsoft Agent Framework applications to call Google Gemini models with familiar chat abstractions, including streaming, tool/function calling, and structured output.
12+
13+
## Authentication
14+
15+
Obtain an API key from [Google AI Studio](https://aistudio.google.com/apikey) and set it via environment variable:
16+
17+
```bash
18+
export GEMINI_API_KEY="your-api-key"
19+
export GEMINI_MODEL="gemini-2.5-flash"
20+
```
21+
22+
## Examples
23+
24+
See the [Google Gemini samples](samples/) for runnable end-to-end scripts covering:
25+
26+
- Basic agent with tool calling and streaming
27+
- Extended thinking with `ThinkingConfig`
28+
- Google Search grounding
29+
- Google Maps grounding
30+
- Built-in code execution
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
3+
import importlib.metadata
4+
5+
from ._chat_client import GeminiChatClient, GeminiChatOptions, GeminiSettings, RawGeminiChatClient, ThinkingConfig
6+
7+
try:
8+
__version__ = importlib.metadata.version(__name__)
9+
except importlib.metadata.PackageNotFoundError:
10+
__version__ = "0.0.0"
11+
12+
__all__ = [
13+
"GeminiChatClient",
14+
"GeminiChatOptions",
15+
"GeminiSettings",
16+
"RawGeminiChatClient",
17+
"ThinkingConfig",
18+
"__version__",
19+
]

0 commit comments

Comments
 (0)