Part 9 · 1 chapters · ~12 min

Agent Architecture

Agents as models in a bounded loop: tool calling with validated arguments, the four limits every loop needs, explicit state as a graph with conditional edges, checkpoints for resumption and replay, interrupts before consequential actions, and choosing between a chain, a graph, a free loop and multiple agents.

10

Tools, state, limits and the interrupt

code
// a bounded agent loop: validated tools, limits, and an interrupt before writes
const tools = {
  searchDocs: { schema: z.object({ q: z.string().max(200) }), write: false, run: ({ q }) => retrieve(q, 'loans') },
  draftLetter: { schema: z.object({ customerId: z.string() }), write: false, run: draftClearanceLetter },
  sendEmail:   { schema: z.object({ to: z.string().email(), body: z.string() }), write: true, run: sendEmail },
} as const;

async function runAgent(goal: string, ctx: { approve: (call: ToolCall) => Promise<boolean> }) {
  const state: Msg[] = [{ role: 'user', content: goal }];
  const seen = new Set<string>();
  for (let step = 0; step < 8; step++) {                                   // max steps
    const out = await model.respond(state, { tools: describe(tools), maxTokens: 800 });
    if (out.type === 'answer') return { done: true, answer: out.text, steps: step };
    const tool = tools[out.call.name as keyof typeof tools];
    const args = tool?.schema.safeParse(out.call.args);
    if (!tool || !args?.success) { state.push(toolError(out.call, 'invalid call')); continue; }
    const key = out.call.name + JSON.stringify(args.data);
    if (seen.has(key)) return { done: false, reason: 'repeated call', steps: step };   // loop detection
    seen.add(key);
    if (tool.write && !(await ctx.approve(out.call))) { state.push(toolError(out.call, 'rejected by human')); continue; }
    state.push(toolResult(out.call, await tool.run(args.data as any)));
    await checkpoint(state);                                                  // resume and replay
  }
  return { done: false, reason: 'step limit', steps: 8 };
}
shapeuse whenexample
chainthe steps are known and fixedclassify → retrieve → answer → check
graphbranches vary by input; some need a humanM phase 2 in LangGraph; a clearance-letter flow with approval
free loopopen-ended research with read-only tools"find every place this fee is documented"
multi-agentone context cannot hold the taska planner with separate implementer and reviewer agents
the link to state machines
An agent graph is the FSM pattern from the loan flow with some transitions chosen by a model. Keep the states and the allowed transitions in code, so the model can only choose among edges you have drawn.
AGENT ARCHITECTURE: TOOLS, STATE AND GRAPHS
from one prompt to a bounded loop: tool calling, explicit state, graphs with checkpoints, and a human in the right place
swipe the figure sideways, or tap expand for full screen
1/6
tool calling
Tool calling: each tool has a name, a description the model reads, and a JSON schema for its arguments. The model returns a tool call; your code validates the arguments, runs the tool and returns the result. The model never executes anything itself. Tool descriptions are prompts: write them like API documentation.