{"id":1085,"date":"2026-07-15T02:15:30","date_gmt":"2026-07-15T02:15:30","guid":{"rendered":"https:\/\/learnerbox.net\/blog\/?p=1085"},"modified":"2026-07-15T02:15:40","modified_gmt":"2026-07-15T02:15:40","slug":"building-an-ai-agent-from-scratch-tools-memory-and-reasoning-loops","status":"publish","type":"post","link":"https:\/\/learnerbox.net\/blog\/ai-engineering\/building-an-ai-agent-from-scratch-tools-memory-and-reasoning-loops\/","title":{"rendered":"Building an AI Agent from Scratch: Tools, Memory, and Reasoning Loops"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">What Makes Something an Agent?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">There is a meaningful difference between calling an LLM API and building an AI agent. A single API call takes an input, produces an output, and stops. An agent does something more: it perceives a situation, decides what action to take, executes that action, observes the result, and decides what to do next. That loop, repeated until the task is complete, is what makes something an agent rather than a wrapper.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The concept has deep roots in AI research, but the practical engineering of LLM-based agents has matured enormously in the past two years. Today, a competent Python developer can build a functional agent in an afternoon. Understanding what the agent is actually doing under the surface, and building it in a way that is reliable, observable, and safe, takes considerably more thought. This post walks through the three core components of any agent system: tools, memory, and the reasoning loop.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">The Reasoning Loop: Think, Act, Observe, Repeat<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The architectural heart of an LLM agent is the reasoning loop. The most widely used formulation is ReAct (Reasoning and Acting), introduced in a 2022 paper by Yao et al. at Princeton and Google Brain. The loop works as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The agent receives a task.<\/li>\n\n\n\n<li>It reasons about what to do next (Thought).<\/li>\n\n\n\n<li>It selects and calls a tool (Action).<\/li>\n\n\n\n<li>It receives the tool&#8217;s output (Observation).<\/li>\n\n\n\n<li>It reasons again, incorporating the observation.<\/li>\n\n\n\n<li>It repeats until it decides the task is complete and returns a final answer.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">In code, this translates to a loop that sends the current state of the conversation to the LLM, parses its response for a tool call, executes the tool, appends the result to the conversation history, and calls the LLM again. A minimal Python implementation looks like this:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>def run_agent(task: str, tools: dict, max_steps: int = 10) -&gt; str:\n    messages = [\n        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: build_system_prompt(tools)},\n        {&quot;role&quot;: &quot;user&quot;,   &quot;content&quot;: task}\n    ]\n\n    for step in range(max_steps):\n        response = call_llm(messages)\n        action = parse_action(response)\n\n        if action[&quot;type&quot;] == &quot;final_answer&quot;:\n            return action[&quot;content&quot;]\n\n        observation = tools[action[&quot;name&quot;]](**action[&quot;args&quot;])\n\n        messages.append({&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: response})\n        messages.append({&quot;role&quot;: &quot;user&quot;,\n                         &quot;content&quot;: f&quot;Observation: {observation}&quot;})\n\n    return &quot;Max steps reached without a final answer.&quot;<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Several things in this skeleton are worth noting. The <code>max_steps<\/code> guard is not optional: without it, a confused or looping agent will burn tokens indefinitely. The system prompt must describe the available tools clearly, including their names, what they do, and the exact format the model should use to call them. And <code>parse_action<\/code> needs to be robust: LLMs do not always produce perfectly formatted output, so defensive parsing with fallback handling is essential in production.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Tools: Giving the Agent Hands<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A tool is any function the agent can call to interact with the world outside the LLM&#8217;s context window. Common tools in production agents include web search, code execution, file reading and writing, database queries, REST API calls, calculator functions, and retrieval from a vector store. The principle is simple: if the agent needs information or capabilities that are not already in its context, it needs a tool to get them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Defining tools well is one of the most important engineering decisions in agent design. Each tool should do one thing clearly, return results in a consistent and parseable format, handle errors gracefully rather than crashing the loop, and be as fast as possible since every tool call adds latency. A poorly designed tool that returns noisy or ambiguous output will confuse the model, produce bad reasoning, and waste steps.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the OpenAI API, tools are defined as JSON schemas that the model uses to structure its calls:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>tools = [\n    {\n        &quot;type&quot;: &quot;function&quot;,\n        &quot;function&quot;: {\n            &quot;name&quot;: &quot;web_search&quot;,\n            &quot;description&quot;: &quot;Search the web for current information.&quot;,\n            &quot;parameters&quot;: {\n                &quot;type&quot;: &quot;object&quot;,\n                &quot;properties&quot;: {\n                    &quot;query&quot;: {\n                        &quot;type&quot;: &quot;string&quot;,\n                        &quot;description&quot;: &quot;The search query.&quot;\n                    }\n                },\n                &quot;required&quot;: [&quot;query&quot;]\n            }\n        }\n    }\n]<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The Anthropic API uses an equivalent structure. The key discipline is writing the <code>description<\/code> field carefully: the model reads it to decide when and how to use the tool, so vague descriptions produce inconsistent tool selection.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Memory: What the Agent Knows and Remembers<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Memory in AI agents divides into four types, each serving a different purpose.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>In-context memory<\/strong> is the simplest: everything in the current conversation history that the model can see. It is immediate and requires no infrastructure, but it is bounded by the context window. For a task that takes many steps or processes large documents, in-context memory alone is insufficient.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>External memory<\/strong> uses a vector database such as Pinecone, Weaviate, or ChromaDB to store and retrieve information by semantic similarity. When the agent needs to recall something from a long earlier conversation, a previous session, or a large document corpus, it queries the vector store and injects the relevant results into the context. This is the retrieval-augmented memory pattern, and it is the most common approach for agents that need persistent knowledge.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Episodic memory<\/strong> stores summaries of past interactions, allowing the agent to recall what it did in previous sessions without storing every message verbatim. A lightweight implementation writes a structured summary to a database at the end of each session and retrieves relevant episodes at the start of the next one.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Working memory<\/strong> is an explicit scratchpad the agent maintains during a multi-step task: a structured record of what it has done, what it has found, and what it still needs to do. Externalising this into a structured object rather than relying purely on the conversation history significantly improves performance on complex tasks, because it prevents the model from losing track of earlier steps as the context grows.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">The System Prompt: The Agent&#8217;s Constitution<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The system prompt is the most underestimated component of agent design. It defines the agent&#8217;s identity, its available tools, the format it must use to call them, its reasoning style, its stopping conditions, and its constraints. A well-written system prompt for an agent typically includes a role definition, a tool registry with descriptions and invocation syntax, an explicit instruction to reason before acting, a rule specifying when to stop, and a safety boundary defining what the agent must not do.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A common mistake is writing a minimal system prompt and expecting the model to infer the rest. In an agentic loop, ambiguity in the system prompt compounds across steps: a model that is slightly uncertain about when to call a tool versus reason further will make inconsistent decisions, produce unpredictable behaviour, and be difficult to debug.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Observability and Safety: What Most Tutorials Skip<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Two concerns that most introductory agent tutorials omit are observability and safety, and both matter enormously in production.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Observability means logging every step of the reasoning loop: what the model decided, which tool it called, what arguments it passed, and what the tool returned. Without structured logs, debugging a failed agent run is nearly impossible. Tools such as LangSmith, Weights and Biases, and Langfuse provide agent tracing infrastructure that makes this practical.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Safety in agentic systems means imposing hard limits on what the agent can do autonomously. Any action that is irreversible, such as sending an email, deleting a record, or executing a financial transaction, should require a human confirmation step before execution. This is not a limitation on capability; it is a precondition for deploying agents in environments where mistakes have real consequences.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Conclusion<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">An AI agent is a reasoning loop wrapped around an LLM, extended with tools that give it reach and memory systems that give it persistence. Building one from scratch, rather than dropping a framework in place, forces you to understand exactly what is happening at each step, which is the foundation of being able to debug, extend, and trust what you deploy. Start with a simple loop, a handful of clearly defined tools, and in-context memory. Add external memory and episodic summarisation as the complexity of your tasks demands it. Log everything. And never let an agent take an irreversible action without a human in the loop.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What Makes Something an Agent? There is a meaningful difference between calling an LLM API and building an AI agent. A single API call takes an input, produces an output, and stops. An agent does something more: it perceives a situation, decides what action to take, executes that action, observes the result, and decides what to do next. That loop, repeated until the task is complete, is what makes something an agent rather than a wrapper. The concept has deep roots in AI research, but the practical engineering of LLM-based agents has matured enormously in the past two years. Today, a competent Python developer can build a functional agent in an afternoon. Understanding what the agent is actually doing under the surface, and building it in a way that is reliable, observable, and safe, takes considerably more thought. This post walks through the three core components of any agent system: tools, memory, and the reasoning loop. The Reasoning Loop: Think, Act, Observe, Repeat The architectural heart of an LLM agent is the reasoning loop. The most widely used formulation is ReAct (Reasoning and Acting), introduced in a 2022 paper by Yao et al. at Princeton and Google Brain. The loop works as follows: In code, this translates to a loop that sends the current state of the conversation to the LLM, parses its response for a tool call, executes the tool, appends the result to the conversation history, and calls the LLM again. A minimal Python implementation looks like this: Several things in this skeleton are worth noting. The max_steps guard is not optional: without it, a confused or looping agent will burn tokens indefinitely. The system prompt must describe the available tools clearly, including their names, what they do, and the exact format the model should use to call them. And parse_action needs to be robust: LLMs do not always produce perfectly formatted output, so defensive parsing with fallback handling is essential in production. Tools: Giving the Agent Hands A tool is any function the agent can call to interact with the world outside the LLM&#8217;s context window. Common tools in production agents include web search, code execution, file reading and writing, database queries, REST API calls, calculator functions, and retrieval from a vector store. The principle is simple: if the agent needs information or capabilities that are not already in its context, it needs a tool to get them. Defining tools well is one of the most important engineering decisions in agent design. Each tool should do one thing clearly, return results in a consistent and parseable format, handle errors gracefully rather than crashing the loop, and be as fast as possible since every tool call adds latency. A poorly designed tool that returns noisy or ambiguous output will confuse the model, produce bad reasoning, and waste steps. In the OpenAI API, tools are defined as JSON schemas that the model uses to structure its calls: The Anthropic API uses an equivalent structure. The key discipline is writing the description field carefully: the model reads it to decide when and how to use the tool, so vague descriptions produce inconsistent tool selection. Memory: What the Agent Knows and Remembers Memory in AI agents divides into four types, each serving a different purpose. In-context memory is the simplest: everything in the current conversation history that the model can see. It is immediate and requires no infrastructure, but it is bounded by the context window. For a task that takes many steps or processes large documents, in-context memory alone is insufficient. External memory uses a vector database such as Pinecone, Weaviate, or ChromaDB to store and retrieve information by semantic similarity. When the agent needs to recall something from a long earlier conversation, a previous session, or a large document corpus, it queries the vector store and injects the relevant results into the context. This is the retrieval-augmented memory pattern, and it is the most common approach for agents that need persistent knowledge. Episodic memory stores summaries of past interactions, allowing the agent to recall what it did in previous sessions without storing every message verbatim. A lightweight implementation writes a structured summary to a database at the end of each session and retrieves relevant episodes at the start of the next one. Working memory is an explicit scratchpad the agent maintains during a multi-step task: a structured record of what it has done, what it has found, and what it still needs to do. Externalising this into a structured object rather than relying purely on the conversation history significantly improves performance on complex tasks, because it prevents the model from losing track of earlier steps as the context grows. The System Prompt: The Agent&#8217;s Constitution The system prompt is the most underestimated component of agent design. It defines the agent&#8217;s identity, its available tools, the format it must use to call them, its reasoning style, its stopping conditions, and its constraints. A well-written system prompt for an agent typically includes a role definition, a tool registry with descriptions and invocation syntax, an explicit instruction to reason before acting, a rule specifying when to stop, and a safety boundary defining what the agent must not do. A common mistake is writing a minimal system prompt and expecting the model to infer the rest. In an agentic loop, ambiguity in the system prompt compounds across steps: a model that is slightly uncertain about when to call a tool versus reason further will make inconsistent decisions, produce unpredictable behaviour, and be difficult to debug. Observability and Safety: What Most Tutorials Skip Two concerns that most introductory agent tutorials omit are observability and safety, and both matter enormously in production. Observability means logging every step of the reasoning loop: what the model decided, which tool it called, what arguments it passed, and what the tool returned. Without structured logs, debugging a failed agent run is nearly impossible. Tools such as LangSmith, Weights and Biases, and Langfuse provide agent tracing infrastructure that makes this practical. Safety in agentic systems means imposing hard limits on what the agent can do autonomously. Any action that is irreversible, such as sending an email, deleting a record, or executing a financial transaction, should require a human confirmation step before execution. This is not a limitation on capability; it is a precondition for deploying agents in environments where mistakes have real consequences. Conclusion An AI agent is a reasoning loop wrapped around an LLM, extended with tools that give it reach and memory systems that give it persistence. Building one from scratch, rather than dropping a framework in place, forces you to understand exactly what is happening at each step, which is the foundation of being able to debug, extend, and trust what you deploy. Start with a simple loop, a handful of clearly defined tools, and in-context memory. Add external memory and episodic summarisation as the complexity of your tasks demands it. Log everything. And never let an agent take an irreversible action without a human in the loop.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1085","post","type-post","status-publish","format-standard","hentry","category-ai-engineering"],"_links":{"self":[{"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/posts\/1085","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/comments?post=1085"}],"version-history":[{"count":2,"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/posts\/1085\/revisions"}],"predecessor-version":[{"id":1087,"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/posts\/1085\/revisions\/1087"}],"wp:attachment":[{"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/media?parent=1085"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/categories?post=1085"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnerbox.net\/blog\/wp-json\/wp\/v2\/tags?post=1085"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}