"AI agent" sounds like it needs a framework. It doesn't. Strip away the branding and an agent is one loop:
- Send the conversation to the model.
- If it asks to use a tool, run the tool.
- Feed the result back.
- Repeat until it answers.
Here's the whole thing with Claude:
for (let step = 0; step < MAX_STEPS; step++) {
const runner = anthropic.messages.stream({ model, max_tokens: 1024, system, tools, messages });
runner.on("text", (delta) => send(delta)); // stream tokens out
const final = await runner.finalMessage();
if (final.stop_reason !== "tool_use") break; // model answered, we're done
messages.push({ role: "assistant", content: final.content });
const results = [];
for (const block of final.content) {
if (block.type === "tool_use") {
const result = await runTool(block.name, block.input); // your code
results.push({ type: "tool_result", tool_use_id: block.id, content: result });
}
}
messages.push({ role: "user", content: results }); // feed the results back, loop
}
That's it. Tool use is just: the model emits a tool_use block, you run the matching function, you hand back a tool_result. Streaming is just forwarding token deltas as they arrive.
I packaged this into a runnable starter — Next.js, a streaming UI, two example tools, one-command Vercel deploy. Clone it, add a key, ship:
https://github.com/mnifzied-create/agentloop
The free core is the loop above, MIT-licensed. If you want the production patterns next — running multiple tools in parallel, persistent memory on SQLite, retries, an eval harness, human-in-the-loop approval, sub-agents — I wrote those up as a small, equally-readable kit too (linked in the repo).
The point isn't the kit, though. It's that you can read every line of an agent in one sitting. Go look.
Top comments (0)