Welcome to Agents Academy

Module 05 · Agent basics · ~10 min

The agent loop.

By the end of this module, your agent can keep working without you in the loop. Observe, think, act, repeat, the basic shape of every autonomous worker, with stop conditions that prevent it from running away with itself.

To get there, you’ll wire observation → reasoning → action → repeat. The same loop shape every later module, memory, monitoring, kill switches, bolts on to.

Agent basics tier · Reference card
Quick answer

What is an agent loop?

An agent loop is the observe → think → act → observe cycle an autonomous agent repeats until a stop condition ends the run. The agent observes the current state, thinks (an LLM call decides what, if anything, to do next), acts by executing the chosen tool, such as placing an order or fetching detail, then feeds the result back in as the next observation. Everything else, memory, monitoring, kill switches, is plumbing around that cycle. The loop ends when the model returns plain text with no tool call (it is done) or a stop condition trips. A step cap is essential: a loop without one is a credit card with no limit, because every iteration burns inference cost and trade fees. Cap typical sessions around 10 to 20 steps and alert when the agent hits the cap.

No Limitless API claims here; this is agent-runtime teaching. Verified 2026-06-09.

Section 01

The loop in plain English.

An agent doesn’t make one decision and stop. It makes a decision, executes it, observes the result, and uses what it learned to make the next decision. That cycle, observe, think, act, observe, is the agent loop. Everything else (memory, monitoring, kill switches) is plumbing around the loop.

Observe

Read state: positions, market prices, pending orders.

Think

LLM call. Model decides what (if anything) to do next.

Act

Execute the chosen tool. Place order, fetch detail, etc.

Observe

Feed the tool result back. Loop until terminal or max iters.

Section 02

A minimal loop in code.

A working agent loop in 30 lines. The model gets one tool (browse_markets from Module 04) and a simple system prompt. The loop runs until the model returns plain text (no tool call) or hits the iteration cap.

How to run this

  1. Set three env vars: LIMITLESS_API_KEY (the tool hits Limitless), plus ANTHROPIC_API_KEY (TypeScript) or OPENAI_API_KEY (Python). Keep Module 04’s tool file next to this one so the ./tools import resolves.
  2. Save as agent-loop.ts next to tools.ts from Module 04, then run npx tsx agent-loop.ts.
  3. You see the agent call browse_markets once, the loop feeds the market list back to the model, and the model prints a final summary of 5 markets prefixed with Final:. If it hits Max iterations reached, your tool string is likely too large, trim it.
// Module 05: Minimal agent loop
import Anthropic from '@anthropic-ai/sdk';
import { browseMarkets, browseMarketsTool } from './tools.js';

const client = new Anthropic();
const MAX_ITERS = 10;

async function runAgent(userMessage: string) {
  const messages: Anthropic.MessageParam[] = [{ role: 'user', content: userMessage }];

  for (let i = 0; i < MAX_ITERS; i++) {
    const resp = await client.messages.create({
      model:      'claude-opus-4-8',
      max_tokens: 1024,
      system:     'You are a Limitless trading research agent. Use tools to investigate markets.',
      tools:      [browseMarketsTool],
      messages,
    });

    // Terminal: model returned plain text, no more tool calls.
    if (resp.stop_reason === 'end_turn') {
      const text = resp.content.find(c => c.type === 'text');
      console.log('Final:', text?.text);
      return;
    }

    // Execute any tool calls and feed results back.
    const toolUses = resp.content.filter(c => c.type === 'tool_use');
    messages.push({ role: 'assistant', content: resp.content });
    const toolResults = await Promise.all(toolUses.map(async (tu: any) => ({
      type:        'tool_result' as const,
      tool_use_id: tu.id,
      content:     await browseMarkets(tu.input),
    })));
    messages.push({ role: 'user', content: toolResults });
  }

  console.warn('Max iterations reached');
}

runAgent('Find me 5 active markets.').catch(console.error);

Section 03

Stop conditions.

A loop without termination is a fire hazard. Every agent loop needs at least four stop conditions wired in from day one:

01

Model says stop

No tool calls in the response, model is done reasoning. Cleanest exit.

02

Max iterations

Hard cap (10–20 typical). If the loop hits it, log a warning and bail.

03

Wall-clock budget

Total time per run. Prevents a hung tool from blocking the agent forever.

04

Kill switch tripped

External flag the operator can set. Module 14 covers the file-flag pattern.

Section 04

Recovery from tool errors.

Tool calls fail. Network blips, rate limits, schema mismatches. The right pattern is to surface the error to the model as a tool result with an error string, let the model decide whether to retry, try a different tool, or give up. Don’t catch the error and silently swallow it; the model needs context to make a good decision.

What you should NOT do: throw an exception out of the loop. That kills the run and loses all the reasoning so far. Capture every tool error, format it as a string the model can read (e.g. “Error: rate limit exceeded, retry in 60s”), and let the model react.

The exception to the rule

If the error indicates a SECURITY problem (auth failure, signature invalid, IP blocked), do NOT feed it to the model. Stop the loop immediately and alert a human. The model is not equipped to recover from auth issues, and it might try increasingly desperate things.

Wire this loop into your dashboard.

The seed NDJSON you dropped in Module 02 was eight lines of mock data. As soon as your agent loop is producing real iterations, append each one to $ACADEMY_DATA_DIR/agent.log.ndjson with the same field shape (ts, iter, event, tool, tokens_in, tokens_out, cost_usd). The panel and the Telegram bot will pick up the new lines automatically, that’s the moment the dashboard stops being a mockup and becomes your live view.

Common questions

The agent loop: what people ask

Each answer also ships invisibly as schema.org FAQ data for search engines and AI assistants. Tap a question to expand.

  1. What is the agent loop (observe, think, act, observe)?
    It is the cycle an agent repeats instead of deciding once and stopping: observe the current state, think (an LLM call decides the next move), act (run the chosen tool), then observe the result and feed it back. The model loops until it returns plain text with no tool call, or a stop condition trips. Memory, monitoring, and kill switches are plumbing around it.
  2. How is an agent different from a single LLM call?
    A single call makes one decision and stops. An agent loops: it executes its decision, observes the result, and uses what it learned to make the next decision. That repeated observe-think-act cycle is what lets an agent investigate a market over several tool calls instead of guessing in one shot.
  3. How does an agent loop terminate safely?
    Wire at least four stop conditions from day one: the model returns no tool call (the cleanest exit), a hard iteration cap (maxSteps of 10 to 20 is typical), a wall-clock budget so a hung tool cannot block forever, and an operator kill switch. Hitting the cap should log a warning and bail; a loop without a step cap is a credit card with no limit.
  4. How should an agent recover from a tool error?
    Surface the error to the model as a tool result string (for example Error: rate limit exceeded, retry in 60s) and let it decide whether to retry, switch tools, or give up. Never throw out of the loop, that kills the run and loses all reasoning so far. The exception is a security error (auth failure, invalid signature, IP block): stop the loop immediately and alert a human.
  5. What do you need to run a minimal agent loop?
    Three env vars: LIMITLESS_API_KEY (the tool calls Limitless) plus ANTHROPIC_API_KEY (TypeScript) or OPENAI_API_KEY (Python). Give the model one tool and a short system prompt; the whole loop is about 30 lines and runs until the model prints a final summary or hits MAX_ITERS.

Module checklist

Five quick confirmations.

Tick each item once you’ve actually done it. The Continue button unlocks at 5/5.

Module 05 complete

Loop spinning.

Your agent runs on its own now. It looks at the market, decides what to do, calls a tool, and reads the result, over and over, until a goal is met or a guard rail trips. That’s the difference between a chat session and an actual worker that can move money.

Concretely, you have a working agent loop with safe termination. A complete observe → think → act cycle, four stop conditions wired in from day one, and a recovery pattern for tool errors that keeps the model in the driver’s seat.

01

A minimal but complete runAgent/run_agent function, observe, think, act, observe, that drives Module 04’s browse_markets tool end-to-end through Claude or GPT-4o.

02

The four stop conditions every loop needs wired in: model says end_turn, MAX_ITERS cap, wall-clock budget, kill-switch placeholder.

03

A recovery pattern for tool errors, surface them to the model as readable strings, and the one exception to that rule: auth/security failures stop the loop and alert a human.

Next up: giving the loop a memory, persisting position state, appending reasoning traces, and knowing when a vector store actually pays off.

Complete the checklist above to unlock