Tool use (also called function calling) lets you hand Claude a menu of operations your application can perform. Instead of replying with prose, Claude can respond with a structured request — "call get_order_status with order_id: 4711" — which your code executes, returning the result so Claude can finish the job. Tool use is generally available for Claude on Google Vertex AI, with one boundary to internalize up front: Google's documentation states it plainly — Claude models on the platform support client tools, but server tools are not supported. Anything the tool actually does happens in your code, on your infrastructure, under your IAM. (The exceptions are the basic web search variant and tool search, which Vertex does run server-side; Anthropic-hosted tools like code execution and web fetch are unavailable here.)
Defining a tool schema
A tool is a name, a description, and a JSON Schema describing its parameters. The description does the heavy lifting — Claude decides when to use the tool based on it, so write it like documentation for a new colleague:
tools = [{
"name": "get_order_status",
"description": "Look up the current status and ETA of a customer "
"order by its numeric order ID.",
"input_schema": {
"type": "object",
"properties": {"order_id": {"type": "string",
"description": "The order number, digits only"}},
"required": ["order_id"],
},
}]
Parsing tool_use blocks and closing the loop
When Claude decides to call a tool, the response arrives with stop_reason: "tool_use" and the content includes a tool_use block carrying an id, the tool name, and the parsed input. Your job is to execute the call and send back a tool_result block that echoes the same ID, then let Claude continue:
from anthropic import AnthropicVertex
client = AnthropicVertex(project_id="my-project", region="global")
messages = [{"role": "user", "content": "Where is order 4711?"}]
while True:
resp = client.messages.create(model="claude-sonnet-5",
max_tokens=1024, tools=tools, messages=messages)
if resp.stop_reason != "tool_use":
break
messages.append({"role": "assistant", "content": resp.content})
results = [{"type": "tool_result", "tool_use_id": b.id,
"content": run_tool(b.name, b.input)} # your code
for b in resp.content if b.type == "tool_use"]
messages.append({"role": "user", "content": results})
Three details keep this loop honest in production. First, append the assistant's entire content back into the history, not just the tool blocks — if the model produced thinking blocks alongside a tool request, they must be returned unmodified. Second, a single response can contain several tool_use blocks; answer all of them in one user turn, as the loop above does. Third, when a tool fails, don't swallow the error — return a tool_result describing the failure so Claude can recover or tell the user, and put a hard cap on loop iterations so a confused exchange can't spin forever.
Enterprise notes for the Vertex surface
Because tools execute in your application, the security story is refreshingly conventional: the service account calling Vertex needs only roles/aiplatform.user, while each tool's side effects are governed by whatever permissions your code already has. Treat tool inputs as untrusted user input — validate them before acting, exactly as you would form data. Structured outputs and strict tool use are generally available on Vertex if you need schema-guaranteed arguments, and fine-grained tool streaming works if you stream responses. Tool definitions count as input tokens on every request, which makes a long tool catalogue a natural candidate for prompt caching.
Testing the loop before it meets users
Tool-use quality is measurable in a way free-form generation is not, so take advantage. Build a small suite of real tasks and assert on concrete outcomes: did Claude pick the right tool, were the arguments valid against your schema, did the loop terminate within its iteration cap, and did the final answer actually incorporate the tool result rather than ignoring it. Run the suite whenever you change a tool description, add a tool, or move to a new model version — description wording and model generation are the two variables that most often shift tool-selection behavior. Because the tool executor is ordinary code you wrote, it can be unit-tested separately with mocked model output, which keeps the expensive live-model tests focused on the decision-making layer.
Where to go next
For designing the surrounding agent, see the agentic loop pattern and Agent vs Workflow. For what server-side tooling Vertex lacks and the workarounds, see The Feature Gaps.