The Agent Loop — What This Demo Does
Every AI agent is a while loop. This demo implements the ReAct pattern (Reasoning + Acting) from scratch — no LangChain, no Mastra, no framework.
while (steps < MAX_STEPS) {
// THINK — call the LLM
const res = await callLLM(messages, tools);
// Done? Return final answer
if (res.finish === 'stop') return res.content;
// ACT + OBSERVE — run each tool
for (const tc of res.tool_calls) {
const result = await runTool(tc);
messages.push({ role: 'tool', result });
}
} // ← loop back to THINK
Four Guardrails (All Active)
Max Steps (10) — stops the loop after 10 LLM calls, then forces a summary answer
Token Budget (8,000) — stops when cumulative tokens exceed the limit
Loop Detection — redirects if the same tool is called 3× with the same args
Tool Timeout (5s) — prevents a hanging tool call from stalling the agent
Memory System (No Vector DB)
Short-term — the messages array holds every Thought/Action/Observation this session. The LLM reads it on every step.
Long-term — when the agent calls remember(key, value), the fact is saved to localStorage and injected into the system prompt on the next session.
Replacing Tools for Production
The demo's search() tool returns mock results. In production, swap the implementation without touching the agent loop:
// Brave Search (free tier)
search: async ({ query }) => {
const res = await fetch(
`https://api.search.brave.com/...?q=${query}`,
{ headers: { 'X-Subscription-Token': BRAVE_KEY } }
);
return (await res.json()).web.results
.slice(0,3).map(r => r.snippet).join('\n');
}
// Agent loop does NOT change ↑