Skip to content

Commit 5ab589c

Browse files
authored
Merge branch 'google:main' into main
2 parents e6947ad + c4c127d commit 5ab589c

64 files changed

Lines changed: 3536 additions & 229 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
name: Copybara PR Handler
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
inputs:
9+
pr_number:
10+
description: 'PR number to close (for testing)'
11+
required: true
12+
type: string
13+
commit_sha:
14+
description: 'Commit SHA reference (optional, for testing)'
15+
required: false
16+
type: string
17+
18+
jobs:
19+
close-imported-pr:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
pull-requests: write
23+
issues: write
24+
contents: read
25+
26+
steps:
27+
- name: Check for Copybara commits and close PRs
28+
uses: actions/github-script@v7
29+
with:
30+
github-token: ${{ secrets.ADK_TRIAGE_AGENT }}
31+
script: |
32+
// Check if this is a manual test run
33+
const isManualRun = context.eventName === 'workflow_dispatch';
34+
35+
let prsToClose = [];
36+
37+
if (isManualRun) {
38+
// Manual testing mode
39+
const prNumber = parseInt(context.payload.inputs.pr_number);
40+
const commitSha = context.payload.inputs.commit_sha || context.sha.substring(0, 7);
41+
42+
console.log('=== MANUAL TEST MODE ===');
43+
console.log(`Testing with PR #${prNumber}, commit ${commitSha}`);
44+
45+
prsToClose.push({ prNumber, commitSha });
46+
} else {
47+
// Normal mode: process commits from push event
48+
const commits = context.payload.commits || [];
49+
console.log(`Found ${commits.length} commit(s) in this push`);
50+
51+
// Process each commit
52+
for (const commit of commits) {
53+
const sha = commit.id;
54+
const committer = commit.committer.name;
55+
const message = commit.message;
56+
57+
console.log(`\n--- Processing commit ${sha.substring(0, 7)} ---`);
58+
console.log(`Committer: ${committer}`);
59+
60+
// Check if this is a Copybara commit
61+
if (committer !== 'Copybara-Service') {
62+
console.log('Not a Copybara commit, skipping');
63+
continue;
64+
}
65+
66+
// Extract PR number from commit message
67+
// Pattern: "Merge https://github.com/google/adk-python/pull/3333"
68+
const prMatch = message.match(/Merge https:\/\/github\.com\/google\/adk-python\/pull\/(\d+)/);
69+
70+
if (!prMatch) {
71+
console.log('No PR number found in Copybara commit message');
72+
continue;
73+
}
74+
75+
const prNumber = parseInt(prMatch[1]);
76+
const commitSha = sha.substring(0, 7);
77+
78+
prsToClose.push({ prNumber, commitSha });
79+
}
80+
}
81+
82+
// Process PRs to close
83+
for (const { prNumber, commitSha } of prsToClose) {
84+
console.log(`\n--- Processing PR #${prNumber} ---`);
85+
86+
// Get PR details to check if it's open
87+
let pr;
88+
try {
89+
pr = await github.rest.pulls.get({
90+
owner: context.repo.owner,
91+
repo: context.repo.repo,
92+
pull_number: prNumber
93+
});
94+
} catch (error) {
95+
console.log(`PR #${prNumber} not found or inaccessible:`, error.message);
96+
continue;
97+
}
98+
99+
// Only close if PR is still open
100+
if (pr.data.state !== 'open') {
101+
console.log(`PR #${prNumber} is already ${pr.data.state}, skipping`);
102+
continue;
103+
}
104+
105+
const author = pr.data.user.login;
106+
107+
try {
108+
// Add comment with commit reference
109+
await github.rest.issues.createComment({
110+
owner: context.repo.owner,
111+
repo: context.repo.repo,
112+
issue_number: prNumber,
113+
body: `Thank you @${author} for your contribution! 🎉\n\nYour changes have been successfully imported and merged via Copybara in commit ${commitSha}.\n\nClosing this PR as the changes are now in the main branch.`
114+
});
115+
116+
// Close the PR
117+
await github.rest.pulls.update({
118+
owner: context.repo.owner,
119+
repo: context.repo.repo,
120+
pull_number: prNumber,
121+
state: 'closed'
122+
});
123+
124+
console.log(`Successfully closed PR #${prNumber}`);
125+
} catch (error) {
126+
console.log(`Error closing PR #${prNumber}:`, error.message);
127+
}
128+
}
129+
130+
if (isManualRun) {
131+
console.log('\n=== TEST COMPLETED ===');
132+
} else {
133+
console.log('\n--- Finished processing all commits ---');
134+
}

README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<img src="https://raw.githubusercontent.com/google/adk-python/main/assets/agent-development-kit.png" width="256"/>
1212
</h2>
1313
<h3 align="center">
14-
An open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.
14+
An open-source, code-first Python framework for building, evaluating, and deploying sophisticated AI agents with flexibility and control.
1515
</h3>
1616
<h3 align="center">
1717
Important Links:
@@ -22,7 +22,11 @@
2222
</h3>
2323
</html>
2424

25-
Agent Development Kit (ADK) is a flexible and modular framework for developing and deploying AI agents. While optimized for Gemini and the Google ecosystem, ADK is model-agnostic, deployment-agnostic, and is built for compatibility with other frameworks. ADK was designed to make agent development feel more like software development, to make it easier for developers to create, deploy, and orchestrate agentic architectures that range from simple tasks to complex workflows.
25+
Agent Development Kit (ADK) is a flexible and modular framework that applies
26+
software development principles to AI agent creation. It is designed to
27+
simplify building, deploying, and orchestrating agent workflows, from simple
28+
tasks to complex systems. While optimized for Gemini, ADK is model-agnostic,
29+
deployment-agnostic, and compatible with other frameworks.
2630

2731
---
2832

@@ -37,7 +41,7 @@ Agent Development Kit (ADK) is a flexible and modular framework for developing a
3741
## ✨ Key Features
3842

3943
- **Rich Tool Ecosystem**: Utilize pre-built tools, custom functions,
40-
OpenAPI specs, or integrate existing tools to give agents diverse
44+
OpenAPI specs, MCP tools or integrate existing tools to give agents diverse
4145
capabilities, all for tight integration with the Google ecosystem.
4246

4347
- **Code-First Development**: Define agent logic, tools, and orchestration
@@ -54,13 +58,6 @@ Agent Development Kit (ADK) is a flexible and modular framework for developing a
5458
- **Deploy Anywhere**: Easily containerize and deploy agents on Cloud Run or
5559
scale seamlessly with Vertex AI Agent Engine.
5660

57-
## 🤖 Agent2Agent (A2A) Protocol and ADK Integration
58-
59-
For remote agent-to-agent communication, ADK integrates with the
60-
[A2A protocol](https://github.com/google-a2a/A2A/).
61-
See this [example](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents)
62-
for how they can work together.
63-
6461
## 🚀 Installation
6562

6663
### Stable Release (Recommended)
@@ -84,6 +81,13 @@ pip install git+https://github.com/google/adk-python.git@main
8481

8582
Note: The development version is built directly from the latest code commits. While it includes the newest fixes and features, it may also contain experimental changes or bugs not present in the stable release. Use it primarily for testing upcoming changes or accessing critical fixes before they are officially released.
8683

84+
## 🤖 Agent2Agent (A2A) Protocol and ADK Integration
85+
86+
For remote agent-to-agent communication, ADK integrates with the
87+
[A2A protocol](https://github.com/google-a2a/A2A/).
88+
See this [example](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents)
89+
for how they can work together.
90+
8791
## 📚 Documentation
8892

8993
Explore the full documentation for detailed guides on building, evaluating, and
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# FastMCP Server-Side Sampling with ADK
2+
3+
This project demonstrates how to use server-side sampling with a `fastmcp` server connected to an ADK `MCPToolset`.
4+
5+
## Description
6+
7+
The setup consists of two main components:
8+
9+
1. **ADK Agent (`agent.py`):** An `LlmAgent` is configured with an `MCPToolset`. This toolset connects to a local `fastmcp` server.
10+
2. **FastMCP Server (`mcp_server.py`):** A `fastmcp` server that exposes a single tool, `analyze_sentiment`. This server is configured to use its own LLM for sampling, independent of the ADK agent's LLM.
11+
12+
The flow is as follows:
13+
1. The user provides a text prompt to the ADK agent.
14+
2. The agent decides to use the `analyze_sentiment` tool from the `MCPToolset`.
15+
3. The tool call is sent to the `mcp_server.py`.
16+
4. Inside the `analyze_sentiment` tool, `ctx.sample()` is called. This delegates an LLM call to the `fastmcp` server's own sampling handler.
17+
5. The `mcp_server`'s LLM processes the prompt from `ctx.sample()` and returns the result to the server.
18+
6. The server processes the LLM response and returns the final sentiment to the agent.
19+
7. The agent displays the result to the user.
20+
21+
## Steps to Run
22+
23+
### Prerequisites
24+
25+
- Python 3.10+
26+
- `google-adk` library installed.
27+
- A configured OpenAI API key.
28+
29+
### 1. Set up the Environment
30+
31+
Clone the project and navigate to the directory. Make sure your `OPENAI_API_KEY` is available as an environment variable.
32+
33+
### 2. Install Dependencies
34+
35+
Install the required Python libraries:
36+
37+
```bash
38+
pip install fastmcp openai litellm
39+
```
40+
41+
### 3. Run the Example
42+
43+
Navigate to the `samples` directory and choose this ADK agent:
44+
45+
```bash
46+
adk web .
47+
```
48+
49+
The agent will automatically start the FastMCP server in the background.
50+
51+
- **Sample user prompt:** "What is the sentiment of 'I love building things with Python'?"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from . import agent
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
17+
from google.adk.agents import LlmAgent
18+
from google.adk.models.lite_llm import LiteLlm
19+
from google.adk.tools.mcp_tool import MCPToolset
20+
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
21+
from mcp import StdioServerParameters
22+
23+
# This example uses the OpenAI API for both the agent and the server.
24+
# Ensure your OPENAI_API_KEY is available as an environment variable.
25+
api_key = os.getenv('OPENAI_API_KEY')
26+
if not api_key:
27+
raise ValueError('The OPENAI_API_KEY environment variable must be set.')
28+
29+
# Configure the StdioServerParameters to start the mcp_server.py script
30+
# as a subprocess. The OPENAI_API_KEY is passed to the server's environment.
31+
server_params = StdioServerParameters(
32+
command='python',
33+
args=['mcp_server.py'],
34+
env={'OPENAI_API_KEY': api_key},
35+
)
36+
37+
# Create the ADK MCPToolset, which connects to the FastMCP server.
38+
# The `tool_filter` ensures that only the 'analyze_sentiment' tool is exposed
39+
# to the agent.
40+
mcp_toolset = MCPToolset(
41+
connection_params=StdioConnectionParams(
42+
server_params=server_params,
43+
),
44+
tool_filter=['analyze_sentiment'],
45+
)
46+
47+
# Define the ADK agent that uses the MCP toolset.
48+
root_agent = LlmAgent(
49+
model=LiteLlm(model='openai/gpt-4o'),
50+
name='SentimentAgent',
51+
instruction=(
52+
'You are an expert at analyzing text sentiment. Use the'
53+
' analyze_sentiment tool to classify user input.'
54+
),
55+
tools=[mcp_toolset],
56+
)

0 commit comments

Comments
 (0)