chore: import upstream snapshot with attribution
Continuous Integration / Pre-commit Linter (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.10) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.11) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.12) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.10) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.11) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.12) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.14) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Waiting to run
Copybara PR Handler / close-imported-pr (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:25:13 +08:00
commit ec2b666284
2231 changed files with 491535 additions and 0 deletions
@@ -0,0 +1,155 @@
# Interactions API Sample Agent
This sample agent demonstrates the Interactions API integration in ADK. The
Interactions API provides stateful conversation capabilities, allowing chained
interactions using `previous_interaction_id` instead of sending full
conversation history.
## Features Tested
1. **Basic Text Generation** - Simple conversation without tools
1. **Google Search Tool** - Web search using `GoogleSearchTool` with
`bypass_multi_tools_limit=True`
1. **Multi-Turn Conversations** - Stateful interactions with context retention
via `previous_interaction_id`
1. **Custom Function Tool** - Weather lookup using `get_current_weather`
## Important: Tool Compatibility
The Interactions API does **NOT** support mixing custom function calling tools
with built-in tools (like `google_search`) in the same agent. To work around
this limitation:
```python
# Use bypass_multi_tools_limit=True to convert google_search to a function tool
GoogleSearchTool(bypass_multi_tools_limit=True)
```
This converts the built-in `google_search` to a function calling tool (via
`GoogleSearchAgentTool`), which allows it to work alongside custom function
tools.
## How to Run
### Prerequisites
```bash
# From the adk-python root directory
uv sync --all-extras
source .venv/bin/activate
# Set up authentication (choose one):
# Option 1: Using Google Cloud credentials
export GOOGLE_CLOUD_PROJECT=your-project-id
# Option 2: Using API Key
export GOOGLE_API_KEY=your-api-key
```
### Running Tests
```bash
cd contributing/samples
# Run automated tests with Interactions API
python -m interactions_api.main
```
## Key Differences: Interactions API vs Standard API
### Interactions API (`use_interactions_api=True`)
- Uses stateful interactions via `previous_interaction_id`
- Only sends current turn contents when chaining interactions
- Returns `interaction_id` in responses for chaining
- Ideal for long conversations with many turns
- Context caching is not used (state maintained via interaction chaining)
### Standard API (`use_interactions_api=False`)
- Uses stateless `generate_content` calls
- Sends full conversation history with each request
- No interaction IDs in responses
- Context caching can be used
## Code Structure
```
interactions_api/
├── __init__.py # Package initialization
├── agent.py # Agent definition with Interactions API
├── main.py # Test runner
├── test_interactions_curl.sh # cURL-based API tests
├── test_interactions_direct.py # Direct API tests
└── README.md # This file
```
## Agent Configuration
```python
from google.adk.agents.llm_agent import Agent
from google.adk.models.google_llm import Gemini
from google.adk.tools.google_search_tool import GoogleSearchTool
root_agent = Agent(
model=Gemini(
model="gemini-2.5-flash",
use_interactions_api=True, # Enable Interactions API
),
name="interactions_test_agent",
tools=[
GoogleSearchTool(bypass_multi_tools_limit=True), # Converted to function tool
get_current_weather, # Custom function tool
],
)
```
## Example Output
```
============================================================
TEST 1: Basic Text Generation
============================================================
>> User: Hello! What can you help me with?
<< Agent: Hello! I can help you with: 1) Search the web...
[Interaction ID: v1_abc123...]
PASSED: Basic text generation works
============================================================
TEST 2: Function Calling (Google Search Tool)
============================================================
>> User: Search for the capital of France.
[Tool Call] google_search_agent({'request': 'capital of France'})
[Tool Result] google_search_agent: {'result': 'The capital of France is Paris...'}
<< Agent: The capital of France is Paris.
[Interaction ID: v1_def456...]
PASSED: Google search tool works
============================================================
TEST 3: Multi-Turn Conversation (Stateful)
============================================================
>> User: Remember the number 42.
<< Agent: I'll remember that number - 42.
[Interaction ID: v1_ghi789...]
>> User: What number did I ask you to remember?
<< Agent: You asked me to remember the number 42.
[Interaction ID: v1_jkl012...]
PASSED: Multi-turn conversation works with context retention
============================================================
TEST 5: Custom Function Tool (get_current_weather)
============================================================
>> User: What's the weather like in Tokyo?
[Tool Call] get_current_weather({'city': 'Tokyo'})
[Tool Result] get_current_weather: {'city': 'Tokyo', 'temperature_f': 68, ...}
<< Agent: The weather in Tokyo is 68F and Partly Cloudy.
[Interaction ID: v1_mno345...]
PASSED: Custom function tool works with bypass_multi_tools_limit
ALL TESTS PASSED (Interactions API)
```
@@ -0,0 +1,17 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Sample agent for testing the Interactions API integration."""
from . import agent
@@ -0,0 +1,90 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Agent definition for testing the Interactions API integration."""
from google.adk.agents.llm_agent import Agent
from google.adk.models.google_llm import Gemini
from google.adk.tools.google_search_tool import GoogleSearchTool
def get_current_weather(city: str) -> dict:
"""Get the current weather for a city.
This is a mock implementation for testing purposes.
Args:
city: The name of the city to get weather for.
Returns:
A dictionary containing weather information.
"""
# Mock weather data for testing
weather_data = {
"new york": {"temperature": 72, "condition": "Sunny", "humidity": 45},
"london": {"temperature": 59, "condition": "Cloudy", "humidity": 78},
"tokyo": {
"temperature": 68,
"condition": "Partly Cloudy",
"humidity": 60,
},
"paris": {"temperature": 64, "condition": "Rainy", "humidity": 85},
"sydney": {"temperature": 77, "condition": "Clear", "humidity": 55},
}
city_lower = city.lower()
if city_lower in weather_data:
data = weather_data[city_lower]
return {
"city": city,
"temperature_f": data["temperature"],
"condition": data["condition"],
"humidity": data["humidity"],
}
else:
return {
"city": city,
"temperature_f": 70,
"condition": "Unknown",
"humidity": 50,
"note": "Weather data not available, using defaults",
}
# Main agent with google_search built-in tool and custom function tools
#
# NOTE: code_executor is not compatible with function calling mode because the model
# tries to call a function (e.g., run_code) instead of outputting code in markdown.
root_agent = Agent(
model=Gemini(
model="gemini-3.1-flash-lite",
use_interactions_api=True,
),
name="interactions_test_agent",
description="An agent for testing the Interactions API integration",
instruction="""You are a helpful assistant that can:
1. Search the web for information using google_search
2. Get weather information using get_current_weather
When users ask for information that requires searching, use google_search.
When users ask about weather, use get_current_weather.
Be concise and helpful in your responses. Always confirm what you did.
""",
tools=[
GoogleSearchTool(),
get_current_weather,
],
)
@@ -0,0 +1,452 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Main script for testing the Interactions API integration.
This script tests the following features:
1. Basic text generation
2. Google Search tool
3. Multi-turn conversations with stateful interactions
4. Google Search tool (additional coverage)
5. Custom function tool (get_current_weather)
NOTE: Code execution via UnsafeLocalCodeExecutor is not compatible with function
calling mode because the model tries to call a function instead of outputting
code in markdown.
Run with:
cd contributing/samples
python -m interactions_api_test.main
"""
import argparse
import asyncio
import logging
from pathlib import Path
import time
from dotenv import load_dotenv
from google.adk.agents.run_config import RunConfig
from google.adk.cli.utils import logs
from google.adk.runners import InMemoryRunner
from google.adk.runners import Runner
from google.genai import types
import httpx
from .agent import root_agent
# Load .env from the samples directory (parent of this module's directory)
_env_path = Path(__file__).parent.parent / ".env"
load_dotenv(_env_path)
APP_NAME = "interactions_api_test_app"
USER_ID = "test_user"
async def call_agent_async(
runner: Runner,
user_id: str,
session_id: str,
prompt: str,
agent_name: str = "",
show_interaction_id: bool = True,
additional_parts: list[types.Part] | None = None,
) -> tuple[str, str | None]:
"""Call the agent asynchronously with the user's prompt.
Args:
runner: The agent runner
user_id: The user ID
session_id: The session ID
prompt: The prompt to send
agent_name: The expected agent name for filtering responses
show_interaction_id: Whether to show interaction IDs in output
additional_parts: Optional list of additional content parts (e.g. files)
Returns:
A tuple of (response_text, interaction_id)
"""
parts = [types.Part.from_text(text=prompt)]
if additional_parts:
parts.extend(additional_parts)
content = types.Content(role="user", parts=parts)
final_response_text = ""
last_interaction_id = None
print(f"\n>> User: {prompt}")
async for event in runner.run_async(
user_id=user_id,
session_id=session_id,
new_message=content,
run_config=RunConfig(save_input_blobs_as_artifacts=False),
):
# Track interaction ID if available
if event.interaction_id:
last_interaction_id = event.interaction_id
# Show function calls
if event.get_function_calls():
for fc in event.get_function_calls():
print(f" [Tool Call] {fc.name}({fc.args})")
# Show function responses
if event.get_function_responses():
for fr in event.get_function_responses():
print(f" [Tool Result] {fr.name}: {fr.response}")
# Collect text responses from the agent (not user, not partial)
if (
event.content
and event.content.parts
and event.author != "user"
and not event.partial
):
for part in event.content.parts:
if part.text:
# Filter by agent name if provided, otherwise accept any non-user
if not agent_name or event.author == agent_name:
final_response_text += part.text
print(f"<< Agent: {final_response_text}")
if show_interaction_id and last_interaction_id:
print(f" [Interaction ID: {last_interaction_id}]")
return final_response_text, last_interaction_id
async def test_basic_text_generation(runner: Runner, session_id: str):
"""Test basic text generation without tools."""
print("\n" + "=" * 60)
print("TEST 1: Basic Text Generation")
print("=" * 60)
response, interaction_id = await call_agent_async(
runner, USER_ID, session_id, "Hello! What can you help me with?"
)
assert response, "Expected a non-empty response"
print("PASSED: Basic text generation works")
return interaction_id
async def test_function_calling(runner: Runner, session_id: str):
"""Test function calling with the google_search tool."""
print("\n" + "=" * 60)
print("TEST 2: Function Calling (Google Search Tool)")
print("=" * 60)
response, interaction_id = await call_agent_async(
runner,
USER_ID,
session_id,
"Search for the capital of France.",
)
assert response, "Expected a non-empty response"
assert "paris" in response.lower(), f"Expected Paris in response: {response}"
print("PASSED: Google search tool works")
return interaction_id
async def test_multi_turn_conversation(runner: Runner, session_id: str):
"""Test multi-turn conversation to verify stateful interactions."""
print("\n" + "=" * 60)
print("TEST 3: Multi-Turn Conversation (Stateful)")
print("=" * 60)
# Turn 1: Tell the agent a fact directly (test conversation memory)
response1, id1 = await call_agent_async(
runner,
USER_ID,
session_id,
"My favorite color is blue. Just acknowledge this, don't use any tools.",
)
assert response1, "Expected a response for turn 1"
print(f" Turn 1 interaction_id: {id1}")
# Turn 2: Ask about something else (use weather tool to add variety)
response2, id2 = await call_agent_async(
runner,
USER_ID,
session_id,
"What's the weather like in London?",
)
assert response2, "Expected a response for turn 2"
assert (
"59" in response2
or "london" in response2.lower()
or "cloudy" in response2.lower()
), f"Expected London weather info in response: {response2}"
print(f" Turn 2 interaction_id: {id2}")
# Turn 3: Ask the agent to recall conversation context
response3, id3 = await call_agent_async(
runner,
USER_ID,
session_id,
"What is my favorite color that I mentioned earlier in our conversation?",
)
assert response3, "Expected a response for turn 3"
assert (
"blue" in response3.lower()
), f"Expected agent to remember the color 'blue': {response3}"
print(f" Turn 3 interaction_id: {id3}")
# Verify interaction IDs are different (new interactions) but chained
if id1 and id2 and id3:
print(f" Interaction chain: {id1} -> {id2} -> {id3}")
print("PASSED: Multi-turn conversation works with context retention")
async def test_google_search_tool(runner: Runner, session_id: str):
"""Test the google_search built-in tool."""
print("\n" + "=" * 60)
print("TEST 4: Google Search Tool (Additional)")
print("=" * 60)
response, interaction_id = await call_agent_async(
runner,
USER_ID,
session_id,
"Use google search to find out who wrote the novel '1984'.",
)
assert response, "Expected a non-empty response"
assert (
"orwell" in response.lower() or "george" in response.lower()
), f"Expected George Orwell in response: {response}"
print("PASSED: Google search built-in tool works")
async def test_custom_function_tool(runner: Runner, session_id: str):
"""Test the custom function tool alongside google_search.
The root_agent has both GoogleSearchTool (with bypass_multi_tools_limit=True)
and get_current_weather. This tests that function calling tools work with
the Interactions API when all tools are function calling types.
"""
print("\n" + "=" * 60)
print("TEST 5: Custom Function Tool (get_current_weather)")
print("=" * 60)
response, interaction_id = await call_agent_async(
runner,
USER_ID,
session_id,
"What's the weather like in Tokyo?",
)
assert response, "Expected a non-empty response"
# The mock weather data for Tokyo has temperature 68, condition "Partly Cloudy"
assert (
"68" in response
or "partly" in response.lower()
or "tokyo" in response.lower()
), f"Expected weather info for Tokyo in response: {response}"
print("PASSED: Custom function tool works with bypass_multi_tools_limit")
return interaction_id
async def test_pdf_summarization(runner: Runner, session_id: str) -> str | None:
"""Test PDF summarization using the Interactions API."""
print("\n" + "=" * 60)
print("TEST 6: PDF Summarization")
print("=" * 60)
url = "https://storage.googleapis.com/cloud-samples-data/generative-ai/pdf/2403.05530.pdf"
print(f"Downloading {url}...")
async with httpx.AsyncClient() as client:
response = await client.get(
url, headers={"User-Agent": "Mozilla/5.0"}, follow_redirects=True
)
response.raise_for_status()
pdf_bytes = response.content
pdf_part = types.Part.from_bytes(data=pdf_bytes, mime_type="application/pdf")
response, interaction_id = await call_agent_async(
runner,
USER_ID,
session_id,
"Please summarize the attached PDF document.",
additional_parts=[pdf_part],
)
assert response, "Expected a non-empty response"
assert len(response) > 0, f"Expected summary in response: {response}"
assert (
"gemini" in response.lower() or "multimodal" in response.lower()
), f"Expected summary of PDF in response: {response}"
print("PASSED: PDF Summarization works")
return interaction_id
def check_interactions_api_available() -> bool:
"""Check if the interactions API is available in the SDK."""
try:
from google.genai import Client
client = Client()
# Check if interactions attribute exists
return hasattr(client.aio, "interactions")
except Exception:
return False
async def run_all_tests():
"""Run all tests with the Interactions API."""
print("\n" + "#" * 70)
print("# Running tests with Interactions API")
print("#" * 70)
# Check if interactions API is available
if not check_interactions_api_available():
print("\nERROR: Interactions API is not available in the current SDK.")
print("The interactions API requires a SDK version with this feature.")
print("To use the interactions API, ensure you have the SDK with")
print("interactions support installed (e.g., from private-python-genai).")
return False
test_agent = root_agent
runner = InMemoryRunner(
agent=test_agent,
app_name=APP_NAME,
)
# Create a new session
session = await runner.session_service.create_session(
user_id=USER_ID,
app_name=APP_NAME,
)
print(f"\nSession created: {session.id}")
try:
# Run all tests
await test_basic_text_generation(runner, session.id)
await test_function_calling(runner, session.id)
await test_multi_turn_conversation(runner, session.id)
await test_google_search_tool(runner, session.id)
await test_custom_function_tool(runner, session.id)
await test_pdf_summarization(runner, session.id)
print("\n" + "=" * 60)
print("ALL TESTS PASSED (Interactions API)")
print("=" * 60)
return True
except AssertionError as e:
print(f"\nTEST FAILED: {e}")
return False
except Exception as e:
print(f"\nERROR: {e}")
import traceback
traceback.print_exc()
return False
async def interactive_mode():
"""Run in interactive mode for manual testing."""
# Check if interactions API is available
if not check_interactions_api_available():
print("\nERROR: Interactions API is not available in the current SDK.")
print("To use the interactions API, ensure you have the SDK with")
print("interactions support installed (e.g., from private-python-genai).")
return
print("\nInteractive mode with Interactions API")
print("Type 'quit' to exit, 'new' for a new session\n")
test_agent = agent.root_agent
runner = InMemoryRunner(
agent=test_agent,
app_name=APP_NAME,
)
session = await runner.session_service.create_session(
user_id=USER_ID,
app_name=APP_NAME,
)
print(f"Session created: {session.id}\n")
while True:
try:
user_input = input("You: ").strip()
if not user_input:
continue
if user_input.lower() == "quit":
break
if user_input.lower() == "new":
session = await runner.session_service.create_session(
user_id=USER_ID,
app_name=APP_NAME,
)
print(f"New session created: {session.id}\n")
continue
await call_agent_async(runner, USER_ID, session.id, user_input)
except KeyboardInterrupt:
break
print("\nGoodbye!")
def main():
parser = argparse.ArgumentParser(
description="Test the Interactions API integration"
)
parser.add_argument(
"--mode",
choices=["test", "interactive"],
default="test",
help=(
"Run mode: 'test' runs automated tests, 'interactive' for manual"
" testing"
),
)
parser.add_argument(
"--debug",
action="store_true",
help="Enable debug logging",
)
args = parser.parse_args()
if args.debug:
logs.setup_adk_logger(level=logging.DEBUG)
else:
logs.setup_adk_logger(level=logging.INFO)
start_time = time.time()
if args.mode == "test":
success = asyncio.run(run_all_tests())
if not success:
exit(1)
elif args.mode == "interactive":
asyncio.run(interactive_mode())
end_time = time.time()
print(f"\nTotal execution time: {end_time - start_time:.2f} seconds")
if __name__ == "__main__":
main()
@@ -0,0 +1,37 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "Hello! What can you help me with?"
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "Hello! I am \"interactions_test_agent,\" an agent designed for testing the Interactions API integration.\n\nI can help you with two main tasks:\n1. **Searching the web:** If you have questions that require up-to-date information, I can search the web for you.\n2. **Checking the weather:** I can provide the current weather for a specific city.\n\nHow can I assist you today?"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
}
]
}
@@ -0,0 +1,86 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "What's the weather like in Tokyo?"
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"functionCall": {
"args": {
"city": "Tokyo"
},
"id": "fc-1",
"name": "get_current_weather"
}
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"longRunningToolIds": [],
"nodeInfo": {
"path": "interactions_test_agent@1"
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"functionResponse": {
"id": "fc-1",
"name": "get_current_weather",
"response": {
"city": "Tokyo",
"condition": "Partly Cloudy",
"humidity": 60,
"temperature_f": 68
}
}
}
],
"role": "user"
},
"id": "e-3",
"invocationId": "i-1",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "I have retrieved the weather information for Tokyo. It is currently 68\u00b0F and partly cloudy with 60% humidity."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-1",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
}
]
}
@@ -0,0 +1,40 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "Use google search to find out who wrote the novel '1984'."
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "search_suggestions='<style>\\n.container {\\n align-items: center;\\n border-radius: 8px;\\n display: flex;\\n font-family: Google Sans, Roboto, sans-serif;\\n font-size: 14px;\\n line-height: 20px;\\n padding: 8px 12px;\\n}\\n.chip {\\n display: inline-block;\\n border: solid 1px;\\n border-radius: 16px;\\n min-width: 14px;\\n padding: 5px 16px;\\n text-align: center;\\n user-select: none;\\n margin: 0 8px;\\n -webkit-tap-highlight-color: transparent;\\n}\\n.carousel {\\n overflow: auto;\\n scrollbar-width: none;\\n white-space: nowrap;\\n margin-right: -12px;\\n}\\n.headline {\\n display: flex;\\n margin-right: 4px;\\n}\\n.gradient-container {\\n position: relative;\\n}\\n.gradient {\\n position: absolute;\\n transform: translate(3px, -9px);\\n height: 36px;\\n width: 9px;\\n}\\n@media (prefers-color-scheme: light) {\\n .container {\\n background-color: #fafafa;\\n box-shadow: 0 0 0 1px #0000000f;\\n }\\n .headline-label {\\n color: #1f1f1f;\\n }\\n .chip {\\n background-color: #ffffff;\\n border-color: #d2d2d2;\\n color: #5e5e5e;\\n text-decoration: none;\\n }\\n .chip:hover {\\n background-color: #f2f2f2;\\n }\\n .chip:focus {\\n background-color: #f2f2f2;\\n }\\n .chip:active {\\n background-color: #d8d8d8;\\n border-color: #b6b6b6;\\n }\\n .logo-dark {\\n display: none;\\n }\\n .gradient {\\n background: linear-gradient(90deg, #fafafa 15%, #fafafa00 100%);\\n }\\n}\\n@media (prefers-color-scheme: dark) {\\n .container {\\n background-color: #1f1f1f;\\n box-shadow: 0 0 0 1px #ffffff26;\\n }\\n .headline-label {\\n color: #fff;\\n }\\n .chip {\\n background-color: #2c2c2c;\\n border-color: #3c4043;\\n color: #fff;\\n text-decoration: none;\\n }\\n .chip:hover {\\n background-color: #353536;\\n }\\n .chip:focus {\\n background-color: #353536;\\n }\\n .chip:active {\\n background-color: #464849;\\n border-color: #53575b;\\n }\\n .logo-light {\\n display: none;\\n }\\n .gradient {\\n background: linear-gradient(90deg, #1f1f1f 15%, #1f1f1f00 100%);\\n }\\n}\\n</style>\\n<div class=\"container\">\\n <div class=\"headline\">\\n <svg class=\"logo-light\" width=\"18\" height=\"18\" viewBox=\"9 9 35 35\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M42.8622 27.0064C42.8622 25.7839 42.7525 24.6084 42.5487 23.4799H26.3109V30.1568H35.5897C35.1821 32.3041 33.9596 34.1222 32.1258 35.3448V39.6864H37.7213C40.9814 36.677 42.8622 32.2571 42.8622 27.0064V27.0064Z\" fill=\"#4285F4\"/>\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 43.8555C30.9659 43.8555 34.8687 42.3195 37.7213 39.6863L32.1258 35.3447C30.5898 36.3792 28.6306 37.0061 26.3109 37.0061C21.8282 37.0061 18.0195 33.9811 16.6559 29.906H10.9194V34.3573C13.7563 39.9841 19.5712 43.8555 26.3109 43.8555V43.8555Z\" fill=\"#34A853\"/>\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M16.6559 29.8904C16.3111 28.8559 16.1074 27.7588 16.1074 26.6146C16.1074 25.4704 16.3111 24.3733 16.6559 23.3388V18.8875H10.9194C9.74388 21.2072 9.06992 23.8247 9.06992 26.6146C9.06992 29.4045 9.74388 32.022 10.9194 34.3417L15.3864 30.8621L16.6559 29.8904V29.8904Z\" fill=\"#FBBC05\"/>\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 16.2386C28.85 16.2386 31.107 17.1164 32.9095 18.8091L37.8466 13.8719C34.853 11.082 30.9659 9.3736 26.3109 9.3736C19.5712 9.3736 13.7563 13.245 10.9194 18.8875L16.6559 23.3388C18.0195 19.2636 21.8282 16.2386 26.3109 16.2386V16.2386Z\" fill=\"#EA4335\"/>\\n </svg>\\n <svg class=\"logo-dark\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\" xmlns=\"http://www.w3.org/2000/svg\">\\n <circle cx=\"24\" cy=\"23\" fill=\"#FFF\" r=\"22\"/>\\n <path d=\"M33.76 34.26c2.75-2.56 4.49-6.37 4.49-11.26 0-.89-.08-1.84-.29-3H24.01v5.99h8.03c-.4 2.02-1.5 3.56-3.07 4.56v.75l3.91 2.97h.88z\" fill=\"#4285F4\"/>\\n <path d=\"M15.58 25.77A8.845 8.845 0 0 0 24 31.86c1.92 0 3.62-.46 4.97-1.31l4.79 3.71C31.14 36.7 27.65 38 24 38c-5.93 0-11.01-3.4-13.45-8.36l.17-1.01 4.06-2.85h.8z\" fill=\"#34A853\"/>\\n <path d=\"M15.59 20.21a8.864 8.864 0 0 0 0 5.58l-5.03 3.86c-.98-2-1.53-4.25-1.53-6.64 0-2.39.55-4.64 1.53-6.64l1-.22 3.81 2.98.22 1.08z\" fill=\"#FBBC05\"/>\\n <path d=\"M24 14.14c2.11 0 4.02.75 5.52 1.98l4.36-4.36C31.22 9.43 27.81 8 24 8c-5.93 0-11.01 3.4-13.45 8.36l5.03 3.85A8.86 8.86 0 0 1 24 14.14z\" fill=\"#EA4335\"/>\\n </svg>\\n <div class=\"gradient-container\"><div class=\"gradient\"></div></div>\\n </div>\\n <div class=\"carousel\">\\n<a class=\"chip\" href=\"https://www.google.com/search?q=who+wrote+the+novel+1984&client=app-vertex-grounding&safesearch=active\">who wrote the novel 1984</a>\\n </div>\\n</div>'"
},
{
"text": "The novel *1984* was written by the English author **George Orwell** (whose real name was Eric Arthur Blair). It was published in 1949."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
}
]
}
@@ -0,0 +1,40 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "Search for the capital of France."
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "search_suggestions='<style>\\n.container {\\n align-items: center;\\n border-radius: 8px;\\n display: flex;\\n font-family: Google Sans, Roboto, sans-serif;\\n font-size: 14px;\\n line-height: 20px;\\n padding: 8px 12px;\\n}\\n.chip {\\n display: inline-block;\\n border: solid 1px;\\n border-radius: 16px;\\n min-width: 14px;\\n padding: 5px 16px;\\n text-align: center;\\n user-select: none;\\n margin: 0 8px;\\n -webkit-tap-highlight-color: transparent;\\n}\\n.carousel {\\n overflow: auto;\\n scrollbar-width: none;\\n white-space: nowrap;\\n margin-right: -12px;\\n}\\n.headline {\\n display: flex;\\n margin-right: 4px;\\n}\\n.gradient-container {\\n position: relative;\\n}\\n.gradient {\\n position: absolute;\\n transform: translate(3px, -9px);\\n height: 36px;\\n width: 9px;\\n}\\n@media (prefers-color-scheme: light) {\\n .container {\\n background-color: #fafafa;\\n box-shadow: 0 0 0 1px #0000000f;\\n }\\n .headline-label {\\n color: #1f1f1f;\\n }\\n .chip {\\n background-color: #ffffff;\\n border-color: #d2d2d2;\\n color: #5e5e5e;\\n text-decoration: none;\\n }\\n .chip:hover {\\n background-color: #f2f2f2;\\n }\\n .chip:focus {\\n background-color: #f2f2f2;\\n }\\n .chip:active {\\n background-color: #d8d8d8;\\n border-color: #b6b6b6;\\n }\\n .logo-dark {\\n display: none;\\n }\\n .gradient {\\n background: linear-gradient(90deg, #fafafa 15%, #fafafa00 100%);\\n }\\n}\\n@media (prefers-color-scheme: dark) {\\n .container {\\n background-color: #1f1f1f;\\n box-shadow: 0 0 0 1px #ffffff26;\\n }\\n .headline-label {\\n color: #fff;\\n }\\n .chip {\\n background-color: #2c2c2c;\\n border-color: #3c4043;\\n color: #fff;\\n text-decoration: none;\\n }\\n .chip:hover {\\n background-color: #353536;\\n }\\n .chip:focus {\\n background-color: #353536;\\n }\\n .chip:active {\\n background-color: #464849;\\n border-color: #53575b;\\n }\\n .logo-light {\\n display: none;\\n }\\n .gradient {\\n background: linear-gradient(90deg, #1f1f1f 15%, #1f1f1f00 100%);\\n }\\n}\\n</style>\\n<div class=\"container\">\\n <div class=\"headline\">\\n <svg class=\"logo-light\" width=\"18\" height=\"18\" viewBox=\"9 9 35 35\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M42.8622 27.0064C42.8622 25.7839 42.7525 24.6084 42.5487 23.4799H26.3109V30.1568H35.5897C35.1821 32.3041 33.9596 34.1222 32.1258 35.3448V39.6864H37.7213C40.9814 36.677 42.8622 32.2571 42.8622 27.0064V27.0064Z\" fill=\"#4285F4\"/>\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 43.8555C30.9659 43.8555 34.8687 42.3195 37.7213 39.6863L32.1258 35.3447C30.5898 36.3792 28.6306 37.0061 26.3109 37.0061C21.8282 37.0061 18.0195 33.9811 16.6559 29.906H10.9194V34.3573C13.7563 39.9841 19.5712 43.8555 26.3109 43.8555V43.8555Z\" fill=\"#34A853\"/>\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M16.6559 29.8904C16.3111 28.8559 16.1074 27.7588 16.1074 26.6146C16.1074 25.4704 16.3111 24.3733 16.6559 23.3388V18.8875H10.9194C9.74388 21.2072 9.06992 23.8247 9.06992 26.6146C9.06992 29.4045 9.74388 32.022 10.9194 34.3417L15.3864 30.8621L16.6559 29.8904V29.8904Z\" fill=\"#FBBC05\"/>\\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 16.2386C28.85 16.2386 31.107 17.1164 32.9095 18.8091L37.8466 13.8719C34.853 11.082 30.9659 9.3736 26.3109 9.3736C19.5712 9.3736 13.7563 13.245 10.9194 18.8875L16.6559 23.3388C18.0195 19.2636 21.8282 16.2386 26.3109 16.2386V16.2386Z\" fill=\"#EA4335\"/>\\n </svg>\\n <svg class=\"logo-dark\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\" xmlns=\"http://www.w3.org/2000/svg\">\\n <circle cx=\"24\" cy=\"23\" fill=\"#FFF\" r=\"22\"/>\\n <path d=\"M33.76 34.26c2.75-2.56 4.49-6.37 4.49-11.26 0-.89-.08-1.84-.29-3H24.01v5.99h8.03c-.4 2.02-1.5 3.56-3.07 4.56v.75l3.91 2.97h.88z\" fill=\"#4285F4\"/>\\n <path d=\"M15.58 25.77A8.845 8.845 0 0 0 24 31.86c1.92 0 3.62-.46 4.97-1.31l4.79 3.71C31.14 36.7 27.65 38 24 38c-5.93 0-11.01-3.4-13.45-8.36l.17-1.01 4.06-2.85h.8z\" fill=\"#34A853\"/>\\n <path d=\"M15.59 20.21a8.864 8.864 0 0 0 0 5.58l-5.03 3.86c-.98-2-1.53-4.25-1.53-6.64 0-2.39.55-4.64 1.53-6.64l1-.22 3.81 2.98.22 1.08z\" fill=\"#FBBC05\"/>\\n <path d=\"M24 14.14c2.11 0 4.02.75 5.52 1.98l4.36-4.36C31.22 9.43 27.81 8 24 8c-5.93 0-11.01 3.4-13.45 8.36l5.03 3.85A8.86 8.86 0 0 1 24 14.14z\" fill=\"#EA4335\"/>\\n </svg>\\n <div class=\"gradient-container\"><div class=\"gradient\"></div></div>\\n </div>\\n <div class=\"carousel\">\\n<a class=\"chip\" href=\"https://www.google.com/search?q=capital+of+France&client=app-vertex-grounding&safesearch=active\">capital of France</a>\\n </div>\\n</div>'"
},
{
"text": "I have searched for the capital of France and confirmed that it is Paris."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
}
]
}
@@ -0,0 +1,152 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "My favorite color is blue. Just acknowledge this, don't use any tools."
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "I acknowledge that your favorite color is blue."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
},
{
"author": "user",
"content": {
"parts": [
{
"text": "What's the weather like in London?"
}
],
"role": "user"
},
"id": "e-3",
"invocationId": "i-2",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"functionCall": {
"args": {
"city": "London"
},
"id": "fc-1",
"name": "get_current_weather"
}
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-2",
"longRunningToolIds": [],
"nodeInfo": {
"path": "interactions_test_agent@1"
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"functionResponse": {
"id": "fc-1",
"name": "get_current_weather",
"response": {
"city": "London",
"condition": "Cloudy",
"humidity": 78,
"temperature_f": 59
}
}
}
],
"role": "user"
},
"id": "e-5",
"invocationId": "i-2",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "I have checked the weather in London for you. It is currently cloudy with a temperature of 59\u00b0F and 78% humidity."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-6",
"invocationId": "i-2",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
},
{
"author": "user",
"content": {
"parts": [
{
"text": "What is my favorite color that I mentioned earlier in our conversation?"
}
],
"role": "user"
},
"id": "e-7",
"invocationId": "i-3",
"nodeInfo": {
"path": ""
}
},
{
"author": "interactions_test_agent",
"content": {
"parts": [
{
"text": "Your favorite color, which you mentioned earlier, is blue."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-8",
"invocationId": "i-3",
"nodeInfo": {
"path": "interactions_test_agent@1"
}
}
]
}