Agents and Tool Use
How does tool use (function calling) work?
- You send tool definitions: name, description (when to use it), JSON schema of inputs.
- The model replies with a
tool_useblock (tool name + JSON input) andstop_reason: "tool_use". - Your code runs the function and sends a
tool_resultblock with the sametool_use_id. - The model continues, maybe calling more tools, until
stop_reason: "end_turn".
The model never runs code itself; your application stays in control. The Anthropic SDK's tool runner automates this loop.
What is the difference between a workflow and an agent?
In a workflow, your code fixes the steps (route → retrieve → answer). In an agent, the model decides the next step in a loop with tools. Workflows are cheaper, faster and easier to test; agents handle open-ended tasks. Good practice: start with the simplest option and add agency only where evals show it helps.
How do you stop an agent from looping forever or doing something harmful?
- Hard limits in code: max iterations, token or cost budget, timeout.
- Detect repeated identical tool calls.
- Least privilege: narrow tools (e.g.
refund(order_id, amount ≤ 2000)) instead of generic ones. - Human approval for irreversible or high-value actions, enforced inside the tool.
- Validate every tool input; log every call for audit.
What is MCP, and how is it different from function calling?
The Model Context Protocol is an open protocol (introduced by Anthropic in 2024) for connecting AI apps to tools and data. An MCP server exposes tools, resources and prompts over JSON-RPC (stdio or Streamable HTTP); any MCP host (Claude Desktop, Claude Code, IDEs, your app) can use it. Function calling is the model-level mechanism; MCP is a standard way to package and share tools, which the host turns into function-calling tool definitions.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("shopease")
@mcp.tool()
def get_order_status(order_id: str) -> str:
"""Get a ShopEase order's status. Use when the user mentions an order ID."""
return lookup(order_id)
mcp.run()