diff --git a/contributing/samples/managed_agent/custom_agent/README.md b/contributing/samples/managed_agent/custom_agent/README.md new file mode 100644 index 00000000..4e0f11ac --- /dev/null +++ b/contributing/samples/managed_agent/custom_agent/README.md @@ -0,0 +1,87 @@ +# Managed Agent: Create and Use a Custom Agent + +> For setup, authentication, backends, and background on `ManagedAgent`, see the +> [ManagedAgent guide](../../../../docs/guides/agents/managed_agent/index.md). + +## Overview + +This sample demonstrates the **control-plane lifecycle** of a custom managed +agent: creating a persistent, named agent *resource* — its persona and +server-side tools baked in — then driving it and deleting it. + +You do **not** need a custom resource just to set a persona or server-side +tools. `ManagedAgent` accepts both inline: `instruction=...` for a persona (see +the [`system_instruction`](../system_instruction) sample) and +`tools=[google_search]` for server-side tools (see the [`basic`](../basic) +sample). Create a custom resource when you instead want a reusable, +server-managed agent that other apps and sessions can share by id. + +This module drives that lifecycle: run it with `--create` to provision the +resource (reusing the genai client `ManagedAgent` already holds, +`root_agent.api_client`, which exposes both interactions and agent +create/delete), then drive `root_agent` with `adk web` / `adk run`, and +`--delete` to remove it. + +## Setup + +Custom-agent creation requires the **GEAP / Vertex** backend (`global` +location); the Gemini API backend cannot create agent resources. For backend +selection, authentication, and credentials, see the +[ManagedAgent guide](../../../../docs/guides/agents/managed_agent/index.md#prerequisites). + +## Usage + +```bash +# 1. Create the custom agent (once). +python contributing/samples/managed_agent/custom_agent/agent.py --create + +# 2. Chat with it. Provisioning can take a few minutes (longer for the first +# agent in a project), so wait a moment after --create before the first turn. +adk run contributing/samples/managed_agent/custom_agent +# or: adk web + +# 3. Delete it when done. +python contributing/samples/managed_agent/custom_agent/agent.py --delete +``` + +Creation is asynchronous: `--create` returns before the agent is fully ready, so +if the first turn fails with a "not found" / "being created" error, wait a few +seconds and retry. + +## Sample Inputs + +Answers are grounded in live search, so exact text varies: + +- `What are the most significant AI announcements this week?` + + The created agent's persona makes it answer **concisely** and **cite its + sources**, using server-side `google_search`. + +- `Summarize that in one sentence.` + + A follow-up turn that reuses the recovered interaction (multi-turn chaining). + +## Graph + +```mermaid +graph LR + User -->|message| CustomManagedAgent + CustomManagedAgent -->|interactions.create| ManagedAgentsAPI + ManagedAgentsAPI -->|server-side google_search| ManagedAgentsAPI + ManagedAgentsAPI -->|streamed events| CustomManagedAgent + CustomManagedAgent -->|answer| User +``` + +## How To + +- **Define the custom agent**: pass a `system_instruction` (persona) and + server-side `tools` (here `{'type': 'google_search'}`) to + `client.agents.create(...)`, extending the `antigravity-preview-05-2026` base + agent. +- **Reuse the ManagedAgent client**: `root_agent.api_client` is the genai client + `ManagedAgent` already holds; its `agents.create` / `agents.delete` cover the + control plane. +- **Provision a sandbox**: `ManagedAgent(environment={'type': 'remote'})` gives + each interaction a remote sandbox (required to run the agent). +- **Run it**: `--create` provisions, `--delete` removes; in between, `root_agent` + is a normal `BaseAgent`, so `adk web` / `adk run` (or a `Runner`) drive it. diff --git a/contributing/samples/managed_agent/custom_agent/__init__.py b/contributing/samples/managed_agent/custom_agent/__init__.py new file mode 100644 index 00000000..4015e47d --- /dev/null +++ b/contributing/samples/managed_agent/custom_agent/__init__.py @@ -0,0 +1,15 @@ +# 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. + +from . import agent diff --git a/contributing/samples/managed_agent/custom_agent/agent.py b/contributing/samples/managed_agent/custom_agent/agent.py new file mode 100644 index 00000000..fbea1216 --- /dev/null +++ b/contributing/samples/managed_agent/custom_agent/agent.py @@ -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. + +"""Create, use, and delete a custom managed-agent resource. + +This sample demonstrates the control-plane lifecycle of a custom managed agent: +creating a persistent, named agent *resource* (its persona and server-side tools +baked in), then driving it and deleting it. + +You don't need a custom resource just to set a persona or server-side tools -- +``ManagedAgent`` accepts both inline (``instruction=...`` and +``tools=[google_search]``; see the ``system_instruction`` and ``basic`` +samples). Create a custom resource when you instead want a reusable, +server-managed agent that other apps and sessions can share by id. + +Run this module with ``--create`` once to provision the resource, then drive +``root_agent`` with ``adk web`` / ``adk run +contributing/samples/managed_agent/custom_agent``, then ``--delete`` to remove +it. See the README for the required GEAP/Vertex setup. + + python contributing/samples/managed_agent/custom_agent/agent.py --create + python contributing/samples/managed_agent/custom_agent/agent.py --delete +""" + +import argparse + +from dotenv import load_dotenv +from google.adk.agents import ManagedAgent + +load_dotenv() + +_AGENT_ID = 'adk-custom-search-agent' + +_SYSTEM_INSTRUCTION = ( + 'You are a concise research assistant. Use Google Search to ground every ' + 'answer in current sources, cite the sources you used, and keep answers to ' + 'a few sentences.' +) + +root_agent = ManagedAgent( + name='custom_managed_agent', + agent_id=_AGENT_ID, + environment={'type': 'remote'}, +) + + +def main() -> None: + """Create or delete the custom managed-agent resource.""" + parser = argparse.ArgumentParser( + description='Create or delete the custom managed agent for this sample.' + ) + parser.add_argument( + '--create', action='store_true', help='Create the custom managed agent.' + ) + parser.add_argument( + '--delete', action='store_true', help='Delete the custom managed agent.' + ) + args = parser.parse_args() + if not (args.create or args.delete): + parser.print_help() + return + + # ManagedAgent's genai client also exposes agent create/delete. + client = root_agent.api_client + if args.create: + client.agents.create( + id=_AGENT_ID, + base_agent='antigravity-preview-05-2026', + system_instruction=_SYSTEM_INSTRUCTION, + tools=[{'type': 'google_search'}], + ) + print(f'Created "{_AGENT_ID}".') + if args.delete: + client.agents.delete(id=_AGENT_ID) + print(f'Deleted "{_AGENT_ID}".') + + +if __name__ == '__main__': + main()