An agent is an LLM placed in a loop where it can call tools (functions, APIs, shell) and act on the results — turning a text predictor into something that does things.
The core loop (ReAct)
1. THOUGHT — model reasons about the goal
2. ACTION — model emits a tool call (name + args)
3. OBSERVE — runtime executes the tool, returns the result
4. repeat — until the model emits a final answer
while not done:
msg = llm(messages) # model decides
if msg.tool_calls:
result = run_tool(msg.tool_calls[0])
messages.append(tool_result(result)) # feed back
else:
done = True # final answer
What makes or breaks an agent
- Tool schemas — clear names, typed args, good descriptions (Tool Calling & Structured Outputs with Local Models).
- Stopping — cap iterations; agents loop forever without a budget.
- Error handling — feed failures back as observations so the model can recover.
- Context growth — each step adds tokens; summarize or prune (Ollama Parameters Guide).
The local-model catch: smaller models are worse at multi-step tool use. Keep tasks short, schemas tight, and verify outputs. Build the tools as MCP servers.
Related: Building MCP Tools for a Local LLM · Tool Calling & Structured Outputs with Local Models · RAG with Local Embeddings