Building a simple agent with Claude
By Iain,
This article covers how to build a simple AI agent using Claude, using a hypothetical sales function as a worked example.
A sales team does not need a fully autonomous agent that orchestrates twelve tools and makes decisions about deal strategy. What it needs, at first, is a thing that answers a question correctly and saves someone 15 minutes of tab-switching. That is the agent worth building. And Claude’s API makes it straightforward to build one.
What “agent” means when you strip out the marketing
The word “agent” has been overused to the point of losing its meaning, so let me clarify. In this context, an agent is a programme that interprets a natural-language request, determines whether to invoke one or more external tools to answer it, and then calls those tools to provide a synthesised response. It has no memory of previous interactions across sessions, no autonomous goal-setting, and no recursive self-improvement. Essentially, when you strip away the jargon, it is a language model with a telephone.
Claude’s tool use API is what makes this possible. You define a set of functions (called “tools”) with names, descriptions, and JSON schemas for their inputs. You send these definitions along with the user’s message. Claude reads the message, decides which tools (if any) are required, and emits a structured tool_use block with the function name and typed arguments. Your code executes the function, sends back the result, and Claude produces a final response.
The trust boundary is very clear and worth emphasising because Claude never calls your functions directly. It expresses intent, and your application determines whether to honour that intent, executes the actual call, and returns the result. This is less dramatic than “autonomous agent” but far more useful, because you have full control over every interaction with your systems.
The agent that earns its keep on day one
Forget any full orchestration fantasies for a moment. Consider what a sales rep actually does 40 times a day that a simple agent could handle.
A rep receives a meeting invite. Before the call, they need the account’s recent activity in the CRM, any open support tickets, the last 3 emails exchanged, and perhaps the latest earnings call or press release for the prospect. Currently, this involves opening a CRM like HubSpot, searching for the account, navigating to the activity timeline, switching to the support tool, switching to email, and opening a new Google Chrome tab. This process takes about seven minutes—perhaps ten—repeated before every call.
An internal agent connected to two or three tools can streamline this into a single request. “Give me a prep brief for tomorrow’s call with Acme Corp” becomes a command to the CRM, a query to the ticketing system, and optionally a web search for recent news. Claude compiles these results into a clear, concise summary. The rep can read it in 45 seconds.
This is not science fiction. It is a Python script with four tool definitions and a system prompt.
Building it with Claude’s tool use
Here is the skeleton of what the tool definitions look like when you wire them up to Claude. I am keeping this deliberately minimal, because the important thing is not the specific CRM you use but the pattern itself.
import anthropic
client = anthropic.Anthropic()
tools = [
{
"name": "get_account_summary",
"description": "Retrieves account details and recent activity from the CRM. Returns company name, deal stage, owner, last activity date, and the five most recent interactions.",
"input_schema": {
"type": "object",
"properties": {
"account_name": {
"type": "string",
"description": "The company name to look up"
}
},
"required": ["account_name"]
}
},
{
"name": "get_open_tickets",
"description": "Retrieves open support tickets for a given account. Returns ticket ID, subject, priority, status, and days since creation.",
"input_schema": {
"type": "object",
"properties": {
"account_name": {
"type": "string",
"description": "The company name to look up tickets for"
}
},
"required": ["account_name"]
}
},
{
"name": "get_recent_emails",
"description": "Retrieves the three most recent email threads with a given account. Returns subject lines, dates, and a brief summary of each thread.",
"input_schema": {
"type": "object",
"properties": {
"account_name": {
"type": "string",
"description": "The company name to search emails for"
}
},
"required": ["account_name"]
}
}
]
The tool definitions are where most of the intelligence resides. Claude decides which tools to invoke mainly based on the descriptions you provide. A vague description leads to a vague tool selection. Conversely, a description that clearly specifies what should be returned and what the input should look like leads to dependable behaviour. Anthropic’s own documentation emphasises this point, and in practice, it is the most significant lever you have to influence agent quality.
The message loop is the other part. When Claude determines it needs a tool, it responds with a stop_reason of tool_use and one or more tool_use content blocks. Your application parses these, executes the corresponding function (which is typically an API call to your CRM, ticketing system, or email provider), and then sends the result back as a tool_result message. Claude then generates its final response.
def run_agent(user_message):
messages = [{"role": "user", "content": user_message}]
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=4096,
system="You are an internal sales assistant. When asked to prepare for a meeting, gather account details, open tickets, and recent emails, then produce a concise briefing document.",
tools=tools,
messages=messages,
)
# Loop until Claude is done calling tools
while response.stop_reason == "tool_use":
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=4096,
system="You are an internal sales assistant. When asked to prepare for a meeting, gather account details, open tickets, and recent emails, then produce a concise briefing document.",
tools=tools,
messages=messages,
)
return response.content[0].text
The execute_tool function is where you plug in your actual integrations. For a HubSpot CRM, this might be a call to their REST API. For Zendesk tickets, their API. For email, the Gmail API or whatever your organisation uses. Each tool maps to a single API call, which keeps the system predictable and debuggable.
Why Sonnet and not Opus
A quick note on model selection because this impacts cost. Claude Sonnet 4.5 is generally the best choice for most internal agent workloads. It reliably handles tool selection, delivers clean synthesis, and costs significantly less per request than Opus. Currently, Sonnet processes input tokens at $3 per million and output tokens at $15 per million, compared to Opus at $15 and $75, respectively.
For a sales prep agent used around 200 times daily across a team, the difference between a $6 daily API bill and a $30 one adds up over a year. In my experience, Sonnet’s tool selection accuracy is more than adequate for agents with fewer than ten tools. Reserve Opus for tasks that genuinely require front-line reasoning, such as complex deal analysis or contract review.
Connecting to a CRM without a headache
If your team uses HubSpot, Salesforce, or other CRMs supporting the Model Context Protocol (MCP), you can avoid writing custom API wrappers. MCP offers standardised integrations that automatically manage authentication and API calls. For example, Close CRM recently introduced a Claude integration allowing you to query leads, generate deal-stage reports, and audit opportunities via natural language.
For those without a pre-built MCP connector, expect to spend a few hours per integration. The CRM’s REST API returns JSON; you write a wrapper function matching tool inputs to API parameters and formatting the response, then register this wrapper within your tool definitions. It’s straightforward plumbing and basic engineering.
The more interesting question is which tools to make available. It’s tempting to grant the agent access to every CRM endpoint, filter, and field. Resist this urge. Start with no more than three tools. Ensure they work reliably. Observe how your team actually uses the agent. Then add tools based on real requests, not assumptions about what they might need.
The conversation with your sales team
Technical implementation is the straightforward part. The more challenging aspect is managing expectations with the people who will be using it.
Sales teams have been promised AI-powered everything for three years now, and most of what they’ve received are auto-generated email templates that sound as if they were written by a committee of strangers. The bar for credibility is low, but the bar for actual adoption is high because reps are busy, sceptical, and have limited tolerance for tools that perform correctly only 80% of the time.
Be honest about what the agent can and cannot do. It can pull data from connected systems and compile it into a readable format. However, it cannot read the room in a negotiation or determine if the VP of Engineering truly has budget authority. It is a research assistant, not a strategist. Framing it this way helps prevent the inevitable disappointment cycle that hampers the adoption of most internal AI tools.
Also, be transparent about accuracy. Claude is very good at synthesising structured data, but it may occasionally misinterpret an ambiguous CRM field or overlook a nuance in a ticket thread. The prep brief it generates should be regarded as a starting point that saves ten minutes of gathering information, not as a substitute for the representative’s own judgment. If you present it this way from the outset, you avoid building false trust that could be shattered the first time the agent produces an error.
Where to go once the simple version functions
Once your three-tool agent is operational and your reps are using it daily, two paths become available.
The first is expanding the tool set. Adding a web search enables the agent to pull recent news about the account. Adding calendar access allows it to check when the last meeting occurred. Incorporating a tool that queries your analytics platform for product usage data is beneficial if you sell software. Each addition requires a few hours of integration work and significantly improves the prep brief.
The second path is more ambitious and requires careful consideration. You can grant the agent write access to your systems, allowing it to update deal stages, log call notes, or create follow-up tasks in the CRM. This is when the “autonomous” label begins to feel justified, and the associated risks increase accordingly. A read-only agent that produces a wrong summary wastes someone’s time; a write-enabled agent that incorrectly updates a deal stage risks corrupting your sales data. If you choose this route, establish approval workflows, incorporate confirmation steps before any write operations, and ensure everything is logged.
Anthropic’s Agent SDK provides a production-grade framework for this progression. It offers error handling, session management, and permission controls that make moving from prototype to internal tool less cumbersome than building everything from scratch.
The $47,000 question
At some point, someone on the leadership team will ask about the ROI. Here is how to think about it.
A sales rep who makes eight external calls a day spends roughly an hour on pre-call research. If the agent cuts that to 15 minutes, you regain 45 minutes per rep per day. For a team of 10 reps at an average loaded cost of $120,000 a year, that amounts to about $47,000 in recovered capacity annually, assuming the rep does nothing useful with the reclaimed time except stare out the window, which they likely will.
The API costs to run this are small in comparison—just a few hundred dollars per month at most, depending on volume. The engineering cost involves a developer for a week or two, depending on how many integrations are needed.
The less quantifiable benefit is consistency. Every rep receives the same quality of preparation, whether they are diligent about pre-call research or tend to wing it. Consistent preparation correlates with better discovery conversations, and better discovery correlates with higher close rates. You might find it difficult to prove causation, but the logical relationship holds.
Start boring, stay boring
The most effective internal tools are the unglamorous ones that work so reliably they fade into the background. That is the goal for a sales agent—not something that excites in a demo but something they open reflexively before every call because it saves time and makes them better prepared.
Claude’s tool use API makes the technical side straightforward. The harder part is the discipline to keep the scope small, connect only the tools your team actually needs, and resist the temptation to turn your prep assistant into an autonomous deal-closing machine. An agent who reliably answers three questions is worth more than one who promises to answer thirty and gets four wrong.
Build the boring thing first. If it works, you’ll know what to build next—your team will tell you.
Like this? Get email updates or grab the RSS feed.
More insights:
-
The path to an agent-first web
For three decades, the web has operated on an implicit contract between the people who build websites and the people who visit them. You design pages for human eyes and organise information for human brains, monetising attention through ads, upsells, and sticky navigation patter…
-
Generative engine optimisation: separating sound practice from snake oil
A new three-letter acronym is stalking the marketing industry. Generative Engine Optimisation (GEO) is the practice of making your content visible in AI-generated answers, such as those produced by ChatGPT, Perplexity, Google AI Overviews, and Claude. The term was coined in a 20…
-
Automating your marketing 01: Paid Search Ads
Google has always wanted you to believe that running search ads is simple and not as complex as it actually is. Set a budget (a generous one!), choose some keywords, and let the machine handle the rest. To be fair, the machine has become exceptionally good at certain aspects of …
-
Why AI models hallucinate
In September 2025, OpenAI published a paper that said something the AI industry already suspected but hadn’t quite articulated. The paper, “Why Language Models Hallucinate”, authored by Adam Tauman Kalai, Ofir Nachum, Santosh Vempala, and Edwin Zhang, didn’t just catalogue the p…
-
Received wisdom: classic frameworks under AI pressure 01: David C Baker
David C Baker has spent thirty years telling agency owners something they already suspected but lacked the courage to act on. You are not expensive enough, not focused enough in what you do. You are not sufficiently authoritative with your clients. The issue is not your work. Th…