DEV Community

Cover image for Vertex AI Agent Tools: Connect Your Agent to APIs with ADK and Terraform πŸ”Œ
Suhas Mallesh
Suhas Mallesh

Posted on

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

Tool Type What It Does Best For
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}
Enter fullscreen mode Exit fullscreen mode

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
)
Enter fullscreen mode Exit fullscreen mode

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],
)
Enter fullscreen mode Exit fullscreen mode

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],
)
Enter fullscreen mode Exit fullscreen mode

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"
    ),
)
Enter fullscreen mode Exit fullscreen mode

πŸ”§ 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
}
Enter fullscreen mode Exit fullscreen mode

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.email}"
}
Enter fullscreen mode Exit fullscreen mode

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"
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

πŸ“ 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],
)
Enter fullscreen mode Exit fullscreen mode

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! πŸ’¬

Top comments (0)