Building an AI Agent Framework with the Claude API
What "building an AI agent framework" actually means
If you're searching for this, you're probably past the "call the API once and get a response" stage and into "I need Claude to plan, use tools, and keep going until a task is done." An agent framework is the code that sits between your application and the Claude API: it manages the conversation loop, decides when to call tools, tracks state across steps, and knows when to stop. Claude itself doesn't run loops or call tools on its own — your framework does, using Claude's tool-use responses as the decision signal.
This article covers the architecture pattern that almost every production agent framework uses, regardless of whether it's built on the raw Anthropic API, LangChain, or a hosted gateway like SubToAPI. You'll get a working control loop, the state and memory pieces you need around it, and the guardrails that stop agents from looping forever or burning your budget.
The core agent loop
Every Claude-based agent framework, from a 50-line script to a multi-agent orchestration system, is a variation of this loop:
- Send the conversation + available tools to Claude.
- Check the response: is it a final text answer, or a tool-use request?
- If it's a tool-use request, execute the tool in your code, append the result, and go back to step 1.
- If it's a final answer, return it to the caller.
- Stop after a max number of steps or a budget limit, even if Claude hasn't produced a final answer.
async function runAgent(userMessage, tools, maxSteps = 8) {
let messages = [{ role: "user", content: userMessage }];
for (let step = 0; step < maxSteps; step++) {
const response = await callClaude(messages, tools);
if (response.stop_reason !== "tool_use") {
return response.content; // final answer
}
const toolResults = await executeToolCalls(response.content);
messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: toolResults });
}
throw new Error("Agent exceeded max steps");
}
This is the whole skeleton. Everything else — memory, retries, cost tracking, multi-agent handoffs — is built around this loop, not replacing it.
Designing your tool interface
Tools are the agent's only way to act on the world, so their design matters more than prompt wording. A few rules that hold up in production:
- Name tools by outcome, not implementation.
search_knowledge_baseis better thanquery_vector_db. - Keep parameters flat and typed. Claude is reliable with simple JSON schemas; deeply nested optional objects increase malformed calls.
- Return structured errors, not exceptions. If a tool fails, send Claude a result like
{ "error": "rate_limited", "retry_after": 30 }so it can decide what to do next, rather than crashing your loop. - Make tools idempotent where possible. Agents retry; a tool that double-charges a customer on retry is a bug in your framework, not Claude's fault.
If you haven't worked with Claude's tool-use format yet, the tools documentation covers the request/response schema in detail — the loop above assumes you're already comfortable with how tool calls and tool results are structured.
State, memory, and context management
A naive agent appends every message to one growing array and resends it every turn. That works for short tasks and falls apart for anything that runs more than ~15 steps, because context grows, latency grows, and costs grow with it.
Practical patterns:
- Summarize old steps. After N tool calls, compress the earlier history into a short summary and keep only the last 2–3 full turns verbatim.
- Separate working memory from long-term memory. Working memory is the current task's message array. Long-term memory is a database or vector store the agent queries as a tool call — not something you keep stuffing into every prompt.
- Checkpoint state outside the model. Store task progress (what's done, what's pending) in your own data structure, not in Claude's context. This lets you resume a crashed agent run without re-deriving state from conversation history.
Guardrails that keep agents from running away
Agent frameworks fail in predictable ways: infinite tool-call loops, runaway token usage, and tools being called with bad arguments. Build these in from day one rather than retrofitting them:
- Hard step limits — cap at a fixed number of loop iterations per task.
- Token/cost budgets per run — track cumulative input/output tokens and abort if a single task exceeds a threshold.
- Tool allowlists per agent type — a "research agent" shouldn't have access to a
send_emailtool even if it's defined in the same codebase. - Human-in-the-loop checkpoints — for irreversible actions (payments, deletions, external emails), require explicit confirmation before executing the tool call.
Logging every step — the request sent, the tool called, the result returned — is non-negotiable. Agent bugs are almost always found by reading the step-by-step trace, not by staring at the final output.
Where SubToAPI fits
The loop above works against the raw Anthropic API, but most teams building agent frameworks also need per-key usage visibility, streaming for long-running tool chains, and a way to issue scoped keys per agent or per environment without sharing one Claude login. SubToAPI wraps your existing Claude access in a standard HTTPS API — sub_live_... keys, streaming, tool-use support, and usage metadata per key — so your agent framework can treat each agent, service, or customer as its own authenticated client instead of one shared credential.
That's useful specifically for agent frameworks because agents tend to multiply: a staging agent, a production agent, a per-customer agent in a multi-tenant app. Issuing a separate key per use case and reading per-key usage from the dashboard is simpler than building that metering yourself. Start with the quickstart, check streaming if your agent needs to show intermediate output, and see pricing for Solo, Team, and Scale plans — there's a free trial at signup.
Getting started
Don't start with a framework library. Start with the loop above, a single tool, and a hard step limit. Get that working end to end — including logging and failure handling — before adding a second tool or a second agent. Most agent framework complexity should come from your domain logic (what tools exist, what state needs tracking), not from the orchestration loop itself, which stays nearly identical across projects.
Questions
Do I need a framework library like LangChain to build a Claude agent? No. The control loop is roughly 30–50 lines of code. Libraries add convenience features (built-in tools, tracing, memory stores) but the core pattern is simple enough to write yourself, which also makes debugging easier.
How do I stop an agent from calling tools in an infinite loop? Enforce a hard maximum step count in your loop (not a suggestion in the prompt), and track cumulative tokens or tool calls per task so you can abort before costs spiral.
Should each agent in my framework use the same API key? Not if you have multiple agents, environments, or customers. Separate keys per use case make usage tracking and revocation much easier — SubToAPI's dashboard shows usage per key, which maps directly onto a one-key-per-agent setup.