Vertex AI Agent Tools: Connect Your Agent to APIs with ADK and Terraform 🔌

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MyrinNew
    Senior Member
    • Feb 2024
    • 5175

    #1

    Vertex AI Agent Tools: Connect Your Agent to APIs with ADK and Terraform 🔌

    An agent without tools is just a chatbot. ADK gives your Vertex AI agent five ways to connect to APIs - function tools, OpenAPI tools, MCP tools, built-in tools, and agent-as-tool. Here's how to wire them up with Terraform provisioning the infrastructure.


    In the previous post, we deployed a Vertex AI agent with ADK and Agent Engine. It can reason and hold conversations, but without tools it can only generate text. Ask it to check a stock price or create a ticket, and it describes what it would do instead of doing it.


    ADK's tool ecosystem is where GCP agents shine. Unlike AWS where action groups require Lambda functions and OpenAPI schemas as separate resources, ADK lets you define tools as Python functions, OpenAPI specs, MCP servers, or even other agents - all in the same codebase. The agent decides which tool to use based on the user's request, and ADK handles the execution. Terraform provisions the infrastructure; Python defines the capabilities. 🎯


    🔧 Five Tool Types in ADK

    Function Tool Plain Python function Custom logic, calculations, internal APIs
    OpenAPI Tool Auto-generated from OpenAPI spec Existing REST APIs with documentation
    MCP Tool Connects to MCP servers Third-party services (GitHub, Slack, DBs)
    Built-in Tool Google Search, Code Execution Web search, running generated code
    Agent Tool Uses another agent as a tool Delegation, specialized sub-tasks


    This post focuses on function tools and OpenAPI tools - the two patterns that connect your agent to your own APIs.


    🔧 Function Tools: Python Functions as Agent Capabilities

    The simplest way to give an agent a capability. Write a Python function with a docstring, and ADK makes it available as a tool:






    # agent_source/tools.py

    import urllib.request
    import json

    def get_exchange_rate(
    currency_from: str,
    currency_to: str,
    ) -> dict:
    """Get the current exchange rate between two currencies.

    Use this when the user asks about currency conversion or exchange rates.

    Args:
    currency_from: The source currency code (e.g., USD, EUR, GBP).
    currency_to: The target currency code (e.g., USD, EUR, GBP).

    Returns:
    A dictionary with the exchange rate.
    """
    url = f"https://api.frankfurter.dev/v1/latest?base={currency_from}&symbols={currency_to}"
    req = urllib.request.Request(url)
    with urllib.request.urlopen(req) as resp:
    data = json.loads(resp.read())

    rate = data["rates"].get(currency_to, "N/A")
    return {"rate": rate, "from": currency_from, "to": currency_to}







    The docstring is the schema. ADK uses type hints for parameter types and the docstring for descriptions. The agent reads these to decide when and how to call the function. Clear docstrings drive better tool selection, just like OpenAPI descriptions in AWS action groups.


    Wire Tools to the Agent





    # agent_source/agent.py

    import json
    from google.adk.agents import Agent
    from google.adk.models.vertexai import VertexAi
    from tools import get_exchange_rate

    with open("config.json") as f:
    config = json.load(f)

    model = VertexAi(model=config["model_id"])

    agent = Agent(
    name=config["agent_name"],
    model=model,
    instruction=config["instruction"],
    tools=[get_exchange_rate], # Register tools here
    )







    That's it. No Lambda function, no OpenAPI schema file, no IAM permissions for tool invocation. The function runs in the same process as the agent.


    Multiple Function Tools

    Add as many tools as needed. The agent decides which to call:






    from tools import get_exchange_rate, get_weather, create_ticket

    agent = Agent(
    name=config["agent_name"],
    model=model,
    instruction="""You are a helpful assistant.
    Use get_exchange_rate for currency questions.
    Use get_weather for weather queries.
    Use create_ticket for support requests.""",
    tools=[get_exchange_rate, get_weather, create_ticket],
    )







    Instruction quality matters. Tell the agent when to use each tool. Without guidance, the model guesses based on docstrings alone - explicit instructions improve tool selection accuracy.


    🔧 OpenAPI Tools: Auto-Generate from API Specs

    For existing REST APIs with OpenAPI documentation, ADK can generate tools automatically:






    # agent_source/agent_with_openapi.py

    from google.adk.agents import Agent
    from google.adk.models.vertexai import VertexAi
    from google.adk.tools.openapi_tool.openapi_spec_parser. openapi_toolset import OpenAPIToolset

    model = VertexAi(model=config["model_id"])

    # Load OpenAPI spec and generate tools
    petstore_toolset = OpenAPIToolset(
    spec_str=open("petstore_openapi.yaml").read(),
    spec_str_type="yaml",
    )

    agent = Agent(
    name="api-agent",
    model=model,
    instruction="You manage the pet store. Use the API tools to list, create, and look up pets.",
    tools=[petstore_toolset],
    )







    OpenAPIToolset parses the spec and creates one RestApiTool per operation. The agent sees list_pets, create_pet, get_pet_by_id as separate callable tools. When the agent decides to call one, ADK handles the HTTP request automatically.


    OpenAPI Tool with Authentication

    For APIs requiring auth, pass credentials to the toolset:






    from google.adk.tools.openapi_tool.auth.auth_helpers import token_to_scheme_credential

    toolset = OpenAPIToolset(
    spec_str=open("my_api.yaml").read(),
    spec_str_type="yaml",
    auth_scheme_credential=token_to_scheme_credential(
    "bearer", "my-api-token"
    ),
    )







    🔧 Terraform: Infrastructure for Tool-Connected Agents

    Terraform provisions the APIs, IAM, and any GCP services your tools need. The tool logic stays in Python.


    APIs for External Connectivity





    # agent/apis.tf

    resource "google_project_service" "agent_tools" {
    for_each = toset([
    "aiplatform.googleapis.com",
    "cloudfunctions.googleapis.com",
    "secretmanager.googleapis.com", # For API keys
    "run.googleapis.com", # For Agent Engine
    ])
    project = var.project_id
    service = each.value
    }







    Store API Keys in Secret Manager





    # agent/secrets.tf

    resource "google_secret_manager_secret" "api_keys" {
    for_each = var.tool_api_keys
    secret_id = "${var.environment}-${each.key}-api-key"
    project = var.project_id

    replication {
    auto {}
    }
    }

    resource "google_secret_manager_secret_version" "api_keys" {
    for_each = var.tool_api_keys
    secret = google_secret_manager_secret.api_keys[each.key].id
    secret_data = each.value
    }

    # Grant agent SA access to secrets
    resource "google_secret_manager_secret_iam_member" "agent_access" {
    for_each = var.tool_api_keys
    secret_id = google_secret_manager_secret.api_keys[each.key].id
    role = "roles/secretmanager.secretAccessor"
    member = "serviceAccount:${google_service_account.agent.ema il}"
    }







    Config with Tool Settings





    # agent/config.tf

    resource "local_file" "agent_config" {
    filename = "${path.module}/agent_source/config.json"
    content = jsonencode({
    project_id = var.project_id
    location = var.region
    model_id = var.agent_model.id
    agent_name = "${var.environment}-${var.agent_name}"
    instruction = var.agent_instruction
    tool_config = {
    api_key_secret = "${var.environment}-exchange-rate-api-key"
    }
    })
    }







    📐 Sequential Tool Use

    ADK supports chaining tools where one tool's output feeds another. Describe the sequence in the agent's instructions:






    agent = Agent(
    name="research-agent",
    model=model,
    instruction="""You are a research assistant.
    When the user asks for analysis:
    1. First use search_documents to find relevant data
    2. Then use summarize_data to create a summary
    3. Finally use create_report to format the output""",
    tools=[search_documents, summarize_data, create_report],
    )







    The agent follows the sequence, passing results between tools automatically. No orchestration code needed.


    ⚠️ Gotchas and Tips

    Docstrings are your schema. ADK infers tool descriptions from Python docstrings and type hints. Missing or vague docstrings mean the agent can't properly select or parameterize the tool.


    Tool limitations. Some built-in tools (Google Search, Code Execution) can't be combined with other tools in the same agent. Check ADK documentation for compatibility.


    Long-running tools. For operations that take more than a few seconds, use LongRunningFunctionTool which supports async execution with polling.


    Testing locally. ADK's CLI (adk run) and dev UI let you test tool interactions locally before deploying to Agent Engine. Always test tool selection with varied prompts.


    ⏭️ What's Next

    This is Post 2 of the GCP AI Agents with Terraform series.
    • Post 1: Deploy First Vertex AI Agent 🤖
    • Post 2: Agent Tools - Connect to APIs (you are here) 🔌
    • Post 3: Multi-Agent with Agent Engine
    • Post 4: Agent + Google Search Grounding





    Your agent can now take action. Function tools, OpenAPI tools, MCP integrations - ADK makes your Python functions into agent capabilities. The model reasons; your code executes. 🔌


    Found this helpful? Follow for the full AI Agents with Terraform series! 💬




    More...
Working...