You wired up a Claude agent over a weekend. It calls your tools, reasons through a messy request, and returns something that makes your team say "wait, it did that?"
Then someone asks the question that kills most agent projects:
"Cool. Can we put it in front of customers?"
The distance between "it works on my laptop" and "it runs in production every day" is where most of the real engineering lives. This post walks through that gap: the parts a demo can skip and production can't.
1. Start with a loop you actually understand
Every Claude agent, whatever framework sits on top, comes down to the same loop: send messages and tools, let Claude ask for a tool, run it, send the result back, and repeat until Claude is done.
Here's the bare version in Python with the official anthropic SDK:
import anthropic
client = anthropic.Anthropic()
tools = [{
"name": "lookup_order",
"description": "Fetch an order by its ID. Returns status, items and shipping info.",
"input_schema": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
"additionalProperties": False,
},
"strict": True,
}]
messages = [{"role": "user", "content": "Where is order A-1042?"}]
while True:
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
tools=tools,
messages=messages,
)
if response.stop_reason != "tool_use":
break # end_turn, max_tokens, refusal... handle each in real code
messages.append({"role": "assistant", "content": response.content})
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = run_tool(block.name, block.input) # your code
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
# All results go back in ONE user message
messages.append({"role": "user", "content": tool_results})
print(next(b.text for b in response.content if b.type == "text"))
A few details that bite people later:
- Return every tool result in a single user message. Claude can call several tools in parallel. Splitting the results across messages teaches it to stop doing that.
-
Don't drop failed tool calls. Send back a
tool_resultwithis_error: Trueso Claude can recover or explain. -
Check
stop_reasonbefore you read the content.end_turnis not the only way a turn ends.
If you don't need to own the loop, the SDK's beta tool runner (client.beta.messages.tool_runner) handles it for you. Understanding the raw loop still pays off, because every production concern below hooks into it.
2. Put a human in the loop where it matters
The fastest way to lose trust in an agent is to let it do something irreversible that nobody approved.
You don't need a fancy framework for this. Sort your tools into two buckets:
- Read tools (search, lookup, summarize) run automatically.
- Write tools (refund, send email, update record) pause for approval.
In the loop above, that's a check before run_tool: if the tool is in the write bucket, hold the call, ask a human, and send back either the real result or a "user declined" tool result. Claude handles the decline gracefully, and you get an audit trail of who approved what.
Human-in-the-loop checkpoints are one of the things GoML calls out as standard in the Claude agents it builds, and it's the single cheapest way to make a risky agent shippable.
3. Treat every tool output as untrusted
Your agent reads tool output, logs and user text, and then writes things out. That's two leak paths.
Before production, add guardrails on both sides:
- Outbound: scan responses and tool arguments for PII and secrets (API keys, tokens, connection strings) before they leave your system or land in logs.
- Inbound: treat retrieved documents and web content as data, not instructions. A tool result that says "ignore previous instructions" should never change what your agent is allowed to do. Enforce permissions in your code, not in the prompt.
Developers using Claude Code to prototype run into this a lot: the prototype works, but nobody added PII and API-key leak prevention, traceability or monitoring. Those are exactly the gaps GoML lists in its "From Claude Code to Production" work.
4. Make it traceable before you make it smart
When an agent gives a bad answer in production, "the model did something weird" is not a root cause.
Log, per turn:
- the messages and tool definitions sent (or a hash plus a pointer to storage)
- each
tool_useblock and its result -
stop_reasonand tokenusage - which human approved which action
With that, you can replay a failure, build an eval set from real traffic, and answer the compliance question "why did the system do this?" Without it, you're guessing.
5. Spend tokens on purpose
Agents resend the whole conversation every turn, so costs compound fast. Three habits help:
-
Cache the stable prefix. Prompt caching is a prefix match over
tools, thensystem, thenmessages. Keep your tool list and system prompt byte-for-byte identical between requests, and put anything volatile (timestamps, request IDs) after the cache breakpoint. Then checkusage.cache_read_input_tokensto confirm it's working. If it stays at zero, something in your prefix keeps changing. - Keep tool results lean. Return the fields Claude needs, not the whole API payload.
-
Tune effort per route.
output_config={"effort": "low"}is often enough for simple routing or classification steps. Save higher effort for the hard reasoning.
"Token-efficient agents" sounds like marketing until you see the invoice at production volume.
6. Connect tools with MCP instead of glue code
Once you have more than a handful of integrations, hand-written tool wrappers turn into a maintenance tax. The Model Context Protocol (MCP) gives you a standard way to expose systems (databases, ticketing, internal APIs) as tools that Claude agents can discover and call.
Build an MCP server once per system, and every agent you ship afterward can reuse it.
7. Running on AWS? Use Amazon Bedrock
If your data and security reviews already live in AWS, running Claude on Amazon Bedrock keeps everything inside that boundary. The Python SDK has a dedicated client, so the loop above barely changes:
from anthropic import AnthropicBedrockMantle
client = AnthropicBedrockMantle(aws_region="us-east-1")
response = client.messages.create(
model="anthropic.claude-opus-5-5", # Bedrock IDs take the anthropic. prefix
max_tokens=16000,
tools=tools,
messages=messages,
)
Same messages.create, same tool loop, same stop_reason handling. Auth comes from your usual AWS credentials.
8. Migrating from another stack? Don't port the prompts blindly
Plenty of teams are moving agents from OpenAI, Azure, GCP, LangChain or AutoGen to Claude. The API swap is the easy part. The traps are:
- prompts tuned for another model's quirks, which are often too prescriptive for Claude
- framework abstractions that hide the loop, so you can't see where tools or retries fail
- missing evals, so you can't prove the new system is at least as good
Build a small eval set from real traffic first, then migrate, then compare.
The production checklist
Before you call your Claude agent production-ready, you should be able to say yes to each of these:
- [ ] I understand and can trace every turn of the agent loop
- [ ] Irreversible actions need human approval
- [ ] Outputs are scanned for PII and secrets
- [ ] Retrieved content can't change the agent's permissions
- [ ] Every turn is logged with tool calls, results and token usage
- [ ] Prompt caching is verified with
cache_read_input_tokens - [ ] Integrations go through reusable MCP servers
- [ ] I have an eval set, and monitoring tells me when quality drifts
How teams get there faster
GoML's approach to Claude agent development follows four stages that map neatly onto this checklist:
- Design: a 1-day AI consulting workshop to pick the right use case.
- Experiment: a 4-day rapid proof of concept.
- Build: about 4 months of product development.
- Run: LLMOps for monitoring, evaluation, and cost and model optimization.
They also publish reusable blueprints for common agent shapes, such as conversational agents, search engines, agentic workflows and data analytics, plus industry versions for healthcare, finance, manufacturing and more.
👉 Follow along: Claude Agent Development by GoML covers production Claude agents, MCP integrations, Amazon Bedrock deployment and migrations from other AI stacks.
Shipping a Claude agent and stuck between demo and production? Drop your biggest blocker in the comments, or book a 30-minute call with GoML to map where your Claude work is today and what it needs to go live.
Top comments (0)