Claude API Agentic Workflow Builder Tutorial
What this tutorial covers
If you're searching for how to build an agentic workflow with the Claude API, you're likely trying to go beyond a single prompt-response call and build something that can plan, use tools, check its own output, and loop until a task is actually done. This tutorial walks through the core pattern: a control loop that sends messages to Claude, lets the model call tools, feeds results back, and decides when to stop.
The key insight is that "agentic" doesn't mean a special API endpoint — it means a loop you write around normal Claude API calls, using tool use (function calling) to let the model take actions and see results before producing a final answer. Everything below works whether you call Anthropic's API directly or through a proxy like SubToAPI; the loop logic is identical.
The core agentic loop
An agentic workflow has four moving parts:
- System prompt that defines the agent's role, constraints, and available tools
- Tool definitions describing what the model can call and what arguments it expects
- A loop that sends messages, checks for
tool_useblocks, executes them, and appends results - A stopping condition — either the model returns a final text answer, or you hit a max-iteration limit
Here's a minimal implementation in JavaScript:
const tools = [
{
name: "search_docs",
description: "Search internal documentation for relevant passages",
input_schema: {
type: "object",
properties: {
query: { type: "string" }
},
required: ["query"]
}
},
{
name: "create_ticket",
description: "Create a support ticket",
input_schema: {
type: "object",
properties: {
title: { type: "string" },
body: { type: "string" }
},
required: ["title", "body"]
}
}
];
async function runAgent(userMessage) {
let messages = [{ role: "user", content: userMessage }];
for (let step = 0; step < 8; step++) {
const response = await callClaude(messages, tools);
messages.push({ role: "assistant", content: response.content });
const toolUses = response.content.filter(b => b.type === "tool_use");
if (toolUses.length === 0) {
return response.content.find(b => b.type === "text")?.text;
}
const toolResults = [];
for (const call of toolUses) {
const result = await executeTool(call.name, call.input);
toolResults.push({
type: "tool_result",
tool_use_id: call.id,
content: JSON.stringify(result)
});
}
messages.push({ role: "user", content: toolResults });
}
throw new Error("Agent exceeded max steps");
}
The callClaude function is whatever wraps your HTTP request to the Messages endpoint. If you use SubToAPI, that call looks like a standard POST to https://api.subtoapi.app/v1/messages with your sub_live_... key, and tool use works exactly as documented in /docs/tools.
Designing tools the model can actually use well
Agentic reliability comes mostly from tool design, not prompt tricks. Three rules matter more than anything else:
- Narrow scope per tool. A tool that does one thing (
search_docs,create_ticket) is easier for the model to call correctly than one that does five things based on a mode flag. - Strict schemas. Use
requiredfields and tight types ininput_schema. Loose schemas lead to malformed calls and wasted loop iterations. - Descriptive names and descriptions. The model picks tools based on the
descriptionfield — vague descriptions cause wrong tool selection even with a correct schema.
Also design your executeTool function to return structured, bounded output. Dumping a 50KB JSON blob into a tool result burns context and often confuses the next reasoning step. Truncate and summarize before returning.
Managing state across steps
Agentic workflows fail in production not because the model reasons badly, but because state management is sloppy. A few practical patterns:
- Cap iterations explicitly. Always set a max loop count (6–10 is typical for most tasks) so a confused agent doesn't burn budget indefinitely.
- Persist the message array, not just the final answer, if you need to resume or audit a run. Store it alongside a request ID.
- Log every tool call and result separately from the conversation so you can debug which step went wrong without replaying the whole thing.
- Use streaming for long-running agents. If a step involves a long generation (e.g., writing a report after gathering data), stream the response so the UI doesn't look frozen. See /docs/streaming for details on how streamed
tool_useblocks arrive incrementally.
Handling errors inside the loop
Treat tool failures as information the model should see, not exceptions that kill the run. If executeTool throws, catch it and return an error-shaped tool result:
try {
const result = await executeTool(call.name, call.input);
toolResults.push({ type: "tool_result", tool_use_id: call.id, content: JSON.stringify(result) });
} catch (err) {
toolResults.push({
type: "tool_result",
tool_use_id: call.id,
content: JSON.stringify({ error: err.message }),
is_error: true
});
}
Claude generally handles this well — it will retry with different arguments or fall back to a different tool rather than getting stuck, as long as the error message is clear.
Where the API layer matters
Once an agentic workflow is running in production, the pain points shift from prompt design to operational concerns: per-agent API keys so you can isolate usage, usage metadata so you know which workflows are expensive, and team access control so multiple builders aren't sharing one raw key. This is the part SubToAPI is built for — it sits in front of your Claude access and gives you scoped sub_live_... keys per agent or environment, streaming and tool use support identical to the native API, and a dashboard showing token usage per key. If you're moving an agent from a prototype script to something teammates depend on, start with /docs/quickstart and swap in your existing tool-calling code with minimal changes.
Pricing is per seat rather than per call, which matters for agentic workloads since a single task can trigger many tool-use round trips — see /pricing for the Solo, Team, and Scale tiers, or just start building at /signup.
FAQ
Is an "agentic workflow" a different API from normal Claude chat?
No. It's the same Messages API endpoint, used in a loop. What makes it agentic is that you pass tools, let the model emit tool_use blocks, execute those calls yourself, and feed results back as tool_result messages until the model stops calling tools.
How many loop iterations should an agent be allowed before stopping?
Most practical agents finish in 3–6 steps. Set a hard cap around 8–10 and treat hitting that cap as a failure state to log and investigate, not a normal outcome.
Do I need a framework like LangChain to build this?
No — the loop shown above is the entire mechanism most agent frameworks implement internally. A framework adds convenience for memory, retries, and multi-agent orchestration, but a plain loop with tool use covers the majority of real workflows with far less complexity to debug.