{
  "id": 591497,
  "title": "Part 4: The Raw ReAct Loop: ~100 Lines, No Framework",
  "url": "https://urgent.news/2026/08/11/part-4-the-raw-react-loop-100-lines-no-framework",
  "topic": "ai",
  "section": "AI",
  "published": "2026-08-11T18:43:50.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/akashpal/part-4-the-raw-react-loop-100-lines-no-framework-5bi6"
  },
  "original_language": "en",
  "account": "In this fourth part of the series, we build a support-ticket agent from scratch without using any framework. The agent operates on a simple loop, consisting of calling a language model, checking if it requires a tool, running the tool if needed, and looping again until a final answer is produced or the ticket is escalated.\n\nThe process starts with initializing the state with the ticket and customer data. Then, a guardrail check is performed to prevent escalation before any model call. If an escalation pattern is detected, the agent returns an outcome of \"escalated\" with a final text message and state.\n\nNext, a Google Gemini AI model is initialized using the environment variable GEMINI_API_KEY. The agent prepares a user message from the ticket and creates a contents array containing the user role and message.\n\nA loop is initiated, iterating up to a maximum of 8 steps. In each step, the agent calls the AI model to generate a content. If the model response contains no function calls, the agent returns the final answer after processing and trimming the text.\n\nHowever, if function calls are present, the agent executes them one by one using the executeToolWithGuardrails function, which includes guardrails and approval gating. The agent continues to loop, appending the user role and the response parts to the contents array, until the maximum steps are reached or a final answer is returned.\n\nThe system prompt, defined in systemPrompt.ts, outlines the agent's role as a support agent for a specific company, its goal to resolve or escalate tickets efficiently, and the available tools. It also enforces certain policies, such as not calling issue_refund without a prior refund_eligibility result, not fabricating answers, and explicitly stating when uncertainty exists.\n\nFinally, the agent returns an outcome and finalText, either \"escalated\" with a message explaining the escalation or the resolved/refund_proposed/escalated message, depending on the agent's actions. The entire process is implemented in the runAgent function, which takes the ticket, customer, approval function, and maximum steps as parameters and returns an AgentResult object.",
  "summary": "Part 4 of a series building a support-ticket agent with no framework. Previous: Part 3 (the eval set). Repo: github.com/akash-pal/agent-from-scratch This is the part everyone reaches for a framework to skip. Here's the argument for not doing that, at least the first time: if you can't explain what your agent loop does in plain English, no framework is going to fix that — it's just going to make…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}