{"id":642,"date":"2026-04-01T10:34:19","date_gmt":"2026-04-01T10:34:19","guid":{"rendered":"https:\/\/techpaathshala.com\/blog\/?p=642"},"modified":"2026-04-21T08:44:53","modified_gmt":"2026-04-21T08:44:53","slug":"building-an-ai-agent-from-scratch-a-step-by-step-developer-guide-2026","status":"publish","type":"post","link":"https:\/\/techpaathshala.com\/blog\/building-an-ai-agent-from-scratch-a-step-by-step-developer-guide-2026\/","title":{"rendered":"Building an AI Agent from Scratch: A Step-by-Step Developer Guide (2026)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\" id=\"building-an-ai-agent-from-scratch-a-step-by-step-developer-guide-2026\">Every developer who has used ChatGPT or GitHub Copilot has interacted with an LLM. Far fewer have built a system that uses an LLM as a&nbsp;<em>reasoning engine<\/em>&nbsp;\u2014 a system that can plan, remember, use external tools, and complete multi-step tasks autonomously. That is what this guide is about. This&nbsp;<strong>build AI agent from scratch developer guide<\/strong>&nbsp;walks you through every component: what it is, why it matters, and exactly how to implement it in Python \u2014 from the core ReAct loop to memory, tool integration, and production deployment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We will go from first principles to a working, multi-tool agent \u2014 with real Python code at each step.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By the end, you will understand what separates a chatbot from an agent, why agents fail in production (and how to prevent it), and how frameworks like LangChain and CrewAI compare to building from scratch.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-an-ai-agent-the-four-component-architecture\">What Is an AI Agent? The Four-Component Architecture<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before writing a single line of code, you need a precise mental model. An AI agent is not simply &#8220;an LLM that does things.&#8221; It is a system with four interconnected components working together:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AI Agent = LLM + Planning + Memory + Tool Use\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. LLM (The Reasoning Engine)<\/strong>&nbsp;The LLM is the brain \u2014 the component that understands natural language, reasons about problems, and decides what to do next. In an agent, the LLM is not just generating text; it is making decisions about which tools to call, in what order, with what parameters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Planning (The Goal-Decomposition Layer)<\/strong>&nbsp;Planning is the ability to break a complex goal into a sequence of steps. A simple chatbot has no planning \u2014 it responds to the current message. An agent can say: &#8220;To answer this question, I need to (1) search the web, (2) retrieve the relevant section, (3) synthesise an answer.&#8221; Planning can be implicit (the LLM reasons through steps in its context) or explicit (a structured plan is generated and executed step by step).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>3. Memory (The Persistence Layer)<\/strong>&nbsp;Memory is how the agent maintains context and state. There are four types:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Short-term (in-context):<\/strong>&nbsp;The current conversation history, held in the LLM&#8217;s context window<\/li>\n\n\n\n<li><strong>Long-term (external):<\/strong>&nbsp;A vector database or key-value store the agent can read from and write to across sessions<\/li>\n\n\n\n<li><strong>Episodic:<\/strong>&nbsp;Records of past actions and their outcomes, used to improve future decisions<\/li>\n\n\n\n<li><strong>Semantic:<\/strong>&nbsp;A structured knowledge base of facts the agent knows about its domain<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>4. Tool Use (The Action Layer)<\/strong>&nbsp;Tools are functions the agent can invoke \u2014 web search, database queries, code execution, API calls, file read\/write, calculator, email sender. Tool use is what separates an agent that&nbsp;<em>talks about<\/em>&nbsp;doing things from one that&nbsp;<em>actually does<\/em>&nbsp;them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[Insert Diagram: The Four-Component Agent Architecture \u2014 LLM at centre, connected to Planning, Memory, and Tools]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The interaction loop between these four components is what makes an agent an agent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Goal \u2192 Plan \u2192 Action (Tool Call) \u2192 Observation \u2192 Revised Plan \u2192 Next Action \u2192 ... \u2192 Final Answer\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This loop \u2014 often called the&nbsp;<strong>ReAct loop<\/strong>&nbsp;(Reason + Act) \u2014 is the core pattern you will implement.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<div class=\"custom-ad-banner\" style=\"margin:20px 0; text-align:center;\"><a href=\"https:\/\/techpaathshala.com\/genai-ml-engineer-program-mumbai\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/techpaathshala.com\/blog\/wp-content\/uploads\/2026\/04\/WhatsApp-Image-2026-04-20-at-11.47.34-AM-2.jpeg\" alt=\"Advertisement\" \/><\/a><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-agent-loop-how-it-works-in-practice\">The Agent Loop: How It Works in Practice<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the ReAct loop in plain language, before any code:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The user gives the agent a goal:&nbsp;<em>&#8220;Find the current price of Infosys stock and tell me if it&#8217;s above its 50-day moving average.&#8221;<\/em><\/li>\n\n\n\n<li>The agent&#8217;s LLM&nbsp;<strong>reasons<\/strong>:&nbsp;<em>&#8220;I need to (1) fetch the current Infosys stock price, (2) fetch the 50-day moving average, (3) compare them.&#8221;<\/em><\/li>\n\n\n\n<li>The LLM&nbsp;<strong>acts<\/strong>: calls the&nbsp;<code>get_stock_price<\/code>&nbsp;tool with&nbsp;<code>ticker=\"INFY\"<\/code><\/li>\n\n\n\n<li>The tool returns an&nbsp;<strong>observation<\/strong>:&nbsp;<code>{\"price\": 1842.50, \"currency\": \"INR\"}<\/code><\/li>\n\n\n\n<li>The LLM&nbsp;<strong>reasons again<\/strong>&nbsp;with the new observation:&nbsp;<em>&#8220;I have the current price. Now I need the moving average.&#8221;<\/em><\/li>\n\n\n\n<li>The LLM&nbsp;<strong>acts<\/strong>: calls&nbsp;<code>get_moving_average<\/code>&nbsp;tool with&nbsp;<code>ticker=\"INFY\", period=50<\/code><\/li>\n\n\n\n<li>The tool returns:&nbsp;<code>{\"ma_50\": 1793.20}<\/code><\/li>\n\n\n\n<li>The LLM has enough information to&nbsp;<strong>produce a final answer<\/strong>:&nbsp;<em>&#8220;Infosys is currently trading at \u20b91,842.50, which is above its 50-day moving average of \u20b91,793.20 \u2014 a bullish signal.&#8221;<\/em><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Each iteration of this loop is a&nbsp;<strong>step<\/strong>. Production agents might run 5\u201320 steps for complex tasks. The art of agent design is making each step reliable, cost-efficient, and failure-resistant.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-1-setting-up-the-environment\">Step 1: Setting Up the Environment<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We will build our agent in Python. The implementation uses only the OpenAI API directly \u2014 no LangChain or other abstractions \u2014 so you understand every component before reaching for a framework.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"prerequisites\">Prerequisites<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Create a virtual environment<\/em>\npython -m venv agent-env\nsource agent-env\/bin\/activate  <em># Windows: agent-env\\Scripts\\activate<\/em>\n\n<em># Install dependencies<\/em>\npip install openai python-dotenv requests\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"project-structure\">Project Structure<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>ai-agent\/\n\u251c\u2500\u2500 agent.py          # Main agent loop\n\u251c\u2500\u2500 tools.py          # Tool definitions and implementations\n\u251c\u2500\u2500 memory.py         # Memory management\n\u251c\u2500\u2500 system_prompt.py  # System prompt construction\n\u251c\u2500\u2500 .env              # API keys (never commit this)\n\u2514\u2500\u2500 main.py           # Entry point\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"environment-setup\">Environment Setup<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><em># .env<\/em>\nOPENAI_API_KEY=your_openai_api_key_here\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><em># main.py<\/em>\nfrom dotenv import load_dotenv\nload_dotenv()\n\nfrom agent import Agent\n\nagent = Agent()\nresponse = agent.run(\"What is 15% of 847, and what is the square root of that result?\")\nprint(response)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-2-defining-the-system-prompt\">Step 2: Defining the System Prompt<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The system prompt is the most important piece of engineering in your agent. It defines the agent&#8217;s identity, capabilities, reasoning style, and constraints. A weak system prompt produces an agent that hallucinates tool calls, loops endlessly, or gives up too early. A strong system prompt produces an agent that reasons clearly and uses tools purposefully.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># system_prompt.py<\/em>\n\nAGENT_SYSTEM_PROMPT = \"\"\"You are a precise, task-focused AI assistant with access to a set of tools.\n\n## Your Behaviour\n- Break complex tasks into clear steps before acting\n- Use tools when you need real-world information or computation \u2014 do not guess\n- After each tool call, reason about the result before deciding the next step\n- When you have enough information to answer, provide a clear, direct final answer\n- If a tool call fails, explain the failure and try an alternative approach\n\n## Tool Use Rules\n- Only call tools that exist in the provided tool list\n- Always provide required parameters \u2014 never call a tool with missing inputs\n- Do not call the same tool with the same parameters more than twice\n- Do not make up tool results \u2014 always use the actual observation returned\n\n## Reasoning Format\nThink step by step. Before each action, state:\n- What you know so far\n- What you need to find out\n- Which tool will get you that information\n\n## Stopping Conditions\nStop when:\n- You have a complete, accurate answer to the user's question\n- You have exhausted available tools and can state what you could not find\n- You have reached 10 tool calls (to prevent infinite loops)\n\nBe concise, accurate, and action-oriented.\"\"\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Why this system prompt structure works:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Behavioural anchors<\/strong>&nbsp;(&#8220;Use tools when you need real-world information \u2014 do not guess&#8221;) prevent hallucination<\/li>\n\n\n\n<li><strong>Tool use rules<\/strong>&nbsp;prevent infinite loops and parameter errors<\/li>\n\n\n\n<li><strong>Reasoning format<\/strong>&nbsp;enforces the explicit chain-of-thought that makes agent decisions auditable<\/li>\n\n\n\n<li><strong>Stopping conditions<\/strong>&nbsp;are the safety valve \u2014 every production agent needs them<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-3-defining-and-implementing-tools\">Step 3: Defining and Implementing Tools<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tools are Python functions exposed to the LLM via a schema. The LLM does not&nbsp;<em>call<\/em>&nbsp;the function directly \u2014 it generates a structured JSON object requesting the function call, your agent code intercepts that request, executes the actual function, and returns the result to the LLM as an observation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"tool-schema-how-the-llm-sees-your-tools\">Tool Schema: How the LLM Sees Your Tools<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><em># tools.py<\/em>\nimport requests\nimport math\nimport json\n\n<em># --- Tool Implementations ---<\/em>\n\ndef calculator(expression: str) -&gt; str:\n    \"\"\"Safely evaluate a mathematical expression.\"\"\"\n    try:\n        <em># Use a safe evaluation approach<\/em>\n        allowed_names = {k: v for k, v in math.__dict__.items() if not k.startswith(\"_\")}\n        result = eval(expression, {\"__builtins__\": {}}, allowed_names)\n        return json.dumps({\"result\": result, \"expression\": expression})\n    except Exception as e:\n        return json.dumps({\"error\": str(e), \"expression\": expression})\n\n\ndef web_search(query: str) -&gt; str:\n    \"\"\"Search the web for current information. Returns top results.\"\"\"\n    <em># In production, replace with SerpAPI, Brave Search API, or Tavily<\/em>\n    <em># This is a mock implementation for demonstration<\/em>\n    mock_results = &#091;\n        {\n            \"title\": f\"Search result for: {query}\",\n            \"snippet\": f\"This is a mock result. In production, connect to a real search API.\",\n            \"url\": \"https:\/\/example.com\/result-1\"\n        }\n    ]\n    return json.dumps({\"query\": query, \"results\": mock_results})\n\n\ndef get_current_time() -&gt; str:\n    \"\"\"Get the current date and time.\"\"\"\n    from datetime import datetime\n    now = datetime.now()\n    return json.dumps({\n        \"datetime\": now.isoformat(),\n        \"date\": now.strftime(\"%Y-%m-%d\"),\n        \"time\": now.strftime(\"%H:%M:%S\"),\n        \"timezone\": \"Asia\/Kolkata\"\n    })\n\n\ndef read_file(filepath: str) -&gt; str:\n    \"\"\"Read the contents of a text file.\"\"\"\n    try:\n        with open(filepath, 'r') as f:\n            content = f.read()\n        return json.dumps({\"filepath\": filepath, \"content\": content, \"length\": len(content)})\n    except FileNotFoundError:\n        return json.dumps({\"error\": f\"File not found: {filepath}\"})\n    except Exception as e:\n        return json.dumps({\"error\": str(e)})\n\n\n<em># --- Tool Registry ---<\/em>\n\nTOOLS = &#091;\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"calculator\",\n            \"description\": \"Evaluate a mathematical expression. Use for any arithmetic, percentages, square roots, or numerical calculations.\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"expression\": {\n                        \"type\": \"string\",\n                        \"description\": \"A valid Python math expression. Use math module functions like math.sqrt(), math.pow(), etc. Example: '0.15 * 847' or 'math.sqrt(127.05)'\"\n                    }\n                },\n                \"required\": &#091;\"expression\"]\n            }\n        }\n    },\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"web_search\",\n            \"description\": \"Search the web for current information, facts, news, or data you don't know. Use when the user asks about real-world information.\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"query\": {\n                        \"type\": \"string\",\n                        \"description\": \"The search query. Be specific and precise.\"\n                    }\n                },\n                \"required\": &#091;\"query\"]\n            }\n        }\n    },\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"get_current_time\",\n            \"description\": \"Get the current date and time. Use when the user asks about the current date, time, or when you need to timestamp information.\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {}\n            }\n        }\n    },\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"read_file\",\n            \"description\": \"Read the contents of a text file from the local filesystem.\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"filepath\": {\n                        \"type\": \"string\",\n                        \"description\": \"The path to the file to read.\"\n                    }\n                },\n                \"required\": &#091;\"filepath\"]\n            }\n        }\n    }\n]\n\n<em># Tool dispatcher \u2014 maps tool names to functions<\/em>\nTOOL_FUNCTIONS = {\n    \"calculator\": calculator,\n    \"web_search\": web_search,\n    \"get_current_time\": get_current_time,\n    \"read_file\": read_file\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The tool description is as important as the implementation.<\/strong>&nbsp;The LLM decides&nbsp;<em>which<\/em>&nbsp;tool to call based entirely on the description. Vague descriptions produce wrong tool selections. Precise descriptions with examples produce reliable tool selection.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-4-implementing-the-agent-loop\">Step 4: Implementing the Agent Loop<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the core of the agent \u2014 the loop that executes the ReAct cycle until the agent reaches a final answer or a stopping condition.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># agent.py<\/em>\nimport json\nimport os\nfrom openai import OpenAI\nfrom system_prompt import AGENT_SYSTEM_PROMPT\nfrom tools import TOOLS, TOOL_FUNCTIONS\n\nclass Agent:\n    def __init__(self, model: str = \"gpt-4o\", max_steps: int = 10):\n        self.client = OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))\n        self.model = model\n        self.max_steps = max_steps\n\n    def run(self, user_goal: str, verbose: bool = True) -&gt; str:\n        \"\"\"\n        Execute the agent loop for a given user goal.\n        Returns the agent's final response.\n        \"\"\"\n        <em># Initialise conversation with system prompt and user goal<\/em>\n        messages = &#091;\n            {\"role\": \"system\", \"content\": AGENT_SYSTEM_PROMPT},\n            {\"role\": \"user\", \"content\": user_goal}\n        ]\n\n        step = 0\n\n        while step &lt; self.max_steps:\n            step += 1\n\n            if verbose:\n                print(f\"\\n--- Step {step} ---\")\n\n            <em># Call the LLM<\/em>\n            response = self.client.chat.completions.create(\n                model=self.model,\n                messages=messages,\n                tools=TOOLS,\n                tool_choice=\"auto\"  <em># Let the LLM decide whether to use tools<\/em>\n            )\n\n            message = response.choices&#091;0].message\n\n            <em># Add the assistant's response to conversation history<\/em>\n            messages.append(message)\n\n            <em># Case 1: The LLM wants to use a tool<\/em>\n            if message.tool_calls:\n                for tool_call in message.tool_calls:\n                    tool_name = tool_call.function.name\n                    tool_args = json.loads(tool_call.function.arguments)\n\n                    if verbose:\n                        print(f\"Tool call: {tool_name}({tool_args})\")\n\n                    <em># Execute the tool<\/em>\n                    if tool_name in TOOL_FUNCTIONS:\n                        observation = TOOL_FUNCTIONS&#091;tool_name](**tool_args)\n                    else:\n                        observation = json.dumps({\"error\": f\"Unknown tool: {tool_name}\"})\n\n                    if verbose:\n                        print(f\"Observation: {observation}\")\n\n                    <em># Add the tool result to conversation history<\/em>\n                    messages.append({\n                        \"role\": \"tool\",\n                        \"tool_call_id\": tool_call.id,\n                        \"content\": observation\n                    })\n\n            <em># Case 2: The LLM has produced a final answer<\/em>\n            else:\n                final_answer = message.content\n                if verbose:\n                    print(f\"\\n--- Final Answer ---\\n{final_answer}\")\n                return final_answer\n\n        <em># Reached max steps without a final answer<\/em>\n        return \"I reached the maximum number of steps without completing the task. Here is my last response: \" + (message.content or \"No response generated.\")\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s trace through what happens when you run this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>agent = Agent()\nresult = agent.run(\"What is 15% of 847, and what is the square root of that result?\")\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>--- Step 1 ---\nTool call: calculator({'expression': '0.15 * 847'})\nObservation: {\"result\": 127.05, \"expression\": \"0.15 * 847\"}\n\n--- Step 2 ---\nTool call: calculator({'expression': 'math.sqrt(127.05)'})\nObservation: {\"result\": 11.272533..., \"expression\": \"math.sqrt(127.05)\"}\n\n--- Final Answer ---\n15% of 847 is **127.05**, and the square root of 127.05 is approximately **11.27**.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The agent correctly decomposed the task into two sequential tool calls and produced an accurate final answer. This is the ReAct loop working exactly as designed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-5-adding-memory\">Step 5: Adding Memory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The agent above has no memory between sessions. Each call to&nbsp;<code>agent.run()<\/code>&nbsp;starts fresh. For most real-world applications, you need at least short-term conversational memory (within a session) and often long-term memory (across sessions).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"short-term-memory-conversation-history\">Short-Term Memory: Conversation History<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The simplest form of memory is maintaining the full conversation history within a session:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># memory.py<\/em>\nclass ConversationMemory:\n    def __init__(self, max_history: int = 20):\n        self.messages = &#091;]\n        self.max_history = max_history\n\n    def add(self, role: str, content: str):\n        self.messages.append({\"role\": role, \"content\": content})\n        <em># Trim to prevent context window overflow<\/em>\n        if len(self.messages) &gt; self.max_history:\n            <em># Keep system message (index 0) + recent messages<\/em>\n            self.messages = self.messages&#091;:1] + self.messages&#091;-(self.max_history - 1):]\n\n    def get_history(self) -&gt; list:\n        return self.messages.copy()\n\n    def clear(self):\n        self.messages = &#091;]\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"long-term-memory-vector-database-retrieval\">Long-Term Memory: Vector Database Retrieval<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For persistent memory across sessions, you need a vector database. Here is a minimal implementation using ChromaDB:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Install: pip install chromadb sentence-transformers<\/em>\n\nimport chromadb\nfrom chromadb.utils import embedding_functions\nimport json\n\nclass LongTermMemory:\n    def __init__(self, collection_name: str = \"agent_memory\"):\n        self.client = chromadb.PersistentClient(path=\".\/agent_memory_db\")\n        self.ef = embedding_functions.DefaultEmbeddingFunction()\n        self.collection = self.client.get_or_create_collection(\n            name=collection_name,\n            embedding_function=self.ef\n        )\n\n    def store(self, content: str, metadata: dict = None):\n        \"\"\"Store a piece of information in long-term memory.\"\"\"\n        import uuid\n        doc_id = str(uuid.uuid4())\n        self.collection.add(\n            documents=&#091;content],\n            metadatas=&#091;metadata or {}],\n            ids=&#091;doc_id]\n        )\n        return doc_id\n\n    def retrieve(self, query: str, n_results: int = 3) -&gt; list&#091;str]:\n        \"\"\"Retrieve relevant memories based on a query.\"\"\"\n        results = self.collection.query(\n            query_texts=&#091;query],\n            n_results=min(n_results, self.collection.count() or 1)\n        )\n        return results&#091;\"documents\"]&#091;0] if results&#091;\"documents\"] else &#091;]\n\n    def get_relevant_context(self, query: str) -&gt; str:\n        \"\"\"Format retrieved memories as a context string for the LLM.\"\"\"\n        memories = self.retrieve(query)\n        if not memories:\n            return \"\"\n        formatted = \"\\n\".join(&#091;f\"- {m}\" for m in memories])\n        return f\"\\n\\n## Relevant context from previous sessions:\\n{formatted}\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Integrating long-term memory into the agent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># In agent.py \u2014 add memory retrieval before the main loop<\/em>\n\ndef run_with_memory(self, user_goal: str, memory: LongTermMemory) -&gt; str:\n    <em># Retrieve relevant memories<\/em>\n    context = memory.get_relevant_context(user_goal)\n\n    <em># Augment the system prompt with retrieved context<\/em>\n    augmented_system = AGENT_SYSTEM_PROMPT + context\n\n    messages = &#091;\n        {\"role\": \"system\", \"content\": augmented_system},\n        {\"role\": \"user\", \"content\": user_goal}\n    ]\n\n    <em># ... rest of the agent loop ...<\/em>\n\n    <em># After completion, store the interaction in memory<\/em>\n    memory.store(\n        f\"User asked: {user_goal}. Agent answered: {final_answer}\",\n        metadata={\"type\": \"interaction\"}\n    )\n\n    return final_answer\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"handling-failures-the-three-most-common-agent-bugs\">Handling Failures: The Three Most Common Agent Bugs<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"bug-1-infinite-tool-loops\">Bug 1: Infinite Tool Loops<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Symptom:<\/strong>&nbsp;The agent keeps calling the same tool repeatedly without making progress.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fix:<\/strong>&nbsp;Track tool call history and add deduplication logic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tool_call_history = {}\n\nfor tool_call in message.tool_calls:\n    call_signature = f\"{tool_name}:{json.dumps(tool_args, sort_keys=True)}\"\n\n    if tool_call_history.get(call_signature, 0) &gt;= 2:\n        observation = json.dumps({\n            \"error\": \"This tool call has been attempted multiple times with the same parameters. Try a different approach.\"\n        })\n    else:\n        tool_call_history&#091;call_signature] = tool_call_history.get(call_signature, 0) + 1\n        observation = TOOL_FUNCTIONS&#091;tool_name](**tool_args)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"bug-2-hallucinated-tool-parameters\">Bug 2: Hallucinated Tool Parameters<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Symptom:<\/strong>&nbsp;The agent calls a tool with parameters that don&#8217;t match the schema, or invents parameter values.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fix:<\/strong>&nbsp;Validate tool arguments before execution:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import jsonschema\n\ndef validate_and_call_tool(tool_name: str, tool_args: dict) -&gt; str:\n    tool_schema = next(\n        (t&#091;\"function\"]&#091;\"parameters\"] for t in TOOLS if t&#091;\"function\"]&#091;\"name\"] == tool_name),\n        None\n    )\n\n    if tool_schema:\n        try:\n            jsonschema.validate(tool_args, tool_schema)\n        except jsonschema.ValidationError as e:\n            return json.dumps({\"error\": f\"Invalid tool parameters: {str(e.message)}\"})\n\n    return TOOL_FUNCTIONS&#091;tool_name](**tool_args)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"bug-3-context-window-overflow\">Bug 3: Context Window Overflow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Symptom:<\/strong>&nbsp;Errors when the conversation history grows too long for the model&#8217;s context window.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fix:<\/strong>&nbsp;Implement a sliding window with summarisation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def trim_messages(messages: list, max_tokens: int = 8000) -&gt; list:\n    \"\"\"Keep system message + most recent messages that fit in token budget.\"\"\"\n    <em># Rough token estimate: 4 chars \u2248 1 token<\/em>\n    def estimate_tokens(msg):\n        content = msg.get(\"content\", \"\")\n        if isinstance(content, list):\n            content = str(content)\n        return len(content) \/\/ 4\n\n    system_msg = messages&#091;0]  <em># Always keep system prompt<\/em>\n    recent_messages = messages&#091;1:]\n\n    total_tokens = estimate_tokens(system_msg)\n    trimmed = &#091;]\n\n    for msg in reversed(recent_messages):\n        msg_tokens = estimate_tokens(msg)\n        if total_tokens + msg_tokens &gt; max_tokens:\n            break\n        trimmed.insert(0, msg)\n        total_tokens += msg_tokens\n\n    return &#091;system_msg] + trimmed\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"framework-comparison-build-ai-agent-from-scratch-vs-langchain-vs-crewai--a-developer-guide\">Framework Comparison: Build AI Agent from Scratch vs. LangChain vs. CrewAI \u2014 A Developer Guide<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Building from scratch \u2014 as we have done above \u2014 gives you complete control and deep understanding. But most production agents use frameworks. Here is when each approach makes sense:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Criteria<\/th><th class=\"has-text-align-left\" data-align=\"left\">From Scratch<\/th><th class=\"has-text-align-left\" data-align=\"left\">LangChain\/LlamaIndex<\/th><th class=\"has-text-align-left\" data-align=\"left\">LangGraph<\/th><th class=\"has-text-align-left\" data-align=\"left\">CrewAI<\/th><\/tr><\/thead><tbody><tr><td><strong>Learning value<\/strong><\/td><td>Highest \u2014 understand every component<\/td><td>Medium \u2014 abstractions hide complexity<\/td><td>Medium-High<\/td><td>Medium<\/td><\/tr><tr><td><strong>Dev speed<\/strong><\/td><td>Slowest<\/td><td>Fast<\/td><td>Medium<\/td><td>Fast<\/td><\/tr><tr><td><strong>Flexibility<\/strong><\/td><td>Complete<\/td><td>High<\/td><td>Very High<\/td><td>Medium<\/td><\/tr><tr><td><strong>Multi-agent support<\/strong><\/td><td>Build yourself<\/td><td>Limited<\/td><td>Excellent<\/td><td>Excellent<\/td><\/tr><tr><td><strong>Production debugging<\/strong><\/td><td>Easiest (you own the code)<\/td><td>Moderate<\/td><td>Good (with LangSmith)<\/td><td>Moderate<\/td><\/tr><tr><td><strong>Best for<\/strong><\/td><td>Learning, custom requirements<\/td><td>Single agents, RAG pipelines<\/td><td>Complex stateful workflows<\/td><td>Role-based multi-agent systems<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>When to build from scratch:<\/strong>&nbsp;Learning, highly custom tool integrations, latency-critical systems where framework overhead matters, or when you need full control over error handling.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>When to use LangChain:<\/strong>&nbsp;Rapid prototyping, standard RAG pipelines, connecting to a wide range of document loaders and vector stores.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>When to use LangGraph:<\/strong>&nbsp;Stateful, cyclic agent workflows with complex branching logic. LangGraph represents agent state as a graph \u2014 ideal for workflows where different paths require different tools.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>When to use CrewAI:<\/strong>&nbsp;Multi-agent systems where different agents have different roles (researcher, writer, critic) and need to collaborate on a task.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-same-agent-in-langchain-a-comparison\">The Same Agent in LangChain: A Comparison<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For reference, here is what the equivalent agent looks like using LangChain&#8217;s&nbsp;<code>create_tool_calling_agent<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># pip install langchain langchain-openai<\/em>\n\nfrom langchain_openai import ChatOpenAI\nfrom langchain.agents import create_tool_calling_agent, AgentExecutor\nfrom langchain_core.prompts import ChatPromptTemplate\nfrom langchain_core.tools import tool\n\n@tool\ndef calculator(expression: str) -&gt; str:\n    \"\"\"Evaluate a mathematical expression using Python's math module.\"\"\"\n    import math, json\n    try:\n        result = eval(expression, {\"__builtins__\": {}, \"math\": math})\n        return json.dumps({\"result\": result})\n    except Exception as e:\n        return json.dumps({\"error\": str(e)})\n\nllm = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n\nprompt = ChatPromptTemplate.from_messages(&#091;\n    (\"system\", \"You are a helpful assistant. Use tools when needed.\"),\n    (\"human\", \"{input}\"),\n    (\"placeholder\", \"{agent_scratchpad}\")\n])\n\nagent = create_tool_calling_agent(llm, &#091;calculator], prompt)\nexecutor = AgentExecutor(agent=agent, tools=&#091;calculator], verbose=True)\n\nresult = executor.invoke({\"input\": \"What is 15% of 847, and what is the square root?\"})\nprint(result&#091;\"output\"])\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">LangChain handles the loop, tool dispatch, and message formatting \u2014 but the underlying mechanics are identical to what we built. The from-scratch implementation took ~100 lines; the LangChain version is ~20 lines. The trade-off is transparency vs. convenience.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"a-real-world-agent-pattern-the-research-agent\">A Real-World Agent Pattern: The Research Agent<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a practical, production-relevant agent pattern that Mumbai developers are using in 2026 \u2014 a research agent that takes a question, searches for information, synthesises it, and produces a structured report:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># research_agent.py<\/em>\n\nRESEARCH_SYSTEM_PROMPT = \"\"\"You are a precise research assistant. Your job is to:\n1. Understand the research question\n2. Break it into 2-4 specific search queries\n3. Execute each search\n4. Synthesise the results into a structured report\n\nOutput format for the final report:\n## Summary\n&#091;2-3 sentence executive summary]\n\n## Key Findings\n&#091;Bullet points of the most important facts]\n\n## Sources\n&#091;List of URLs from search results]\n\n## Confidence Level\n&#091;High \/ Medium \/ Low \u2014 based on how well the search results answered the question]\n\nAlways cite sources. Never state something as fact if you did not find it in a search result.\"\"\"\n\n<em># Tools for the research agent<\/em>\nRESEARCH_TOOLS = &#091;\n    <em># web_search tool (same schema as above)<\/em>\n    <em># Plus a \"save_to_file\" tool for outputting the report<\/em>\n]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This pattern \u2014 specialised system prompt + curated tool set \u2014 is how production agents are structured. The general-purpose agent we built first is a learning vehicle; real agents are purpose-built for a specific task class.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"evaluating-your-agent-does-it-actually-work\">Evaluating Your Agent: Does It Actually Work?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Building an agent that works in demo conditions is straightforward. Building one that works reliably across real inputs is engineering. Use these evaluation criteria:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Task completion rate:<\/strong>&nbsp;On a test set of 50 representative queries, what percentage does the agent complete correctly? Aim for &gt;85% before considering production deployment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Tool call accuracy:<\/strong>&nbsp;Are tools being called with correct parameters? Log all tool calls and review for parameter hallucinations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Loop efficiency:<\/strong>&nbsp;What is the average number of steps to complete a task? High step counts (&gt;8 for simple tasks) indicate reasoning inefficiency or tool quality issues.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Failure mode distribution:<\/strong>&nbsp;When the agent fails, how does it fail \u2014 does it give up gracefully, loop infinitely, or hallucinate a confident wrong answer? Graceful failures are acceptable; confident wrong answers are not.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Simple evaluation harness<\/em>\ndef evaluate_agent(agent: Agent, test_cases: list&#091;dict]) -&gt; dict:\n    results = {\"passed\": 0, \"failed\": 0, \"errors\": &#091;]}\n\n    for case in test_cases:\n        try:\n            response = agent.run(case&#091;\"input\"], verbose=False)\n            <em># Your validation logic here<\/em>\n            if case&#091;\"expected_contains\"] in response.lower():\n                results&#091;\"passed\"] += 1\n            else:\n                results&#091;\"failed\"] += 1\n                results&#091;\"errors\"].append({\n                    \"input\": case&#091;\"input\"],\n                    \"expected\": case&#091;\"expected_contains\"],\n                    \"got\": response&#091;:200]\n                })\n        except Exception as e:\n            results&#091;\"failed\"] += 1\n            results&#091;\"errors\"].append({\"input\": case&#091;\"input\"], \"error\": str(e)})\n\n    results&#091;\"accuracy\"] = results&#091;\"passed\"] \/ len(test_cases)\n    return results\n\n<em># Example test cases<\/em>\ntest_cases = &#091;\n    {\"input\": \"What is 25% of 400?\", \"expected_contains\": \"100\"},\n    {\"input\": \"What is the square root of 144?\", \"expected_contains\": \"12\"},\n    {\"input\": \"What time is it?\", \"expected_contains\": \"time\"},\n]\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-makes-mumbais-top-genai-engineers-stand-out\">What Makes Mumbai&#8217;s Top GenAI Engineers Stand Out<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The developers building production agents at Mumbai&#8217;s top Fintech companies and GCCs are not just people who can run a&nbsp;<code>pip install langchain<\/code>&nbsp;and follow a tutorial. They are engineers who:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Understand the ReAct loop well enough to debug it when it breaks at 2 AM<\/li>\n\n\n\n<li>Can write a system prompt that produces reliable, auditable agent behaviour across thousands of inputs<\/li>\n\n\n\n<li>Know when to reach for a framework and when to build from scratch<\/li>\n\n\n\n<li>Can evaluate agent quality systematically \u2014 not just &#8220;it works on my test case&#8221;<\/li>\n\n\n\n<li>Understand the cost implications of agent loops (each LLM call costs money; 10-step loops at scale are expensive)<\/li>\n\n\n\n<li>Have shipped an agent to production and survived the experience<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This is not knowledge you gain from reading documentation. It comes from building, breaking, debugging, and rebuilding \u2014 ideally with guidance from engineers who have already made the expensive mistakes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"build-your-first-production-agent-your-next-step\">Build Your First Production Agent: Your Next Step<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The code in this guide gives you a working agent. The gap between this working agent and a production-ready agent \u2014 one that handles edge cases reliably, integrates with real data sources, gets evaluated systematically, and can be extended by a team \u2014 is where most developers get stuck.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>TechPaathshala&#8217;s Advanced AI Agent Bootcamp<\/strong>&nbsp;is an intensive, hands-on programme for developers who are ready to go beyond tutorials and build real, production-grade agentic AI systems.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the bootcamp, you will:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Build three complete agents from scratch<\/strong>&nbsp;\u2014 a research agent, a data analysis agent, and a customer support agent \u2014 using the architecture covered in this guide, plus advanced patterns including multi-agent orchestration and stateful LangGraph workflows<\/li>\n\n\n\n<li><strong>Master production engineering practices<\/strong>&nbsp;\u2014 proper evaluation frameworks (RAGAS, DeepEval), logging and observability with LangSmith, cost optimisation for high-volume agent deployments, and failure mode analysis<\/li>\n\n\n\n<li><strong>Work with real Mumbai use cases<\/strong>&nbsp;\u2014 BFSI document intelligence, e-commerce customer support automation, developer productivity agents \u2014 building the domain context that makes your portfolio stand out<\/li>\n\n\n\n<li><strong>Get hands-on with multi-agent systems<\/strong>&nbsp;\u2014 CrewAI and LangGraph for complex workflows where multiple specialised agents collaborate on tasks no single agent can handle efficiently<\/li>\n\n\n\n<li><strong>Deploy to production<\/strong>&nbsp;\u2014 Docker containerisation, FastAPI integration, AWS Bedrock deployment, and the CI\/CD practices that make agent systems maintainable at scale<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The bootcamp is for developers with Python proficiency and some exposure to LLMs. No prior agent-building experience required \u2014 the curriculum starts from the architecture covered in this guide and builds to production-grade systems over 8 weeks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49&nbsp;<strong><a href=\"https:\/\/techpaathshala.com\/\">Apply for TechPaathshala&#8217;s Advanced AI Agent Bootcamp<\/a><\/strong>&nbsp;\u2014 and build the agent engineering skills that Mumbai&#8217;s top Fintech companies and GCCs are hiring for right now.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\"><em>TechPaathshala is a Mumbai-based technology education platform helping developers build production-grade AI skills \u2014 from Full Stack development to Agentic AI Engineering.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every developer who has used ChatGPT or GitHub Copilot has interacted with an LLM. Far fewer have built a system that uses an LLM as a&nbsp;reasoning engine&nbsp;\u2014 a system that can plan, remember, use external tools, and complete multi-step tasks autonomously. That is what this guide is about. This&nbsp;build AI agent from scratch developer guide&nbsp;walks [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":710,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"","ocean_second_sidebar":"","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"","ocean_custom_header_template":"","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"","ocean_menu_typo_font_family":"","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"","ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"on","ocean_gallery_id":[],"footnotes":""},"categories":[82],"tags":[],"class_list":["post-642","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gen-ai","entry","has-media"],"acf":[],"_links":{"self":[{"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/posts\/642","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/comments?post=642"}],"version-history":[{"count":2,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/posts\/642\/revisions"}],"predecessor-version":[{"id":973,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/posts\/642\/revisions\/973"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/media\/710"}],"wp:attachment":[{"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/media?parent=642"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/categories?post=642"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techpaathshala.com\/blog\/wp-json\/wp\/v2\/tags?post=642"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}