{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "J4rz59gQNMVL" }, "source": [ "##### Copyright 2026 Google LLC." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "id": "Ig4NLdwHNMVM" }, "outputs": [], "source": [ "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "m6GdcEtiNMVN" }, "source": [ "# Gemini Agents API: Build managed agents with the Interactions API\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "o_Hz5jL5NMVO" }, "source": [ "The [Interactions API](https://ai.google.dev/gemini-api/docs/interactions) provides a unified interface for working with Gemini models and agents. The [Getting Started notebook](./Get_started_interactions_api.ipynb) covers how to use it with standard Gemini **models** for text generation, multi-turn conversations, and tool use.\n", "\n", "This notebook focuses on something different: **managed agents** with the `antigravity-preview-05-2026` agent.\n", "\n", "### `agent=` vs `model=`\n", "\n", "When you call the Interactions API, you choose between two modes:\n", "\n", "| Parameter | What runs | Best for |\n", "|-----------|-----------|----------|\n", "| `model=\"gemini-...\"` | A standard Gemini model | Text generation, structured output, function calling |\n", "| `agent=\"antigravity-preview-05-2026\"` | A **managed agent** in a sandboxed Linux environment | Autonomous tasks: code execution, web research, file management |\n", "\n", "With `model=`, you get a stateless LLM call (see the [Getting Started notebook](./Get_started_interactions_api.ipynb)). With `agent=`, you spin up an autonomous agent that can **reason, plan, write and execute code, browse the web, and manage files** — all inside a secure sandbox, without you writing any orchestration logic.\n", "\n", "This notebook walks you through the agent mode step by step:\n", "\n", "1. **Simple questions** — use the agent like an LLM (it works, but it's overkill!)\n", "2. **Multi-turn conversations** — persistent sandbox = built-in memory\n", "3. **Using tools** — code execution, web search, file operations\n", "4. **Loading data into the sandbox** — inject files before the agent starts\n", "5. **Creating reusable custom agents** — bundle instructions, skills, and environment" ] }, { "cell_type": "markdown", "metadata": { "id": "Z536SYYoNMVO" }, "source": [ "\n", "## Setup" ] }, { "cell_type": "markdown", "metadata": { "id": "EVLP6A9xNMVO" }, "source": [ "### Install SDK\n", "\n", "Install the SDK from [PyPI](https://github.com/googleapis/python-genai). It's recommended to always use the latest version." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "-S7wD_9wNMVP" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m52.7/52.7 kB\u001b[0m \u001b[31m1.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m818.2/818.2 kB\u001b[0m \u001b[31m17.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m246.1/246.1 kB\u001b[0m \u001b[31m6.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25h\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", "google-colab 1.0.0 requires google-auth==2.47.0, but you have google-auth 2.53.0 which is incompatible.\n", "google-cloud-aiplatform 1.148.1 requires google-genai<2.0.0,>=1.66.0; python_version >= \"3.10\", but you have google-genai 2.4.0 which is incompatible.\n", "google-adk 1.29.0 requires google-genai<2.0.0,>=1.64.0, but you have google-genai 2.4.0 which is incompatible.\u001b[0m\u001b[31m\n", "\u001b[0m" ] } ], "source": [ "%pip install -U -q \"google-genai>=2.9.0\"" ] }, { "cell_type": "markdown", "metadata": { "id": "RjSSAHkENMVP" }, "source": [ "### Setup your API key\n", "\n", "To run the following cell, your API key must be stored it in a Colab Secret named `GEMINI_API_KEY`. If you don't already have an API key or you aren't sure how to create a Colab Secret, see [Authentication ![image](https://storage.googleapis.com/generativeai-downloads/images/colab_icon16.png)](../quickstarts/Authentication.ipynb) for an example." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "b8P6cvjtNMVP" }, "outputs": [], "source": [ "from google.colab import userdata\n", "\n", "GEMINI_API_KEY = userdata.get('GEMINI_API_KEY')" ] }, { "cell_type": "markdown", "metadata": { "id": "Mg_TLymZNMVQ" }, "source": [ "### Initialize SDK client\n", "\n", "With the new SDK, now you only need to initialize a client with you API key." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "lMfvdM5KNMVQ" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Client ready!\n" ] } ], "source": [ "import uuid\n", "from google import genai\n", "from google.genai import types\n", "from IPython.display import Markdown\n", "\n", "client = genai.Client(api_key=GEMINI_API_KEY)\n", "\n", "# The default managed agent.\n", "AGENT = \"antigravity-preview-05-2026\"\n", "\n", "# Generate a unique suffix for this notebook session to prevent agent ID conflicts\n", "UNIQUE_SUFFIX = uuid.uuid4().hex[:8]\n", "\n", "print(\"Client ready!\")" ] }, { "cell_type": "markdown", "metadata": { "id": "9SnU4eEeNMVQ" }, "source": [ "## 1. Simple questions — the agent as an LLM\n", "\n", "The simplest way to use a managed agent is to ask it a question, just like you'd call a standard Gemini model. Pass `agent=\"antigravity-preview-05-2026\"` and `environment=\"remote\"` to create a fresh Linux sandbox for the agent.\n", "\n", "This works, but it's a bit like driving a Formula 1 car to the grocery store — the agent has code execution, web search, and file management capabilities that are all sitting idle for a simple factual question." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "D2ox65ixNMVQ" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/tmp/ipykernel_2790/271594579.py:1: UserWarning: Interactions usage is experimental and may change in future versions.\n", " interaction = client.interactions.create(\n" ] }, { "data": { "text/markdown": [ "The capital of France is Paris." ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=\"What is the capital of France?\",\n", " environment=\"remote\",\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "vb6H3iZdNMVQ" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Status: completed\n", "Interaction ID: v1_Chc1SlFNYXVmUE51YXNqckVQM09laGlBYxIXNUpRTWF1ZlBOdWFzanJFUDNPZWhpQWM\n", "Environment ID: fc155701-ea68-4846-973f-f2943e35cdde\n" ] } ], "source": [ "# The response also includes metadata about the agent's sandbox.\n", "print(f\"Status: {interaction.status}\")\n", "print(f\"Interaction ID: {interaction.id}\")\n", "print(f\"Environment ID: {interaction.environment_id}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "nRBBPcB-NMVR" }, "source": [ "Notice the `environment_id` in the response. That's the agent's persistent Linux sandbox. Even for this simple question, a full container was provisioned. Let's make use of that persistence next." ] }, { "cell_type": "markdown", "metadata": { "id": "88W0gyTwNMVR" }, "source": [ "## 2. Multi-turn conversations\n", "\n", "Since each agent runs in a persistent sandbox, you can **continue where you left off** by reusing the `environment_id` and linking turns with `previous_interaction_id`.\n", "\n", "This is fundamentally different from stateless `model=` calls. The agent has a true *persistent environment* — files it creates stick around, packages it installs remain available, and conversation context is preserved." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "sMc09-FINMVR" }, "outputs": [ { "data": { "text/markdown": [ "**Turn 1:** Hi Alice! Nice to meet you. \n", "\n", "I have created a `knowledge.md` file in the working directory and saved your profile details:\n", "* **Name:** Alice\n", "* **Role:** Software Engineer\n", "\n", "I'll keep this in mind for our future interactions! Let me know how I can help you with your tasks today." ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Turn 1: Introduce yourself.\n", "turn1 = client.interactions.create(\n", " agent=AGENT,\n", " input=\"Hi! My name is Alice and I'm a software engineer. Remember that in a knowledge.md doc.\",\n", " environment= \"remote\",\n", ")\n", "\n", "Markdown(f\"**Turn 1:** {turn1.output_text}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "fLXDXnbfNMVR" }, "outputs": [ { "data": { "text/markdown": [ "**Turn 2:** Based on the information in `knowledge.md`, here are your details:\n", "\n", "* **Name:** Alice\n", "* **What you do:** You are a Software Engineer." ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Turn 2: Ask whether the agent remembers.\n", "# Pass environment_id and previous_interaction_id to continue the conversation.\n", "turn2 = client.interactions.create(\n", " agent=AGENT,\n", " input=\"what's my name and what do I do?\",\n", " environment= turn1.environment_id,\n", ")\n", "\n", "Markdown(f\"**Turn 2:** {turn2.output_text}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "hS5R6P9CNMVR" }, "source": [ "The agent remembered across turns because you passed `environment` with the previous environment ID — same sandbox, which means same files.\n", "\n", "You could have achieved the same result using `previous_interaction_id` to keep the history of the previous conversation, but that would not have showcased the environement specificities.\n", "\n", "This is how you build stateful, multi-turn workflows. See the [Getting Started notebook](./Get_started_interactions_api.ipynb) for `model=`-based multi-turn using `previous_interaction_id` alone (without environments)." ] }, { "cell_type": "markdown", "metadata": { "id": "GKwq6D8_NMVR" }, "source": [ "## 3. Using tools — where the agent shines\n", "\n", "This is where managed agents go beyond a standard chat model. The antigravity-preview-05-2026 agent has **built-in tools** it uses autonomously — you don't declare them, just describe your goal and the agent figures out what to use.\n", "\n", "| Tool | Description |\n", "|------|-------------|\n", "| `bash` | Execute shell commands in the sandbox |\n", "| `google_search` | Search the web for current information |\n", "| `url_context` | Fetch and extract text from URLs |\n", "| `write_file` | Create or overwrite files in the sandbox |\n", "| `read_file` | Read file contents from the sandbox |\n", "| `list_files` | List directory contents |\n", "| `delete_file` | Remove files from the sandbox |\n", "\n", "For the standard `model=`-based tools (Google Search grounding, code execution, function calling), see the [Getting Started notebook](./Get_started_interactions_api.ipynb) and the dedicated tool notebooks:\n", "- [Code Execution](./Code_Execution.ipynb)\n", "- [Search Grounding](./Search_Grounding.ipynb)\n", "- [Function Calling](./Function_calling.ipynb)" ] }, { "cell_type": "markdown", "metadata": { "id": "zxbwQpvYNMVR" }, "source": [ "### Code execution\n", "\n", "Ask a computational question and the agent will write code, run it in its sandbox, and return the verified result." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "fSblgpRQNMVR" }, "outputs": [ { "data": { "text/markdown": [ "I have created and executed a Python script to compute the first 20 Fibonacci numbers.\n", "\n", "### Python Script (`fibonacci.py`)\n", "\n", "Here is the code written to `fibonacci.py`:\n", "\n", "```python\n", "def fibonacci(n):\n", " if n <= 0:\n", " return []\n", " elif n == 1:\n", " return [0]\n", " \n", " fib_sequence = [0, 1]\n", " while len(fib_sequence) < n:\n", " fib_sequence.append(fib_sequence[-1] + fib_sequence[-2])\n", " return fib_sequence\n", "\n", "if __name__ == \"__main__\":\n", " n = 20\n", " fib_numbers = fibonacci(n)\n", " print(f\"The first {n} Fibonacci numbers are:\")\n", " print(fib_numbers)\n", "```\n", "\n", "### Execution Output\n", "\n", "Running this script yields the following result:\n", "\n", "```text\n", "The first 20 Fibonacci numbers are:\n", "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]\n", "```" ], "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=(\n", " \"Write a Python script that computes the first 20 Fibonacci numbers. \"\n", " \"Run it and show the output.\"\n", " ),\n", " environment=\"remote\",\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "YxDfGufgNMVS" }, "source": [ "### Inspecting steps — what the agent actually did\n", "\n", "The `steps` field in the response shows the agent's reasoning chain: its thoughts, tool calls, tool results, and final output. This is useful for debugging and understanding the agent's behavior." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ENSVCrbPNMVS" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--- Step 0 [thought] ---\n", "\n", "--- Step 1 [function_call] ---\n", " Tool: write_file\n", " Args: {'path': '/fibonacci.py', 'content': 'def fibonacci(n):\\n if n <= 0:\\n return []\\n elif n == 1:\\n return [0]\\n \\n fib_sequence = [0, 1]\\n while len(fib_sequence) < n:\\n fib_sequence.append(fib_sequence[-1] + fib_sequence[-2])\\n return fib_sequence\\n\\nif __name_\n", "\n", "--- Step 2 [function_result] ---\n", " Tool: write_file\n", "\n", "--- Step 3 [code_execution_call] ---\n", "\n", "--- Step 4 [code_execution_result] ---\n", "\n", "--- Step 5 [model_output] ---\n", " Text: I have created and executed a Python script to compute the first 20 Fibonacci numbers.\n", "\n", "### Python Script (`fibonacci.py`)\n", "\n", "Here is the code written to `fibonacci.py`:\n", "\n", "```python\n", "def fibonacci(n):\n", " if n <= 0:\n", " return []\n", " elif n == 1:\n", " return [0]\n", " \n", " fib_sequence = [0, 1]\n", " \n", "\n" ] } ], "source": [ "# Inspect the steps from the Fibonacci interaction above.\n", "for i, step in enumerate(interaction.steps):\n", " step_type = step.type\n", " print(f\"--- Step {i} [{step_type}] ---\")\n", "\n", " # Tool call steps show which tool was invoked and with what arguments.\n", " if hasattr(step, \"name\") and step.name:\n", " print(f\" Tool: {step.name}\")\n", " if hasattr(step, \"arguments\"):\n", " args_str = str(step.arguments)[:300]\n", " print(f\" Args: {args_str}\")\n", "\n", " # Content steps contain the agent's text output.\n", " if hasattr(step, \"content\") and step.content:\n", " for c in step.content:\n", " if hasattr(c, \"text\"):\n", " print(f\" Text: {c.text[:300]}\")\n", " print()" ] }, { "cell_type": "markdown", "metadata": { "id": "zKAJNEl2NMVS" }, "source": [ "### Web search\n", "\n", "The agent can search the web autonomously when it needs up-to-date information." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "sJcr7EovNMVS" }, "outputs": [ { "data": { "text/markdown": [ "The week of May 12–19, 2026, has been exceptionally busy for Google, dominated by the kickoff of **Google I/O 2026** and its preliminary event, **\"The Android Show.\"** \n", "\n", "Here are the top three major news stories about Google from this week:\n", "\n", "---\n", "\n", "### 1. Google Unveils the \"Googlebook\" — The Successor to the Chromebook\n", "Google announced a brand-new, high-end laptop class called the **Googlebook**, designed to compete directly with Apple’s MacBooks and Microsoft’s AI-centric Copilot+ PCs [1, 2]. \n", "* **The Software:** The laptops will run a newly designed hybrid, on-device OS codenamed **\"Aluminium OS\"** (based on Android and ChromeOS) [2]. \n", "* **Key Features:** Googlebooks are marketed as \"the first laptops built from the ground up for Gemini Intelligence\" [2]. They will feature a nostalgic retro-style **rainbow light bar** on the lid, along with unique interaction features like **\"Magic Pointer\"**—a gesture tool that lets users shake their cursor to prompt context-aware AI suggestions (e.g., automatically scheduling a calendar event from highlighted text) [1].\n", "\n", "### 2. Android 17 Showcased Along with Hardware Exclusion Backlash\n", "During *The Android Show*, Google gave a detailed preview of **Android 17**, highlighting deep integration with on-device AI [3, 5]. However, the announcement has triggered a wave of user dissatisfaction regarding device compatibility [4].\n", "* **The Features:** Android 17 introduces **Gemini Intelligence**, which handles multi-step app automation and custom AI widgets [5]. Other features include **\"Rambler\"** (a multilingual dictation tool capable of polishing spoken text, including natural code-switching like Hinglish) and native **AirDrop compatibility** for Google's Quick Share on supported devices [5].\n", "* **The Controversy:** Google revealed that the marquee Gemini Intelligence features require the advanced hardware specs of **Gemini Nano v3** [4]. This rules out almost all older phones—including the highly popular **Pixel 9 series** launched just a year prior—prompting widespread backlash from premium phone buyers over artificial hardware limitations [4].\n", "\n", "### 3. Google DeepMind Launches \"AI for the Planet\" Climate Accelerator in APAC\n", "Google DeepMind announced its inaugural **Asia-Pacific (APAC) Accelerator** program dedicated to environmental sustainability [6, 7].\n", "* **The Program:** This three-month program is tailored for climate tech startups, non-profits, and research teams operating in the APAC region [7]. \n", "* **What it Offers:** Kicking off with an in-person bootcamp in Singapore, selected teams will receive intensive, direct mentorship from Google AI researchers, technical assistance, and support in integrating DeepMind's scientific and generative AI models to help scale real-world climate and nature resilience projects [6, 7].\n", "\n", "---\n", "\n", "### Sources\n", "* [1] [PCMag: Reinventing the Laptop with Googlebook](https://www.pcmag.com/opinions/with-the-googlebook-im-betting-on-google-to-reinvent-the-laptop-again)\n", "* [2] [Axios: Googlebook Built for Gemini](https://www.axios.com/2026/05/12/googlebook-ai-chromebook-announcement)\n", "* [3] [CNET: Android 17 Previewed with Gemini Intelligence](https://www.cnet.com/tech/services-and-software/android-17-preview/)\n", "* [4] [HowToGeek: Steep Requirements for Gemini Intelligence](https://www.howtogeek.com/gemini-intelligence-android-17-device-requirements/)\n", "* [5] [Times of India: Google I/O 2026 Android 17 Updates](https://timesofindia.indiatimes.com/technology/tech-news/google-i/o-2026-android-17-updates-android-xr-gemini-intelligence-and-other-things-to-expect/articleshow/131198172.cms)\n", "* [6] [Google Blog: Launching Google DeepMind APAC Accelerator Program](https://blog.google/innovation-and-ai/models-and-research/google-deepmind/accelerator-ai-for-the-planet/)\n", "* [7] [ESG News: DeepMind APAC Climate Accelerator](https://esgnews.com/google-deepmind-launches-apac-ai-accelerator-to-scale-climate-nature-solutions/)" ], "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=\"What were the top 3 news stories about Google this week? Summarize them briefly.\",\n", " environment=\"remote\",\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "x3gXhc0iNMVS" }, "source": [ "### File operations\n", "\n", "The agent can create, read, and manage files in its sandbox. Files persist within the environment across turns." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "H7MCgKaQNMVS" }, "outputs": [ { "data": { "text/markdown": [ "I have created the Python script `analysis.py` and executed it. \n", "\n", "### Python Script (`analysis.py`)\n", "```python\n", "import random\n", "import statistics\n", "\n", "# Set seed for reproducibility (optional, but good for consistency)\n", "random.seed(42)\n", "\n", "# Generate 50 random numbers between 1 and 100\n", "numbers = [random.uniform(1, 100) for _ in range(50)]\n", "\n", "# Calculate statistics\n", "mean_val = statistics.mean(numbers)\n", "median_val = statistics.median(numbers)\n", "stdev_val = statistics.stdev(numbers)\n", "\n", "# Print results\n", "print(\"Generated 50 random numbers:\")\n", "print([round(num, 2) for num in numbers])\n", "print(f\"\\nMean: {mean_val:.4f}\")\n", "print(f\"Median: {median_val:.4f}\")\n", "print(f\"Standard Deviation: {stdev_val:.4f}\")\n", "```\n", "\n", "### Execution Output\n", "```text\n", "Generated 50 random numbers:\n", "[64.3, 3.48, 28.23, 23.1, 73.91, 67.99, 89.33, 9.61, 42.77, 3.95, 22.65, 51.03, 3.63, 20.68, 65.34, 54.95, 22.82, 59.34, 81.13, 1.64, 80.78, 70.12, 34.68, 16.39, 95.76, 34.32, 10.18, 10.57, 84.9, 60.77, 80.91, 73.24, 54.09, 97.34, 38.47, 55.65, 83.11, 62.23, 86.31, 58.16, 70.75, 5.54, 23.56, 29.65, 8.9, 24.05, 11.0, 28.52, 63.93, 37.12]\n", "\n", "Mean: 45.6177\n", "Median: 46.9002\n", "Standard Deviation: 29.0356\n", "```" ], "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ask the agent to create a file, run it, and show results.\n", "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=(\n", " \"Create a Python file called 'analysis.py' that generates 50 random numbers, \"\n", " \"computes mean, median, and standard deviation, then prints the results. \"\n", " \"Run it and show the output.\"\n", " ),\n", " environment=\"remote\",\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "XKjakKQeNMVT" }, "source": [ "## 4. Loading data into the agent's sandbox\n", "\n", "You can inject files into the agent's environment **before it starts** using `sources`. This is how you provide data, configuration, or code for the agent to work with.\n", "\n", "| Source type | Description | Best for |\n", "|------------|-------------|----------|\n", "| `inline` | Embed content directly (max 75 KB) | Config files, small scripts |\n", "| `gcs` | Load from Google Cloud Storage | Large datasets |\n", "| `repository` | Load from GitHub | Code repositories |" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "UIk8asfTNMVT" }, "outputs": [ { "data": { "text/markdown": [ "Based on the data in `workspace/data.csv`, **Charlie** scored the highest with a score of **95**.\n", "\n", "Here is a breakdown of the scores in the file:\n", "\n", "| Name | Age | City | Score |\n", "| :--- | :--- | :--- | :--- |\n", "| **Charlie** | **42** | **Berlin** | **95 (Highest)** |\n", "| Alice | 28 | Paris | 92 |\n", "| Eve | 26 | Sydney | 91 |\n", "| Diana | 31 | Tokyo | 88 |\n", "| Bob | 35 | London | 87 |" ], "text/plain": [ "" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Inject a CSV file inline and ask the agent to analyze it.\n", "csv_data = \"\"\"name,age,city,score\n", " Alice,28,Paris,92\n", " Bob,35,London,87\n", " Charlie,42,Berlin,95\n", " Diana,31,Tokyo,88\n", " Eve,26,Sydney,91\"\"\"\n", "\n", "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=\"Read the file data.csv, analyze it, and tell me who scored the highest.\",\n", " environment={\n", " \"type\": \"remote\",\n", " \"sources\": [\n", " {\n", " \"type\": \"inline\",\n", " \"content\": csv_data,\n", " \"target\": \"/workspace/data.csv\",\n", " }\n", " ],\n", " },\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "rYke35E_NMVT" }, "source": [ "You can also load from other sources:\n", "\n", "```python\n", "# From Google Cloud Storage\n", "{\"type\": \"gcs\", \"source\": \"gs://my-bucket/data/\", \"target\": \"/workspace/data/\"}\n", "\n", "# From a GitHub repository\n", "{\"type\": \"repository\", \"source\": \"https://github.com/user/repo\", \"target\": \"/workspace/repo/\"}\n", "```\n", "\n", "You can combine multiple sources in a single request — the agent will have access to all of them at startup." ] }, { "cell_type": "markdown", "metadata": { "id": "bsS2zsZ_NcCh" }, "source": [ "**Pro tip:** You can use that to add skills to you agent, as you'll see next." ] }, { "cell_type": "markdown", "metadata": { "id": "NwzuReusNMVT" }, "source": [ "## 5. Creating reusable custom agents\n", "\n", "So far, every interaction has used the base `antigravity-preview-05-2026` agent with inline instructions. Once you've found a setup that works well, you can **persist it into a named custom agent** that bundles:\n", "\n", "- **Instructions** — system prompt that defines the agent's behavior\n", "- **Environment** — pre-configured sandbox with files and sources\n", "- **Skills** — `SKILL.md` files that teach the agent specialized capabilities\n", "\n", "This is the recommended workflow:\n", "1. **Prototype** with `agent=\"antigravity-preview-05-2026\"` — iterate on instructions, sources, and prompts\n", "2. **Create** a named agent via the `/agents` endpoint\n", "3. **Invoke** your agent by name from any client" ] }, { "cell_type": "markdown", "metadata": { "id": "QQNU6OmANMVT" }, "source": [ "### Creating a custom agent" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TJ9D3F52NMVT" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✓ Agent created: my-data-analyst\n" ] } ], "source": [ "# Create a custom data analysis agent using the SDK.\n", "my_agent = client.agents.create(\n", " id=f\"my-data-analyst-{UNIQUE_SUFFIX}\",\n", " base_agent=AGENT,\n", " system_instruction=(\n", " \"You are a data analysis assistant. \"\n", " \"Always write Python code using pandas to answer questions. \"\n", " \"Show your code and output clearly. \"\n", " \"When creating visualizations, save them as PNG files.\"\n", " ),\n", " base_environment={\n", " \"type\": \"remote\",\n", " },\n", ")\n", "\n", "print(f\"✓ Agent created: {my_agent.id}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "BT3Z3UXLNMVT" }, "source": [ "### Using a custom agent\n", "\n", "Once created, invoke your agent by name. It will follow its instructions automatically." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "5dVpmZlJNMVT" }, "outputs": [ { "data": { "text/markdown": [ "I have generated a sample dataset of 100 sales records and performed a data analysis to find the top 5 products by total revenue. \n", "\n", "The sample dataset has been successfully saved to `sales_data.csv` and the corresponding visualization has been saved as `top_products_revenue.png`.\n", "\n", "Below is the complete, step-by-step breakdown of the Python code used, the data previews, and the detailed analysis.\n", "\n", "---\n", "\n", "### Step 1: Generating the Sample Dataset\n", "\n", "We used `pandas` and `numpy` to generate a realistic set of 100 sales transactions. To make the data realistic, we mapped individual products to base prices and applied a random variance of $\\pm 10\\%$ to mimic real-world discounts and transactional pricing.\n", "\n", "Here is the Python code to generate and save the dataset:\n", "\n", "```python\n", "import pandas as pd\n", "import numpy as np\n", "\n", "# Set seed for reproducibility\n", "np.random.seed(42)\n", "\n", "# Define products and base unit prices\n", "product_prices = {\n", " 'Laptop': 1000,\n", " 'Smartphone': 700,\n", " 'Tablet': 400,\n", " 'Headphones': 150,\n", " 'Smartwatch': 250,\n", " 'Monitor': 300,\n", " 'Keyboard': 80,\n", " 'Mouse': 50,\n", " 'Printer': 200,\n", " 'Router': 120\n", "}\n", "\n", "products = list(product_prices.keys())\n", "regions = ['North', 'East', 'South', 'West']\n", "\n", "# Generate 100 sales records\n", "n_records = 100\n", "random_products = np.random.choice(products, size=n_records)\n", "random_regions = np.random.choice(regions, size=n_records)\n", "random_quantities = np.random.randint(1, 15, size=n_records)\n", "\n", "# Calculate revenue with small price variations (e.g., matching discounts/promotions)\n", "random_revenues = []\n", "for prod, qty in zip(random_products, random_quantities):\n", " base_price = product_prices[prod]\n", " variation = np.random.uniform(0.9, 1.1)\n", " revenue = round(base_price * qty * variation, 2)\n", " random_revenues.append(revenue)\n", "\n", "# Create DataFrame\n", "df = pd.DataFrame({\n", " 'product': random_products,\n", " 'region': random_regions,\n", " 'revenue': random_revenues,\n", " 'quantity': random_quantities\n", "})\n", "\n", "# Save to CSV\n", "df.to_csv('sales_data.csv', index=False)\n", "```\n", "\n", "#### Dataset Preview (First 10 Rows of `sales_data.csv`)\n", "\n", "| | product | region | revenue | quantity |\n", "|---|---|---|---|---|\n", "| **0** | Keyboard | West | $73.49 | 1 |\n", "| **1** | Headphones | East | $485.75 | 3 |\n", "| **2** | Mouse | North | $540.04 | 10 |\n", "| **3** | Smartwatch | West | $3,079.86 | 12 |\n", "| **4** | Keyboard | South | $619.40 | 8 |\n", "| **5** | Router | South | $1,280.19 | 11 |\n", "| **6** | Tablet | East | $2,508.46 | 6 |\n", "| **7** | Keyboard | West | $690.83 | 8 |\n", "| **8** | Mouse | North | $484.84 | 9 |\n", "| **9** | Smartwatch | South | $1,055.98 | 4 |\n", "\n", "---\n", "\n", "### Step 2: Analyzing the Top 5 Products by Total Revenue\n", "\n", "Using `pandas`, we grouped the dataset by **product**, aggregated the total revenue and quantities, and extracted the top 5 highest-grossing products.\n", "\n", "```python\n", "import pandas as pd\n", "\n", "# Load the generated dataset\n", "df = pd.read_csv('sales_data.csv')\n", "\n", "# Group and aggregate\n", "product_analysis = df.groupby('product').agg(\n", " total_revenue=('revenue', 'sum'),\n", " total_quantity=('quantity', 'sum'),\n", " average_transaction_value=('revenue', 'mean'),\n", " transaction_count=('product', 'count')\n", ").reset_index()\n", "\n", "# Sort by revenue and get top 5\n", "top_5_products = product_analysis.sort_values(by='total_revenue', ascending=False).head(5)\n", "\n", "# Format and display\n", "formatted_top_5 = top_5_products.copy()\n", "formatted_top_5['total_revenue'] = formatted_top_5['total_revenue'].map('${:,.2f}'.format)\n", "formatted_top_5['average_transaction_value'] = formatted_top_5['average_transaction_value'].map('${:,.2f}'.format)\n", "print(formatted_top_5.to_string(index=False))\n", "```\n", "\n", "#### Analysis Output\n", "\n", "| product | total_revenue | total_quantity | average_transaction_value | transaction_count |\n", "| :--- | :--- | :--- | :--- | :--- |\n", "| **Laptop** | \\$54,845.99 | 54 | \\$7,835.14 | 7 |\n", "| **Smartphone** | \\$48,213.02 | 70 | \\$4,821.30 | 10 |\n", "| **Tablet** | \\$20,754.26 | 49 | \\$2,306.03 | 9 |\n", "| **Smartwatch** | \\$17,331.45 | 70 | \\$1,733.14 | 10 |\n", "| **Printer** | \\$14,501.77 | 71 | \\$1,208.48 | 12 |\n", "\n", "#### Key Insights from the Product Analysis\n", "1. **Laptops** generated the highest total revenue (**\\$54,845.99**), despite having a lower transaction count (7) and total quantity sold (54). This is driven by their high unit value, resulting in a high average transaction value of **\\$7,835.14**.\n", "2. **Smartphones** are a close second with **\\$48,213.02** in total revenue, driven by solid volume (70 units across 10 transactions).\n", "3. **Printers** saw the highest volume of transactions (12) and units sold (71) among the top 5, but because of their lower unit price, they sit in fifth place with **\\$14,501.77** in revenue.\n", "\n", "---\n", "\n", "### Step 3: Visualizing the Results\n", "\n", "We used `matplotlib` and `seaborn` to build a publication-quality bar chart representing the top 5 products and saved it as `top_products_revenue.png`.\n", "\n", "```python\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "# Set style\n", "sns.set_theme(style=\"whitegrid\")\n", "plt.figure(figsize=(10, 6))\n", "\n", "# Create barplot\n", "barplot = sns.barplot(\n", " data=top_5_products,\n", " x='total_revenue',\n", " y='product',\n", " palette='viridis',\n", " hue='product',\n", " legend=False\n", ")\n", "\n", "# Annotate each bar with its revenue value\n", "for p in barplot.patches:\n", " width = p.get_width()\n", " plt.text(\n", " width + 500, # X offset\n", " p.get_y() + p.get_height() / 2,\n", " f'${width:,.2f}',\n", " ha='left',\n", " va='center',\n", " fontsize=10,\n", " fontweight='bold',\n", " color='#333333'\n", " )\n", "\n", "plt.title('Top 5 Products by Total Revenue', fontsize=16, fontweight='bold', pad=20)\n", "plt.xlabel('Total Revenue (USD)', fontsize=12, labelpad=10)\n", "plt.ylabel('Product', fontsize=12, labelpad=10)\n", "plt.xlim(0, top_5_products['total_revenue'].max() * 1.15) # Add margin for labels\n", "\n", "plt.tight_layout()\n", "plt.savefig('top_products_revenue.png', dpi=300)\n", "plt.close()\n", "```\n", "\n", "The resulting high-resolution chart (`top_products_revenue.png`) provides a clear visual distinction between the premium earners (Laptops and Smartphones) and the mid-tier products (Tablets, Smartwatches, and Printers).\n", "\n", "---\n", "\n", "### Step 4: Bonus Analysis — Regional Revenue Performance\n", "\n", "To add more value to the analysis, we also grouped the dataset by **region** to see where sales are strongest.\n", "\n", "```python\n", "# Group by region\n", "regional_sales = df.groupby('region').agg(\n", " total_revenue=('revenue', 'sum'),\n", " total_quantity=('quantity', 'sum'),\n", " transaction_count=('product', 'count')\n", ").reset_index()\n", "\n", "# Format and display\n", "regional_sales['total_revenue'] = regional_sales['total_revenue'].map('${:,.2f}'.format)\n", "print(regional_sales.to_string(index=False))\n", "```\n", "\n", "#### Regional Performance Output\n", "\n", "| region | total_revenue | total_quantity | transaction_count |\n", "| :--- | :--- | :--- | :--- |\n", "| **South** | \\$75,877.06 | 210 | 31 |\n", "| **North** | \\$48,667.68 | 190 | 26 |\n", "| **East** | \\$40,204.98 | 126 | 21 |\n", "| **West** | \\$29,124.71 | 118 | 22 |\n", "\n", "* **Regional Takeaway:** The **South** region is by far the strongest performer, contributing **\\$75,877.06** in total revenue (over 39% of all sales) and leading in both quantities sold and transaction count." ], "text/plain": [ "" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Invoke the custom agent.\n", "interaction = client.interactions.create(\n", " agent=f\"my-data-analyst-{UNIQUE_SUFFIX}\",\n", " input=(\n", " \"Generate a sample dataset of 100 sales records with columns: \"\n", " \"product, region, revenue, quantity. \"\n", " \"Find the top 5 products by total revenue and show the analysis.\"\n", " ),\n", " environment=\"remote\",\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "pRLZYk3lNMVU" }, "source": [ "### Creating an agent with pre-loaded data\n", "\n", "You can define the agent's environment with sources, so data is ready before the agent starts:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "dgIi36gkNMVU" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✓ Agent created: my-gemini-api-agent\n" ] } ], "source": [ "# Create an agent with GCS sources pre-loaded using the SDK.\n", "my_slides_agent = client.agents.create(\n", " id=f\"my-gemini-api-agent-{UNIQUE_SUFFIX}\",\n", " base_agent=AGENT,\n", " system_instruction=(\n", " \"You are a software engineer speciliazed in the Gemini API. \"\n", " \"Use the skills available in /.agents/skills/ to create amazing apps.\"\n", " ),\n", " base_environment={\n", " \"type\": \"remote\",\n", " \"sources\": [\n", " {\n", " \"type\": \"repository\",\n", " \"source\": \"https://github.com/google-gemini/gemini-skills\",\n", " \"target\": \"/.agents/skills\",\n", " }\n", " ],\n", " },\n", ")\n", "\n", "print(f\"✓ Agent created: {my_slides_agent.id}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "sI2ddOK2WFu1" }, "outputs": [ { "data": { "text/markdown": [ "As a software engineer specializing in the **Gemini API**, I have access to three highly specialized skill sets that allow me to design, build, and deploy cutting-edge AI-driven applications. \n", "\n", "Here is what I can do with my specialized skills:\n", "\n", "---\n", "\n", "### 1. Gemini API Development (`gemini-api-dev`)\n", "This skill covers standard, hosted model integration across multiple programming languages (Python, JavaScript/TypeScript, Go, and Java) using the modern unified `google-genai` SDKs.\n", "\n", "* **Implement Next-Generation Models:** I can build apps using Google's latest models, such as **Gemini 3.5 Flash** (`gemini-3.5-flash`), **Gemini 3.1 Pro** (`gemini-3.1-pro-preview`), and the **Gemma 4** open-model family (`gemma-4-31b-it`). *(Note: Legacy models like `gemini-2.0-*` and `gemini-1.5-*` are deprecated and avoided.)*\n", "* **Multimodal Applications:** I can build solutions that seamlessly process and analyze diverse inputs including text, high-resolution images, audio, and video files.\n", "* **Structured Outputs:** I can configure models to return strict, type-safe JSON data matching your precise schemas for reliable application-level parsing.\n", "* **Function Calling & Tool Use:** I can extend model capabilities by declaring client-side functions that the model can choose to call based on user queries, allowing real-time integrations with external APIs and databases.\n", "\n", "---\n", "\n", "### 2. Gemini Interactions API (`gemini-interactions-api`)\n", "This skill focuses on stateful, timeline-based conversational flows, background research tasks, and advanced autonomous agent architectures. It adheres to the modern May 2026 schema, which utilizes a structured `steps` timeline.\n", "\n", "* **Stateful Conversations:** I can build chat applications that maintain server-side interaction history, making multi-turn chat simpler and more context-rich without having to manually pass complete histories back and forth.\n", "* **Deep Research Agent Orchestration:** I can construct autonomous pipelines using agents like `deep-research-preview-04-2026` to run background, multi-step, interactive research tasks with automatic progress-polling patterns.\n", "* **Remote Managed Agents:** I can spin up and orchestrate **Antigravity Agents** (`antigravity-preview-05-2026`) operating in remote, Google-hosted Linux sandboxes. These agents can autonomously execute Python or Node.js code, run Bash commands, manage remote workspaces, and search the web.\n", "* **Custom Multi-Agent Systems:** I can program custom remote agents by defining base environments, seeding GitHub repositories directly into the sandboxes, and overriding system instructions to build dedicated code-reviewers, data-analysts, or security auditors.\n", "\n", "---\n", "\n", "### 3. Gemini Live API Development (`gemini-live-api-dev`)\n", "This skill allows me to build low-latency, real-time, bidirectional voice and video streaming experiences over WebSockets.\n", "\n", "* **Low-Latency Audio Conversations:** Using `gemini-3.1-flash-live-preview`, I can configure continuous microphone-to-speaker conversational apps with automatic Voice Activity Detection (VAD) and smart interruption handling (e.g., clearing the playback queue if the user speaks over the assistant).\n", "* **Video Frame Streaming:** I can feed continuous camera or screen-share streams (such as JPEG-encoded frames) to the live session alongside raw PCM audio inputs to create interactive visual companions.\n", "* **Real-Time Native \"Thinking\":** I can adjust the model's performance on the fly by configuring its `thinkingLevel` (from minimal to high) to trade off between complex reasoning depth and ultra-low latency.\n", "* **Production-Ready Audio Integrations:** I can deploy and configure Live API connectors for third-party WebRTC/WebSocket frameworks like **LiveKit**, **Pipecat (Daily)**, **Fishjam**, and **Vision Agents**.\n", "* **Secure Ephemeral Tokens:** I can implement secure authentication pipelines that generate short-lived, client-side ephemeral tokens so your browser or mobile client can communicate directly with the Gemini Live WebSocket server without ever exposing your private API keys.\n", "\n", "***\n", "\n", "### How I Can Help You Today\n", "Whether you want to create a **real-time voice-activated assistant**, launch a **stateful research agent that browses and writes code**, or simply **migrate a legacy `generateContent` codebase to the modern May 2026 schema**, I am fully equipped to design and implement the complete architecture for you. \n", "\n", "Let me know what kind of application you would like to build!" ], "text/plain": [ "" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Invoke the custom agent.\n", "interaction = client.interactions.create(\n", " agent=f\"my-gemini-api-agent-{UNIQUE_SUFFIX}\",\n", " input=\"Tell me what you can do with your skills?\",\n", " environment=\"remote\",\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "6PmdtMJHNMVU" }, "source": [ "### Forking from an existing environment\n", "\n", "If you've already set up a sandbox you like (installed packages, created files, etc.), you can fork it into a new agent using the `environment_id` from a previous interaction:\n", "\n", "```python\n", "my_forked_agent = client.agents.create(\n", " id=\"my-forked-agent\",\n", " base_agent=AGENT,\n", " system_instruction=\"Your custom instructions here.\",\n", " base_environment={\"env_id\": \"YOUR_ENVIRONMENT_ID\"},\n", ")\n", "```\n", "\n", "This captures the exact state of that sandbox — all installed packages, files, and configuration." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2hlOfaRKXRlC" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✓ Agent forked: my-forked-agent\n" ] } ], "source": [ "my_forked_agent = client.agents.create(\n", " id=\"my-forked-agent\",\n", " base_agent=\"my-gemini-api-agent\",\n", " system_instruction=\"I want all your apps to use the Live API\",\n", " base_environment={\"env_id\": interaction.environment_id},\n", ")\n", "print(f\"✓ Agent forked: {my_forked_agent.id}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "5H1F85IONMVZ" }, "source": [ "### Managing agents (CRUD)\n", "\n", "The `/agents` endpoint supports full lifecycle management:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "KyOhiUA_NMVZ" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Your agents:\n", "- $AGENT_ID\n", "- code-reviewer\n", "- data-analyst\n", "- my-gemini-api-agent\n", "- my-forked-agent\n", "\n", "Agent details for my-data-analyst:\n", "Base agent: antigravity-preview-05-2026\n", "System instruction: You are a data analysis assistant. Always write Python code using pandas to answer questions. Show your code and output clearly. When creating visualizations, save them as PNG files.\n" ] } ], "source": [ "# List all your agents.\n", "print(\"Your agents:\")\n", "for agent in client.agents.list().agents:\n", " print(f\"- {agent.id}\")\n", "\n", "# Get a specific agent's details.\n", "agent = client.agents.get(id=\"my-data-analyst\")\n", "print(f\"\\nAgent details for {agent.id}:\")\n", "print(f\"Base agent: {agent.base_agent}\")\n", "print(f\"System instruction: {agent.system_instruction}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "yDbAK9xhNMVZ" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✓ Deleted my-data-analyst\n", "✓ Deleted my-forked-agent\n", "✓ Deleted my-gemini-api-agent\n" ] } ], "source": [ "# Clean up: delete the agents we created.\n", "for agent_name in [\"my-data-analyst\", \"my-forked-agent\", \"my-gemini-api-agent\"]:\n", " try:\n", " client.agents.delete(id=agent_name)\n", " print(f\"✓ Deleted {agent_name}\")\n", " except Exception as e:\n", " print(f\" Failed to delete {agent_name}: {e}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "6Lus2up5NMVZ" }, "source": [ "### Agent directory structure\n", "\n", "Behind the API, an agent is defined by a simple set of files. This is what gets deployed when you create one:\n", "\n", "```\n", "my-agent/\n", "├── agent.yaml # Configuration: base agent, tools, environment\n", "├── AGENTS.md # System instructions (loaded automatically)\n", "├── skills/ # Custom SKILL.md files that extend capabilities\n", "└── workspace/ # Files seeded into the remote sandbox at startup\n", "```\n", "\n", "- **`agent.yaml`** maps directly to the `/agents` API resource\n", "- **`AGENTS.md`** provides system instructions — automatically loaded by the harness\n", "- **`skills/`** contains specialized `SKILL.md` files the agent discovers and uses\n", "- **`workspace/`** files are injected into the sandbox at startup\n", "\n", "This file-based structure makes agents easy to version-control, share, and iterate on. Check the [documentation](https://ai.google.dev/gemini-api/docs/custom-agents#file-based_customization) for more details." ] }, { "cell_type": "markdown", "metadata": { "id": "eHySEmQqNMVZ" }, "source": [ "## 6. Streaming\n", "\n", "For longer tasks, enable streaming with `stream=True` to get real-time updates as the agent works. Instead of waiting for the complete response, you receive a stream of **Server-Sent Events (SSE)** that let you show progress to the user.\n", "\n", "### Event types\n", "\n", "The stream delivers events that tell you what the agent is doing:\n", "\n", "| Event type | Meaning | What to do |\n", "|------------|---------|------------|\n", "| `interaction.created` | The interaction was created | Store the `id` for later reference |\n", "| `interaction.status_update` | Status changed (e.g., `in_progress`) | Update UI status indicator |\n", "| `step.start` | A new step began (thinking, tool call, output) | Show a loading indicator |\n", "| `step.delta` | Incremental content — a chunk of text, thought, or tool output | **Append to display** — this is the main content |\n", "| `step.stop` | A step completed | Hide loading indicator |\n", "| `interaction.completed` | The agent finished all work | Finalize the UI |\n", "\n", "The `step.delta` events are where the content lives. Each delta has a `type` (e.g., `text`, `thought`, `function_call`, `function_result`) and content you can render incrementally." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "WdUB9kEmNMVa" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[interaction.created]\n", "[step.start]\n", "[step.stop]\n", "[step.start]\n", "Endless cradle of deep, dark blue,\n", "Where whispered secrets of the wind come through.\n", "With restless tides that rise and fall,\n", "You sing an ancient song to all.\n", "\n", "A shimmering mirror to the sky,\n", "Where white-winged gulls and currents fly.\n", "In depth and silence, wild and free,\n", "The timeless heart of the mighty sea.[step.stop]\n", "[interaction.completed]\n", "\n", "\n", "--- Collected 4 text chunks ---\n" ] } ], "source": [ "# Stream a response and collect the text as it arrives.\n", "stream = client.interactions.create(\n", " agent=AGENT,\n", " input=\"Write a short poem about the ocean.\",\n", " stream=True,\n", " environment=\"remote\",\n", ")\n", "\n", "collected_text = []\n", "\n", "for event in stream:\n", " # Show the event type so you can see the lifecycle.\n", " if event.event_type in (\"interaction.created\", \"step.start\", \"step.stop\", \"interaction.completed\"):\n", " print(f\"[{event.event_type}]\")\n", "\n", " # step.delta events carry the actual content.\n", " elif event.event_type == \"step.delta\":\n", " delta = event.delta\n", " if hasattr(delta, \"text\") and delta.text:\n", " print(delta.text, end=\"\", flush=True)\n", " collected_text.append(delta.text)\n", "\n", "print(f\"\\n\\n--- Collected {len(collected_text)} text chunks ---\")" ] }, { "cell_type": "markdown", "metadata": { "id": "RE6f1XqINMVa" }, "source": [ "## 7. Advanced features\n", "\n", "### Network configuration\n", "\n", "By default, the agent's sandbox has unrestricted outbound network access. You can control this with the `network` field:\n", "- **Allowlist specific domains** — only requests to listed domains are permitted\n", "- **Inject credentials** — automatically add headers (API keys, tokens) to outbound requests\n", "- **Disable network** — set `network: \"disabled\"` to block all outbound traffic" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "axpOnwYUNMVa" }, "outputs": [ { "data": { "text/markdown": [ "To list the available models in the Gemini API, we can send a `GET` request to the `/v1beta/models` endpoint of `generativelanguage.googleapis.com`. Because authentication is automatically handled by the environment's egress proxy, no API key or Authorization header is required.\n", "\n", "### Curl Command\n", "\n", "```bash\n", "curl -s \"https://generativelanguage.googleapis.com/v1beta/models\"\n", "```\n", "\n", "### First 3 Models Returned\n", "\n", "Here is the JSON payload of the first 3 models returned from the API response:\n", "\n", "```json\n", "[\n", " {\n", " \"name\": \"models/gemini-3.5-flash\",\n", " \"version\": \"001\",\n", " \"displayName\": \"Gemini 3.5 Flash\",\n", " \"inputTokenLimit\": 16777216,\n", " \"outputTokenLimit\": 2048,\n", " \"supportedGenerationMethods\": [\n", " \"generateContent\",\n", " \"countTokens\"\n", " ],\n", " },\n", " {\n", " \"name\": \"models/gemini-3.1-flash-lite\",\n", " \"displayName\": \"Gemini 3.1 Flash Lite\",\n", " \"description\": \"Gemini 3.1 Flash Lite\",\n", " \"inputTokenLimit\": 1048576,\n", " \"outputTokenLimit\": 65536,\n", " \"supportedGenerationMethods\": [\n", " \"generateContent\",\n", " \"countTokens\"\n", " ],\n", " \"temperature\": 1,\n", " \"topP\": 0.95,\n", " \"topK\": 64,\n", " ,\n", " \"maxTemperature\": 2,\n", " \"thinking\": true\n", " },\n", " {\n", " \"name\": \"models/gemini-3.1-pro-preview\",\n", " \"version\": \"001\",\n", " \"displayName\": \"Gemini 3.1 Pro Preview\",\n", " \"description\": \"Gemini 3.1 Pro Preview\",\n", " \"inputTokenLimit\": 1048576,\n", " \"outputTokenLimit\": 65536,\n", " \"supportedGenerationMethods\": [\n", " \"generateContent\",\n", " \"countTokens\"\n", " ],\n", " \"temperature\": 1,\n", " \"topP\": 0.95,\n", " \"topK\": 64,\n", " \"maxTemperature\": 2,\n", " \"thinking\": true\n", " }\n", "]\n", "```" ], "text/plain": [ "" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Allow the agent to call only the Gemini API, with an auto-injected API key.\n", "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=\"Use curl to call the Gemini API and list available models. Show the first 3.\",\n", " environment={\n", " \"type\": \"remote\",\n", " \"network\": {\n", " \"allowlist\": [\n", " {\n", " \"domain\": \"generativelanguage.googleapis.com\",\n", " \"transform\": [{\"x-goog-api-key\": GEMINI_API_KEY}],\n", " },\n", " ]\n", " },\n", " },\n", ")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "markdown", "metadata": { "id": "pnkBpK_yNMVa" }, "source": [ "### Download environment snapshots\n", "\n", "You can download all the files the agent created or modified as a tar archive. This lets you retrieve the agent's work products — code, data, reports — from the sandbox." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "55JDOBbjNMVa" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Environment ID: cbcfb191-7b88-46dc-ba0b-008e32ed7cb5\n" ] }, { "data": { "text/markdown": [ "I have successfully created the `project` directory containing a `README.md` and a `hello.py` script. \n", "\n", "Here are the files created inside `/project`:\n", "- `README.md` — A simple markdown documentation file.\n", "- `hello.py` — A basic Python script that prints a greeting." ], "text/plain": [ "" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import subprocess\n", "import tarfile\n", "import os\n", "\n", "# Create an interaction where the agent produces files.\n", "interaction = client.interactions.create(\n", " agent=AGENT,\n", " input=(\n", " \"Create a directory called 'project' with a README.md and a hello.py script. \"\n", " \"List the files you created.\"\n", " ),\n", " environment=\"remote\",\n", ")\n", "\n", "env_id = interaction.environment_id\n", "print(f\"Environment ID: {env_id}\")\n", "\n", "Markdown(interaction.output_text)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ZaId6U5cNMVa" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Files in snapshot:\n", " . (0 bytes)\n", " ./project (0 bytes)\n", " ./project/README.md (74 bytes)\n", " ./project/hello.py (93 bytes)\n" ] } ], "source": [ "# Download the environment snapshot.\n", "download_url = (\n", " f\"https://generativelanguage.googleapis.com/v1beta/\"\n", " f\"files/environment-{env_id}:download?alt=media\"\n", ")\n", "\n", "result = subprocess.run(\n", " [\"curl\", \"-L\", \"-s\", \"-o\", \"snapshot.tar\",\n", " \"-H\", f\"x-goog-api-key: {GEMINI_API_KEY}\",\n", " download_url],\n", " capture_output=True, text=True,\n", ")\n", "\n", "if os.path.exists(\"snapshot.tar\") and os.path.getsize(\"snapshot.tar\") > 0:\n", " with tarfile.open(\"snapshot.tar\") as tar:\n", " print(\"Files in snapshot:\")\n", " for member in tar.getmembers():\n", " print(f\" {member.name} ({member.size} bytes)\")\n", "else:\n", " print(\"Snapshot not available (environment may have expired).\")" ] }, { "cell_type": "markdown", "metadata": { "id": "oDN6BIagNMVa" }, "source": [ "## Next steps\n", "\n", "You've walked through the core capabilities of managed agents:\n", "\n", "1. ✅ **Simple Q&A** — the agent can answer questions like an LLM\n", "2. ✅ **Multi-turn** — persistent sandbox enables stateful conversations\n", "3. ✅ **Built-in tools** — code execution, web search, file management\n", "4. ✅ **Data loading** — inject files via inline, GCS, or GitHub sources\n", "5. ✅ **Custom agents** — reusable configurations with instructions, skills, and environment\n", "6. ✅ **Streaming** — real-time updates as the agent works\n", "7. ✅ **Advanced** — network control and environment snapshots\n", "\n", "### Learn more\n", "\n", "- **[Getting Started notebook](./Get_started_interactions_api.ipynb)** — the `model=`-based Interactions API for standard generation, multi-turn, and tools\n", "- **[Managed Agents documentation](https://ai.google.dev/gemini-api/docs/eap/gemini-agents/gemini-agents)** — full reference for the agent API\n", "- **[Code Execution](./Code_Execution.ipynb)** — model-based code execution\n", "- **[Search Grounding](./Search_Grounding.ipynb)** — model-based web search\n", "- **[Function Calling](./Function_calling.ipynb)** — custom function declarations" ] } ], "metadata": { "colab": { "name": "Get_started_managed_agents.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 0 }