<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Deepak Patil</title>
    <description>The latest articles on DEV Community by Deepak Patil (@deepcodr).</description>
    <link>https://dev.to/deepcodr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F506947%2F8e927f68-a70c-40fd-9b85-94a5dd1b5137.png</url>
      <title>DEV Community: Deepak Patil</title>
      <link>https://dev.to/deepcodr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/deepcodr"/>
    <language>en</language>
    <item>
      <title>The Orchestrator in Agentic Systems</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Sat, 08 Aug 2026 09:20:28 +0000</pubDate>
      <link>https://dev.to/techtrails/the-orchestrator-in-agentic-systems-4oap</link>
      <guid>https://dev.to/techtrails/the-orchestrator-in-agentic-systems-4oap</guid>
      <description>&lt;p&gt;A multi-agent system without an orchestrator is just a collection of agents. Each one is capable, but none of them coordinated. They might all be excellent at their individual jobs - searching the web, writing code, calling APIs - but without something deciding what gets done, in what order, by whom, and what to do when a result comes back wrong, the system does not behave like a system. It behaves like a group project with no project manager.&lt;/p&gt;

&lt;p&gt;The orchestrator is the project manager. Its job is not to do the work. Its job is to make sure the work gets done - and that is a harder, more subtle problem than it sounds.&lt;/p&gt;




&lt;h2&gt;
  
  
  What an orchestrator is responsible for
&lt;/h2&gt;

&lt;p&gt;An orchestrator does four things, and only these four things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Decompose the goal.&lt;/strong&gt; Turn a high-level objective into a concrete set of subtasks. This is a planning problem, not an execution problem. The orchestrator decides &lt;em&gt;what&lt;/em&gt; needs to happen, not &lt;em&gt;how&lt;/em&gt; to do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Route tasks to the right workers.&lt;/strong&gt; Match each subtask to an agent capable of doing it. This requires knowing what tools and capabilities each worker has - not in detail, but well enough to delegate correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Manage state across the workflow.&lt;/strong&gt; As workers return results, the orchestrator decides what those results mean for the remaining plan. Sometimes a result changes the plan entirely. Sometimes it confirms the next step. The orchestrator holds the full picture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Synthesise the final output.&lt;/strong&gt; Worker outputs are partial. The orchestrator assembles them into a coherent response and decides when the goal has been met.&lt;/p&gt;

&lt;p&gt;Notice what is absent: the orchestrator does not call APIs, does not run code, does not search the web. It reasons about work and routes it. The moment an orchestrator starts executing, it loses the focus that makes it good at coordination.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building one from scratch
&lt;/h2&gt;

&lt;p&gt;Here is a minimal orchestrator in Python. It plans upfront, delegates to type workers, and synthesizes results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;orchestrator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Step 1: plan
&lt;/span&gt;    &lt;span class="n"&gt;plan_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Goal: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    Available workers: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Return a JSON array of steps: [{{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;worker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;}}]
    Return JSON only, no explanation.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_prompt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 2: execute each step, collect results
&lt;/span&gt;    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;worker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 3: synthesise
&lt;/span&gt;    &lt;span class="n"&gt;synthesis_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Original goal: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    Worker results: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Synthesise a final answer from these results.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;synthesis_prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things in this snippet are worth pulling apart.&lt;/p&gt;

&lt;p&gt;The orchestrator calls &lt;code&gt;llm()&lt;/code&gt; twice - once to plan, once to synthesize - but never once to execute. Execution is entirely delegated. If you find yourself adding a tool call directly inside the orchestrator loop, stop and ask whether a worker should own that instead.&lt;/p&gt;

&lt;p&gt;The plan is a first-class object - a list of typed steps, not an implicit chain of thought. This means you can inspect it, log it, replay it, and re-plan from any point when something goes wrong.&lt;/p&gt;

&lt;p&gt;Results are kept verbatim before synthesis. The orchestrator does not summarise early. It gives the synthesis step the full picture, letting the model decide what is relevant. Premature summarization is where context gets lost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Re-planning when reality diverges
&lt;/h2&gt;

&lt;p&gt;A fixed plan fails the moment a worker returns an unexpected result. A real orchestrator needs to decide: Does this change the remaining plan?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;orchestrator_with_replan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initial_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;worker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;# check if the result warrants re-planning
&lt;/span&gt;        &lt;span class="n"&gt;replan_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Remaining plan: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
        Latest result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

        Does this result change what should happen next?
        If yes, return a revised plan as JSON. If no, return null.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;replan_prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;null&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;revision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;synthesise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the plan-and-execute pattern from the last post made concrete. The orchestrator works from a checklist but checks after each result whether the checklist still makes sense. The loop terminates when the plan is empty, not when a fixed number of steps has run.&lt;/p&gt;




&lt;h2&gt;
  
  
  What frameworks add
&lt;/h2&gt;

&lt;p&gt;Writing an orchestrator from scratch gives you control and understanding, but production use cases introduce problems the snippet above does not handle: state that needs to persist across restarts, workflows that need branching and loops, and debugging when something goes wrong three levels deep. This is where the frameworks come in.&lt;/p&gt;

&lt;h3&gt;
  
  
  LangGraph
&lt;/h3&gt;

&lt;p&gt;LangGraph represents a workflow as a &lt;strong&gt;directed graph&lt;/strong&gt; - nodes are agents or functions, edges are transitions between them, and a centralized &lt;code&gt;StateGraph&lt;/code&gt; holds shared state across the whole run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;
    &lt;span class="n"&gt;final_answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;planner_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;researcher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;researcher_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coder_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesiser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;synthesiser_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;route_to_worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# function that reads state and picks next node
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;researcher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;researcher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesiser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesiser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesiser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graph-based model earns its complexity because it makes branching and cycles explicit. The conditional edge above is not hidden inside a prompt - it is code. You can read the graph and know exactly what routes exist. LangGraph also ships with &lt;strong&gt;checkpointers&lt;/strong&gt; that persist state to disk or a database, so a workflow that crashes halfway through can resume from the last checkpoint rather than starting over.&lt;/p&gt;

&lt;p&gt;The honest tradeoff: a simple workflow that would take 40 lines in plain Python takes closer to 120 in LangGraph. You pay in boilerplate. You get auditability, resumability, and explicit control flow in return.&lt;/p&gt;

&lt;h3&gt;
  
  
  AutoGen
&lt;/h3&gt;

&lt;p&gt;AutoGen takes a different approach. Instead of a graph, it models orchestration as &lt;strong&gt;message-passing between agents&lt;/strong&gt;. A &lt;code&gt;GroupChat&lt;/code&gt; manager decides which agent speaks next based on context, and agents broadcast their replies so everyone shares the same conversation history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;autogen&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AssistantAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserProxyAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GroupChat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GroupChatManager&lt;/span&gt;

&lt;span class="n"&gt;planner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AssistantAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Break goals into tasks.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;researcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AssistantAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;researcher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search and retrieve facts.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;coder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AssistantAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write and run Python code.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;critic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AssistantAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;critic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Review outputs for errors.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;group_chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GroupChat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;planner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;researcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;critic&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="n"&gt;max_round&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GroupChatManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;groupchat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;group_chat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;planner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initiate_chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Build a data pipeline for X.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;GroupChatManager&lt;/code&gt; is the orchestrator here. AutoGen v0.4 rebuilt this around an &lt;strong&gt;actor model&lt;/strong&gt; where each agent runs independently and communicates through typed messages - a cleaner design for truly concurrent workflows.&lt;/p&gt;

&lt;p&gt;The full-context broadcast is AutoGen's key architectural bet: every agent sees the whole conversation, which means specialist agents can catch problems earlier in the chain. The cost is that the context window fills faster in long workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  CrewAI
&lt;/h3&gt;

&lt;p&gt;CrewAI uses a &lt;strong&gt;role-driven&lt;/strong&gt; model. You define a crew of agents with named roles, assign tasks, and let the framework handle delegation. Configuration-first rather than code-first - most of the setup lives in YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crewai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;

&lt;span class="n"&gt;researcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Researcher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Find accurate information&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;backstory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expert at web research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Writer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Produce clear summaries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;backstory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Experienced technical writer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;research_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Research topic X&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;researcher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;write_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a summary of the research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;crew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;researcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;research_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write_task&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sequential&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;crew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kickoff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Process.hierarchical&lt;/code&gt; switches to an orchestrator model where a manager agent routes tasks dynamically rather than following a fixed sequence. CrewAI is the fastest path from idea to running prototype, but teams consistently report hitting its ceiling 6–12 months in when workflows grow beyond sequential or simple hierarchical patterns - at which point a migration to LangGraph tends to follow.&lt;/p&gt;

&lt;p&gt;The most honest guidance: start from scratch to understand the pattern, then adopt a framework when you need what it specifically offers - not because frameworks are the default. LangGraph is the current production default for teams that need long-running, resumable workflows with explicit control flow. CrewAI is the right choice when you need something working this week and can accept the ceiling. AutoGen is strongest when agents genuinely need to debate and revise rather than execute a fixed plan.&lt;/p&gt;




&lt;h2&gt;
  
  
  The orchestrator's failure modes
&lt;/h2&gt;

&lt;p&gt;The orchestrator is the single point of failure in a multi-agent system, which means its failure modes are expensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Over-delegation.&lt;/strong&gt; The orchestrator sends a task to a worker that is underspecified. The worker returns garbage. The orchestrator synthesises the garbage. Build task schemas - typed descriptions of what a worker expects - and validate them before dispatch, not after.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan rigidity.&lt;/strong&gt; An upfront plan that doesn't re-evaluate when results diverge will execute confidently toward a wrong answer. Build in a replan check after any result that introduces new information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Silent worker failures.&lt;/strong&gt; Workers that fail quietly return None or an empty string, which the orchestrator may synthesise as if it were real output. Workers should fail loudly with typed errors that the orchestrator can inspect and route around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context overload.&lt;/strong&gt; The orchestrator accumulates results from every worker. In a long workflow, its context fills with raw worker outputs. Pass summaries, not raw transcripts, unless the raw content is genuinely needed for synthesis.&lt;/p&gt;




&lt;p&gt;The orchestrator's value is its deliberate ignorance of the details. It does not know how to search the web, run code, or call an API. It knows what needs doing and who should do it. That separation - reasoning about work versus doing work - is what allows multi-agent systems to scale beyond what any single agent could manage alone.&lt;/p&gt;

&lt;p&gt;The loop is still the heartbeat. The orchestrator is the brain that decides how many loops to start, what they should do, and when to stop.&lt;/p&gt;

</description>
      <category>techtrails</category>
      <category>ai</category>
      <category>genai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Single-Agent vs Multi-Agent System</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Sat, 01 Aug 2026 18:33:43 +0000</pubDate>
      <link>https://dev.to/techtrails/single-agent-vs-multi-agent-system-4mde</link>
      <guid>https://dev.to/techtrails/single-agent-vs-multi-agent-system-4mde</guid>
      <description>&lt;p&gt;&lt;em&gt;When one loop is enough - and when you need a team&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The previous post ended with a loop: reason, act, observe, repeat. That loop, running inside a single agent, can handle a surprising range of tasks. But spend enough time building agents and you'll hit a wall. The task is too long for one context window. Two subtasks need to run at the same time. One part of the problem requires a specialist that would be noise everywhere else. When you hit that wall, you have a choice: push harder on the single agent or split the work across multiple agents. Knowing which to reach for - and why - is what this post is about.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a single agent actually is
&lt;/h2&gt;

&lt;p&gt;Before comparing, it's worth being precise. A single agent is one model, one context window, and one tool set, running one loop. Everything it has learned about the task lives in that growing history of thoughts, actions, and observations. Its memory is its context.&lt;/p&gt;

&lt;p&gt;That constraint is the source of both its simplicity and its limits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where a single agent excels:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks that fit comfortably in one context window&lt;/li&gt;
&lt;li&gt;Linear workflows where each step depends on the last&lt;/li&gt;
&lt;li&gt;Problems where keeping a shared mental model matters more than speed&lt;/li&gt;
&lt;li&gt;Prototyping - one loop is trivial to trace and debug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where it breaks down:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long tasks that exceed the context limit midrun&lt;/li&gt;
&lt;li&gt;Tasks with independent subtasks that could be parallelised&lt;/li&gt;
&lt;li&gt;Workflows that need different capabilities in different phases&lt;/li&gt;
&lt;li&gt;Any situation where one agent failing silently kills the whole job&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What a multi-agent system adds
&lt;/h2&gt;

&lt;p&gt;A multi-agent system is two or more agents coordinating to complete a task. Coordination can mean many things - one agent spawning others, agents running in parallel and reporting back, and a pipeline where each agent's output is the next agent's input. The common thread is that no single agent owns the whole task.&lt;/p&gt;

&lt;p&gt;This unlocks three things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallelism.&lt;/strong&gt; If you need to research five companies simultaneously, a single agent does them sequentially. A multi-agent system spawns five subagents and gets all five results at once. For I/O-bound tasks - anything involving search, API calls, or file reads - this is the primary win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specialisation.&lt;/strong&gt; A coding agent prompted and tooled for writing Python is better at writing Python than a generalist agent. A multi-agent system lets you route subtasks to agents built for them - a planner, a researcher, a coder, a critic — each with the right system prompt and the right tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context management.&lt;/strong&gt; Each subagent gets a fresh, focused context. Instead of one agent accumulating 50,000 tokens of noise from early steps, a subagent receives only what it needs to do its job. The orchestrator summarises and routes; the workers stay sharp.&lt;/p&gt;




&lt;h2&gt;
  
  
  The orchestrator–worker pattern
&lt;/h2&gt;

&lt;p&gt;The most common multi-agent architecture is a two-level hierarchy: one &lt;strong&gt;orchestrator&lt;/strong&gt; and one or more &lt;strong&gt;workers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The orchestrator receives the goal, makes a plan, and delegates subtasks. It does not do the work itself - it decides &lt;em&gt;what&lt;/em&gt; the work is and &lt;em&gt;who&lt;/em&gt; does it. Workers receive a scoped task, run their own loop, and return a result. They don't know about each other or the overall goal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;orchestrator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;worker_agents&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Break this goal into subtasks: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# plan = [{"task": "...", "agent": "researcher"}, ...]
&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;worker_agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;final_answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Synthesise these results: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;final_answer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;worker.run()&lt;/code&gt; is the same agent loop from the previous post - reason, act, observe, repeat - but scoped to a single subtask. The orchestrator never picks up a tool itself; it reads a plan and routes. The workers never see the big picture; they just solve their piece.&lt;/p&gt;

&lt;p&gt;This separation matters. It keeps orchestrator context lean (plans and results, not tool noise) and keeps worker context focused (one task, right tools, nothing else).&lt;/p&gt;




&lt;h2&gt;
  
  
  Parallelising with subagents
&lt;/h2&gt;

&lt;p&gt;When subtasks are independent, run workers concurrently. In Python, &lt;code&gt;asyncio&lt;/code&gt; or &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; are the usual choices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_parallel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;futures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;
                &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to watch. First, &lt;strong&gt;rate limits&lt;/strong&gt;: five agents hitting the same API simultaneously will hit quotas faster than one agent doing it sequentially. Build in back-off logic at the worker level, not just the orchestrator level. Second, &lt;strong&gt;result merging&lt;/strong&gt;: parallel results arrive out of order and may conflict. The orchestrator's synthesis step needs to handle gaps and contradictions, not assume clean, uniform output.&lt;/p&gt;




&lt;h2&gt;
  
  
  When multi-agent is the wrong answer
&lt;/h2&gt;

&lt;p&gt;Multi-agent systems have real costs, and reaching for them too early is one of the most common mistakes in agent engineering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complexity compounds.&lt;/strong&gt; A single agent failing is easy to diagnose - you read the trace. Multiple agents failing is a distributed systems problem. Which agent failed? Did the orchestrator misparse the result? Did the worker receive a bad task? Every hop is a new failure surface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency can get worse, not better.&lt;/strong&gt; Parallelism helps I/O-bound tasks. For CPU-bound or model-call-bound work, the overhead of spawning agents, merging results, and making extra orchestration calls can exceed what a single focused agent would have taken.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context hand-offs lose information.&lt;/strong&gt; When the orchestrator summarises a worker's result to pass to the next, it makes decisions about what to keep. Those decisions are lossy. A single agent that ran the whole task never had to summarise itself.&lt;/p&gt;

&lt;p&gt;The honest default: start with a single agent. Add a second agent when you have a concrete bottleneck - context overflow, a parallelism win you can measure, or a capability mismatch you cannot solve with a better prompt and better tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  A practical decision framework
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Reach for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Task fits in context, linear flow&lt;/td&gt;
&lt;td&gt;Single agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task exceeds context mid-run&lt;/td&gt;
&lt;td&gt;Orchestrator + summarising subagents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Independent subtasks, I/O-bound&lt;/td&gt;
&lt;td&gt;Parallel workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phases need different tool sets&lt;/td&gt;
&lt;td&gt;Specialist workers per phase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need a second opinion on outputs&lt;/td&gt;
&lt;td&gt;Critic agent in the loop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prototyping or debugging&lt;/td&gt;
&lt;td&gt;Single agent - always start here&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;A single agent is not a stepping stone to multi-agent. It is the right architecture for a large class of tasks and the one you should default to until you have a specific reason to split work. Multi-agent systems earn their complexity when tasks genuinely exceed what one context window can hold, when parallelism produces a real speed win, or when specialist agents meaningfully outperform a generalist on a defined subtask.&lt;/p&gt;

&lt;p&gt;The loop does not change. What changes are, who owns which part of it, and how do the pieces report back?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>techtrails</category>
      <category>agents</category>
      <category>genai</category>
    </item>
    <item>
      <title>Agent Memory &amp; Context Engineering</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Tue, 28 Jul 2026 18:41:11 +0000</pubDate>
      <link>https://dev.to/techtrails/agent-memory-context-engineering-1mb5</link>
      <guid>https://dev.to/techtrails/agent-memory-context-engineering-1mb5</guid>
      <description>&lt;p&gt;How agents remember - and why deciding what to forget is the real skill&lt;/p&gt;

&lt;p&gt;An agent that starts every step with a blank mind cannot really pursue a goal. It would reintroduce itself to you on every message, forget what it just tried, and repeat the same mistake forever. &lt;strong&gt;Memory&lt;/strong&gt; is what turns a stateless model into something that accumulates - that knows who you are, what it has already done, and what it learned last Tuesday. This post is about how that works and, more importantly, about the discipline of deciding what an agent should remember at all.&lt;/p&gt;

&lt;h1&gt;
  
  
  The context window is not memory.
&lt;/h1&gt;

&lt;p&gt;The first thing to unlearn: a model’s context window is not its memory. The context window is &lt;strong&gt;working memory - RAM, not a hard drive.&lt;/strong&gt; It is finite, it is reset on every request, and every token in it costs money and dilutes the model’s attention. Stuffing an entire conversation history and knowledge base into the prompt does not scale, and past a point it actively &lt;em&gt;hurts&lt;/em&gt; - the model loses the important signal in a sea of stale detail. Real memory lives outside the window and is selectively loaded into it when needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Four kinds of memory
&lt;/h1&gt;

&lt;p&gt;Borrowing loosely from cognitive science, agent memory is usually split into four types, and good systems use all of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Short-term/working memory&lt;/strong&gt; - the current conversation and the agent’s recent thoughts and observations. Lives in the context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-term episodic memory&lt;/strong&gt; - a record of &lt;em&gt;what happened&lt;/em&gt;: past conversations, decisions, and the outcomes of previous tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-term semantic memory&lt;/strong&gt; - facts and knowledge: who the user is, domain information, documents. This is what retrieval-augmented generation pulls from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Procedural memory&lt;/strong&gt; - &lt;em&gt;how to do things&lt;/em&gt;: learned skills, tool-use patterns, and reusable strategies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Short-term memory: the rolling buffer
&lt;/h1&gt;

&lt;p&gt;The simplest memory is just keeping recent turns in the prompt. The problem is that conversations outgrow the window, so the standard move is to keep the last few turns verbatim and &lt;strong&gt;summarise&lt;/strong&gt; the older ones into a compact note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="n"&gt;older&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;older&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize this conversation so far:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;older&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summary so far: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the prompt bounded while preserving the gist of what came before. It is crude, but it is the backbone of almost every chat agent in production.&lt;/p&gt;

&lt;h1&gt;
  
  
  Long-term memory: embeddings and vector search
&lt;/h1&gt;

&lt;p&gt;To remember across sessions, an agent writes information to an external store and retrieves it later by meaning rather than exact keywords. The mechanism is &lt;strong&gt;embeddings&lt;/strong&gt;: each piece of text is converted into a high-dimensional vector, stored in a vector database, and later retrieved by finding the vectors closest to the current query. This is what lets an agent recall a relevant fact even when you phrase your question completely differently from how the fact was stored.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Write a memory
&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User prefers window seats and vegetarian meals.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pref-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User prefers window seats and vegetarian meals.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Later, retrieve by meaning
&lt;/span&gt;&lt;span class="n"&gt;query_vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;book me a flight to Delhi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;span class="c1"&gt;# injected into the prompt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That retrieval step is what gives an agent its long memory without bloating the context window: you store everything but load only the handful of memories relevant to the moment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why vector search alone isn’t enough
&lt;/h1&gt;

&lt;p&gt;Vector similarity is powerful but blunt, and it is worth knowing its limits before you lean on it. Similarity relies on &lt;strong&gt;relevance - not recency, not authority, not workflow state.&lt;/strong&gt; It will happily surface an outdated preference the user changed yesterday or a fact from a draft that was later overruled, simply because the words are close. It does not understand which memory is current, which is authoritative, or where you are in a multi-step task. Production memory systems layer on recency weighting, source ranking, and explicit state to compensate. Memory in 2026 is treated as a real engineering discipline with measurable trade-offs, not a database you bolt on and forget.&lt;/p&gt;

&lt;h1&gt;
  
  
  Context engineering: the real skill
&lt;/h1&gt;

&lt;p&gt;All of this rolls up into the discipline people increasingly call &lt;strong&gt;context engineering&lt;/strong&gt;: deliberately deciding what goes into the context window on every single step. Prompt engineering asks &lt;em&gt;How do I word the instruction?&lt;/em&gt; Context engineering asks &lt;em&gt;What information should the model see right now, and what should I leave out?&lt;/em&gt; It is closer to managing a tight working-memory budget than to writing clever prompts.&lt;/p&gt;

&lt;p&gt;A recent and influential pattern is &lt;strong&gt;Agentic Context Engineering (ACE)&lt;/strong&gt;, which treats context as something the agent actively curates through a three-role loop: a &lt;strong&gt;Generator&lt;/strong&gt; produces an attempt, a &lt;strong&gt;Reflector&lt;/strong&gt; evaluates it and flags what was missing or wrong, and a &lt;strong&gt;Curator&lt;/strong&gt; distils the lesson into a growing “playbook” that improves future context. Reported results show meaningful accuracy gains on agent benchmarks &lt;em&gt;without retraining the underlying model&lt;/em&gt; - the improvement comes entirely from feeding it better context. That is the whole thesis of context engineering in one experiment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Practical patterns to start with
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Summarise old turns, keeping recent ones verbatim&lt;/strong&gt; - bounded prompt, preserved gist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve, don’t dump&lt;/strong&gt; - pull only the top few relevant memories per step instead of the whole store.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag memories with time and source&lt;/strong&gt; so you can prefer recent, authoritative information over stale matches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write back what matters&lt;/strong&gt; - after a task, save the durable facts and lessons, not the entire transcript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The takeaway
&lt;/h1&gt;

&lt;p&gt;Memory is what separates a chatbot from an agent that genuinely accumulates competence over time. But the headline isn’t “store everything” - it’s the opposite. The skill is curation: deciding, on every step, the smallest set of information that lets the model act well and leaving the rest in long-term storage until it’s needed. Treat context as critical infrastructure, and your agents get sharper, cheaper, and more reliable all at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next in the series:&lt;/strong&gt; One agent can only do so much. We’ll look at multi-agent systems - orchestration, the A2A protocol, and how to split a goal across a team of specialised agents without the whole thing collapsing into chaos.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>genai</category>
      <category>techtrails</category>
      <category>agents</category>
    </item>
    <item>
      <title>Tools, Function Calling &amp; MCP</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Thu, 23 Jul 2026 16:29:21 +0000</pubDate>
      <link>https://dev.to/techtrails/tools-function-calling-mcp-1ood</link>
      <guid>https://dev.to/techtrails/tools-function-calling-mcp-1ood</guid>
      <description>&lt;p&gt;How agents reach into the real world - and how to do it without creating a security nightmare&lt;/p&gt;

&lt;p&gt;A language model on its own is a brain in a jar. It can reason beautifully about the weather and tell you nothing about whether it is actually raining outside, because it has no senses and no hands. &lt;strong&gt;Tools&lt;/strong&gt; are the senses and hands. They are the single feature that turns a model that can &lt;em&gt;talk&lt;/em&gt; about booking a flight into an agent that can actually book one. In the last post we saw the agent loop; this post is about the &lt;em&gt;Act&lt;/em&gt; step inside that loop.&lt;/p&gt;

&lt;h1&gt;
  
  
  What a tool actually is
&lt;/h1&gt;

&lt;p&gt;Strip away the jargon and a tool is two things: a function, and a description the model can read. The function is ordinary code - a database query, an HTTP call, a shell command. The description is a schema that tells the model the tool’s name, what it does, and what arguments it takes. The model never sees your code; it only sees the schema and decides, in the moment, whether this tool is the right one for the goal in front of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return current conditions for a city.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;weather_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# The schema is what the MODEL sees:
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_weather&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Get current weather conditions for a city.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City name, e.g. &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Mumbai&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The one rule that keeps you safe: decide vs. execute
&lt;/h1&gt;

&lt;p&gt;Here is the most important sentence in this entire post. &lt;strong&gt;The model decides; your code executes.&lt;/strong&gt; When a model “calls a tool,” it does not run anything - it returns a structured request that &lt;em&gt;names&lt;/em&gt; a function and its arguments. Your application receives that request, decides whether it is allowed, runs the real function, and feeds the result back into the loop.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The LLM should decide what to do, but never be the thing that does it. Keep a layer of your own code between the model’s intent and any real-world effect.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That gap between intent and execution is where you put validation, permission checks, rate limits, and human approval for anything dangerous. Collapse that gap - let the model run code directly - and you have handed an unpredictable system the keys to your infrastructure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The full decide -&amp;gt; execute -&amp;gt; observe cycle
&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;schemas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;is_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;span class="c1"&gt;# YOUR guardrail
&lt;/span&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: not permitted.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;REGISTRYcall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt; &lt;span class="c1"&gt;# YOUR code runs it
&lt;/span&gt;    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
    &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;span class="c1"&gt;# model uses the results
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Designing tools the model can actually use
&lt;/h1&gt;

&lt;p&gt;An agent is only as capable as its tools are well-designed, and most agent failures trace back to a badly described or badly scoped tool rather than a weak model. A few principles go a long way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name and describe for the model, not for you.&lt;/strong&gt; cancel_order(order_id) with a one-line description of when to use it beats a clever internal name the model has to guess about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep each tool narrow.&lt;/strong&gt; One tool, one job. A single do_everything tool with a mode flag forces the model to reason about your implementation instead of the task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate inputs and fail informatively.&lt;/strong&gt; Return &lt;em&gt;“Error: city ‘Xyz’ not found, did you mean a valid city name?”&lt;/em&gt; rather than a stack trace. The model reads that error and corrects itself on the next loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer idempotency.&lt;/strong&gt; Agents retry. A tool that charges a card twice when called twice is a liability; design so repeats are safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The M×N problem, and why MCP exists
&lt;/h1&gt;

&lt;p&gt;Once tools work, a scaling problem appears. If you have M agent applications and N systems you want to connect (Slack, GitHub, your database, Google Drive), the naive world requires M×N custom integrations - every app re-implementing a connector to every system. The &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, introduced by Anthropic and now broadly adopted, collapses that into M+N. MCP is an open standard - often described as “USB-C for AI tools” - that defines a common way for a model to discover and call tools exposed by any compliant server.&lt;/p&gt;

&lt;p&gt;The division of labour in the 2026 agent stack is clean: &lt;strong&gt;MCP standardizes how agents talk to tools and data; the Agent-to-Agent (A2A) protocol standardizes how agents talk to each other.&lt;/strong&gt; Build a tool once as an MCP server and any MCP-aware client - LangGraph, CrewAI, ADK, a desktop assistant - can use it without bespoke glue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# A minimal MCP server exposing one tool (Python SDK)
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.server.fastmcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastMCP&lt;/span&gt;

&lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastMCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weather-server&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@mcp.tool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get current weather conditions or a city.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;weather_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;span class="c1"&gt;# any MCP client can now discover and call get_weather
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payoff is an ecosystem effect: the catalogue of ready-made MCP servers keeps growing, so connecting an agent to a new system increasingly means &lt;em&gt;pointing it at an existing server&lt;/em&gt; rather than writing an integration.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tools are your attack surface
&lt;/h1&gt;

&lt;p&gt;Every tool you give an agent is also a door someone could walk through. A tool that runs shell commands or sends money is exactly as dangerous in an agent’s hands as in an attacker’s, and prompt injection - hostile instructions hidden in a web page or document the agent reads - can trick an agent into misusing the tools it has. Treat tool access as a security boundary, not a convenience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Least privilege.&lt;/strong&gt; Give each agent the narrowest set of tools its job requires - nothing more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never auto-execute irreversible actions.&lt;/strong&gt; Payments, deletions, and trades should require explicit human confirmation, not an agent’s say-so.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate and sanitize all tool inputs&lt;/strong&gt;, exactly as you would for any untrusted user, because in effect they are&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools are what make an agent useful, and MCP is making them composable across the whole ecosystem. But the discipline that matters most is the gap you keep between the model’s decision and the real action - that gap is where your validation, permissions, and human oversight live. Get the tool design and that boundary right and you have an agent that is both genuinely capable and safe to put in front of real users.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>genai</category>
      <category>techtrails</category>
      <category>agents</category>
    </item>
    <item>
      <title>Inside The Agent Loop</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Tue, 21 Jul 2026 16:26:15 +0000</pubDate>
      <link>https://dev.to/techtrails/inside-the-agent-loop-2l7j</link>
      <guid>https://dev.to/techtrails/inside-the-agent-loop-2l7j</guid>
      <description>&lt;p&gt;How an agent actually thinks and acts: ReAct, tool calling, and the loop that powers every agent&lt;/p&gt;

&lt;p&gt;In the first post, we described an agentic system as software that can plan, reason, use tools, and execute multi-step workflows. This sentence hides the most important idea in the whole field. &lt;em&gt;What is actually happening when an agent “thinks”?&lt;/em&gt; The honest answer is surprisingly simple, and once you see it, every agent framework on the market stops looking like magic and starts looking like a single design pattern repeated with variations.&lt;/p&gt;

&lt;p&gt;The pattern is a loop. A plain language model answers your prompt once and stops. An agent wraps that same model in a loop (its output is fed as its next input and so on) that keeps running - reasoning, taking an action, observing the result, and reasoning again - until the goal is met. That loop is the heartbeat of every agent you will ever build.&lt;/p&gt;

&lt;h1&gt;
  
  
  From one-shot answers to a loop
&lt;/h1&gt;

&lt;p&gt;A chatbot is a function: text in, text out, done. The model never finds out whether its answer was any good. An agent breaks that single shot into a cycle. After each step it gets feedback from the real world and uses that feedback to decide what to do next. This is the difference between a student who writes an exam answer and walks away and a mechanic who turns a bolt, checks whether the engine starts, and adjusts.&lt;/p&gt;

&lt;p&gt;The most influential way to structure that cycle is the &lt;strong&gt;ReAct&lt;/strong&gt; pattern, introduced by Yao et al. in 2022. ReAct stands for &lt;strong&gt;Reason + Act&lt;/strong&gt;, and it interleaves three things on every turn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Thought&lt;/strong&gt; - a short chain-of-thought where the model reflects on the situation and decides what to do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action&lt;/strong&gt; - a concrete step, usually calling a tool or an API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observation&lt;/strong&gt; - the result that action produced, fed straight back into the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By forcing the model to reason in the open &lt;em&gt;and&lt;/em&gt; ground each decision in a real observation, ReAct reduces hallucination: the model cannot quietly invent a fact when the next line of the transcript is the actual output of a search it just ran.&lt;/p&gt;

&lt;h1&gt;
  
  
  A traced example
&lt;/h1&gt;

&lt;p&gt;Suppose the goal is "What &lt;em&gt;was the closing price of the stock the CEO of Tesla most recently tweeted about?”&lt;/em&gt; A ReAct trace might look like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Thought: I need to find Elon Musk's most recent tweet about a stock.&lt;/p&gt;

&lt;p&gt;Action: search_tweets(user="elonmusk", topic="stock")&lt;/p&gt;

&lt;p&gt;Observation: "Just bought more $X ..." (posted 2h ago)&lt;/p&gt;

&lt;p&gt;Thought: The ticker is X. I need today's closing price.&lt;/p&gt;

&lt;p&gt;Action:&amp;nbsp;get_quote(ticker="X")&lt;/p&gt;

&lt;p&gt;Observation: { "close": 41.80, "currency": "USD" }&lt;/p&gt;

&lt;p&gt;Thought: I now have the answer.&lt;/p&gt;

&lt;p&gt;Action: finish("The closing price was $41.80.")&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that no single model call could have answered this. The agent had to act, look at what came back, and only then decide its next move. That is the entire value proposition of the loop.&lt;/p&gt;

&lt;h1&gt;
  
  
  Building the loop from scratch
&lt;/h1&gt;

&lt;p&gt;Stripped of any framework, an agent loop is about a dozen lines. The model returns a structured decision; your code executes it and feeds the result back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_steps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# model reasons + picks an action
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;finish&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;
        &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# YOUR code runs the tool
&lt;/span&gt;        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Observation: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stopped: step budget exhausted.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three details in that snippet matter more than they look. First, the &lt;strong&gt;loop has a hard step budget&lt;/strong&gt; (max_steps). Without it, a confused agent will happily call tools forever and burn through your API bill. Second, &lt;strong&gt;the model never executes anything&lt;/strong&gt; - it only &lt;em&gt;names&lt;/em&gt; an action and arguments; your code decides whether and how to run it. Third, every observation is appended to history, so the model’s context grows with what it has learned.&lt;/p&gt;

&lt;h1&gt;
  
  
  ReAct text vs. native tool calling
&lt;/h1&gt;

&lt;p&gt;There are two ways to get that decision out of the model. The original ReAct approach asks the model to &lt;em&gt;write&lt;/em&gt; its thoughts and actions as text, which you then parse. Modern models offer &lt;strong&gt;native tool calling&lt;/strong&gt; (also called function calling): you hand the model a set of typed function schemas, and it returns a structured JSON object naming the function and its arguments - no fragile text parsing required.&lt;/p&gt;

&lt;h1&gt;
  
  
  Native tool calling: the model returns structured intent, not prose.
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_quote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Get the latest market quote for a ticker symbol.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="c1"&gt;# {name: "get_quote", args: {ticker: "X"}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trade-off is real and worth understanding. Text-based ReAct is &lt;strong&gt;transparent and model-agnostic&lt;/strong&gt; - you can read the reasoning, and it works on any model, even ones without a tool-calling API. Native tool calling is &lt;strong&gt;more efficient and reliable&lt;/strong&gt; - structured output, fewer round trips, and the model can request several tools at once - but the reasoning behind a call is less visible. In practice most production agents use native tool calling and recover transparency through tracing and logging.&lt;/p&gt;

&lt;h1&gt;
  
  
  When one loop isn’t enough: plan-and-execute
&lt;/h1&gt;

&lt;p&gt;Pure ReAct decides its next step one observation at a time, which is flexible but can wander on long tasks. A common evolution is &lt;strong&gt;plan-and-execute&lt;/strong&gt;: the agent first drafts a full plan and then executes the steps, replanning only when reality diverges. Separating slow, expensive planning from fast tactical execution tends to handle complex multi-step workflows more efficiently than reacting from scratch every turn. You can think of ReAct as improvising and plan-and-execute as working from a checklist you’re allowed to revise.&lt;/p&gt;

&lt;h1&gt;
  
  
  Where loops go wrong
&lt;/h1&gt;

&lt;p&gt;The loop is powerful precisely because it is open-ended, and that is also where the failure modes live. Agents get stuck repeating the same failing action, loop until the budget runs out, or call an expensive tool dozens of times. The defenses are unglamorous but essential: a hard step limit, detection of repeated identical actions, a cost ceiling, and clear tool error messages so the model can &lt;em&gt;recover&lt;/em&gt; rather than retry blindly. Treat every observation as something the model might misread, and design your tools to fail loudly and informatively.&lt;/p&gt;

&lt;h1&gt;
  
  
  The takeaway
&lt;/h1&gt;

&lt;p&gt;Every agent - from a customer-support bot to GitHub Copilot’s agent mode - is, at its core, this loop: “reason, act, observe, repeat, until done." "Frameworks add memory, multiple agents, and orchestration on top, but they are all variations on the same heartbeat. Once you can write the loop yourself, you understand agents from the inside, and every framework becomes a convenience rather than a mystery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next in the series, the&lt;/strong&gt; &lt;em&gt;Act&lt;/em&gt; step deserves its own post. We’ll go deep on tools, function calling, and the Model Context Protocol - how agents actually reach into the world without becoming a security liability.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>techtrails</category>
      <category>genai</category>
    </item>
    <item>
      <title>How to Efficiently Run Meta LLaMA on a MacBook Air M1 with Limited RAM</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Fri, 06 Dec 2024 15:16:20 +0000</pubDate>
      <link>https://dev.to/deepcodr/how-to-efficiently-run-meta-llama-on-a-macbook-air-m1-with-limited-ram-5c7l</link>
      <guid>https://dev.to/deepcodr/how-to-efficiently-run-meta-llama-on-a-macbook-air-m1-with-limited-ram-5c7l</guid>
      <description>&lt;p&gt;Running advanced AI models like Meta’s LLaMA on a MacBook might seem ambitious specifically when you have M1 with 8 GB of RAM, But with the right steps, you can start building AI apps locally on your Mac easily. Thanks to Apple’s processor architecture and efficient libraries like &lt;strong&gt;Llama.cpp&lt;/strong&gt;, you can unlock the power of large language models right from your lightweight laptop.&lt;/p&gt;

&lt;p&gt;Let's get you started with the MacBook Air M1 for running these models efficiently.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Download the entire model from Meta's official site by providing your information &amp;amp; details for usage.&lt;/p&gt;

&lt;p&gt;Install the necessary packages as mentioned in the readme file.&lt;/p&gt;

&lt;p&gt;Run the below command to run the model&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;torchrun \
  --nproc_per_node=$NGPUS \
  llama_models/scripts/example_chat_completion.py $CHECKPOINT_DIR \
  --model_parallel_size $NGPUS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Definitely, this is not going to work ☹️. To solve this issue we will be following two methods below&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;first, we will be using &lt;em&gt;llama.cpp&lt;/em&gt; which provides lightweight C++ implementation for running models on various hardware.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will use quantization to reduce the model size so that we will be able to run it easily.&lt;br&gt;
&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 1 (This one will work):&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Install llama.cpp using brew.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install llama.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let's quantize the llama model. To perform this we have a very good space on HuggingFace called GGUF-My-Repo. Follow the below link to go to space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://huggingface.co/spaces/ggml-org/gguf-my-repo" rel="noopener noreferrer"&gt;GGUF-MY-REPO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On this space login with your HuggingFace credentials. Then select the model repository that you want to quantize. For llama, you need to get access to the repo. Select the checkbox for 'Create a private repo under your username'. If you are a beginner then leave other options to default and proceed.&lt;/p&gt;

&lt;p&gt;Once the process is done you will have a quantized model created in your private repository.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clone the HuggingFace repo just created on your Mac. Run the model using the command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llama-cli -m GGUF_MODEL_FILE_NAME -n 1024 -ngl 1 -c 512 --prompt PROMT cnv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llama-cli -m meta-llama-3.1-8b-q4_k_m.gguf -n 1024 -ngl 1 -c 512 --prompt "Hello" -cnv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run directly from the repository name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llama-cli --hf-repo Deepcodr/llama_sample_chat-Q4_K_M-GGUF --hf-file llama_sample_chat-q4_k_m.gguf -p "The meaning to life and the universe is"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;br&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Tip:&lt;/strong&gt;&lt;/em&gt; If you are a beginner avoid using base models if you don't want to get some gibberish or random responses. Instead use instruct models such as chat, or text. etc. You can find some already quantized models &lt;a href="https://huggingface.co/Deepcodr" rel="noopener noreferrer"&gt;here&lt;/a&gt;

</description>
      <category>deepcodr</category>
      <category>ai</category>
      <category>machinelearning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to upload react build files to S3 from GitHub Actions</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Tue, 08 Oct 2024 07:25:07 +0000</pubDate>
      <link>https://dev.to/deepcodr/how-to-upload-react-build-files-to-s3-from-github-actions-15fc</link>
      <guid>https://dev.to/deepcodr/how-to-upload-react-build-files-to-s3-from-github-actions-15fc</guid>
      <description>&lt;p&gt;Every time you push new changes to your React app, it’s live on the web within minutes—no manual uploads, no repetitive commands, just pure automation magic. With GitHub Actions and Amazon S3, you can make it happen but there is a catch, Very few prebuilt scripts are available for uploading react build files to S3 from GitHub actions. In this post, Let's see how to connect the dots between your React project and AWS S3 using GitHub Actions, turning every code push into an automatic deployment.&lt;/p&gt;

&lt;p&gt;To begin with we need to create a script that will iterate over all files in the build folder and then use &lt;em&gt;&lt;strong&gt;aws-sdk&lt;/strong&gt;&lt;/em&gt; to upload all files to the S3 bucket configured with static website hosting. First we will import required packages to JS script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const S3 = require('aws-sdk/clients/s3');
const path =require('path');
const fs = require('fs');
const klawSync = require('klaw-sync');
const {lookup} = require('mime-types')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we will initialize the S3 client and get build folder path which will be generated from github action with &lt;code&gt;npm run build&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var awsoptions = {
    accessKeyId : process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey : process.env.AWS_ACCESS_KEY
}

const buildFolderPath = path.join(__dirname,'build')

var s3 = new S3(awsoptions);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we will use &lt;strong&gt;&lt;em&gt;klaw-sync&lt;/em&gt;&lt;/strong&gt; to get file path for each file and then upload that file to the S3 bucket using upload() function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const filePaths = klawSync(buildFolderPath,{
    nodir : true
});

filePaths.map((filePath)=&amp;gt;{
    const fileContent = fs.createReadStream(filePath.path);
    const bucketPath = path.join('',path.relative(buildFolderPath,filePath.path));


    config ={
        Bucket : 'YOUR_BUCKET_NAME',
        Body : fileContent,
        Key : bucketPath,
        ContentType : lookup(filePath.path) || "text/plain"
    }

    upload(config);
})

function upload(config){
    return new Promise((resolve) =&amp;gt; {
        s3.upload(config, (err, data) =&amp;gt; {
          if (err) console.error(err);
          console.log(`uploaded - ${data.Key}`);
          console.log(`located - ${data.Location}`);
          resolve(data.Location);
        });
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thats it place this script file in react project directory where package.json is present. Run this script from your github action workflow after building the react project. Once called it will upload all files from build folder to bucket. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Example job steps for building &amp;amp; uploading files&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    steps :
      - uses : actions/checkout@v4
      - uses : actions/setup-node@v4
        with :
          node-version : 20
      - name : Install node modules
        run : npm install
      - name : Build the project for production
        run : npm run build
      - name : Upload Files to S3
        run : node s3upload.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With GitHub Actions and S3 working together, deploying your React static site is no longer a tedious task but an automated part of your workflow. This setup not only saves time but also ensures that every time your static files get pushed to the bucket while developer can focus on development.&lt;/p&gt;

</description>
      <category>deepcodr</category>
      <category>react</category>
      <category>aws</category>
      <category>github</category>
    </item>
    <item>
      <title>What are AI accelerators or NPUs?</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Thu, 12 Sep 2024 14:46:50 +0000</pubDate>
      <link>https://dev.to/deepcodr/what-are-ai-accelerators-or-npus-187e</link>
      <guid>https://dev.to/deepcodr/what-are-ai-accelerators-or-npus-187e</guid>
      <description>&lt;p&gt;   With the increasing popularity of AI software &amp;amp; technologies, there is a need for specialized hardware units to provide high performance to AI services. Traditional processors like CPUs and GPUs often struggle with the massive computational load required by advanced machine learning models. &lt;strong&gt;Neural Processing Units (NPUs)&lt;/strong&gt;, often known as &lt;em&gt;AI accelerators&lt;/em&gt; or &lt;em&gt;DL(Deep Learning) Accelerators&lt;/em&gt;, are the answer to this problem. NPUs are specialized hardware designed to boost AI tasks by optimizing performance and energy efficiency. These purpose-built processors are revolutionizing AI application performance and data processing.&lt;br&gt;
   NPUs perform various complex computational operations required by AI efficiently compared to GPUs which are more power-consuming and come at cost. NPUs have dedicated hardware circuits for training models on Trillions of parameters. Currently, GPUs are gaining popularity due to their performance in training the models. But upcoming NPUs are disrupting this trend providing much more performance than GPUs.NPUs implement in-memory computing architecture allowing them to replicate human brain-like working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcfa9b1asf4vuwya8w44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcfa9b1asf4vuwya8w44.png" alt="AWS NPUs" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;em&gt;source : AWS&lt;/em&gt;
&lt;/h6&gt;

&lt;p&gt;   These devices can help build the most complex neural networks and vision applications. Implementing the circuit for performing three types of computations (scalar, vector, tensor) makes them the elite hardware for next-generation computers. Companies like Google, Intel, and AWS have already begun constructing their NPUs dedicated for computing devices and cloud infrastructures.AWS Inferentia &amp;amp; Trainium are the NPUs powering modern AI workloads in Cloud infrastructure. &lt;br&gt;
   With the research still going on to develop more efficient NPUs it is interesting to see what next things will come to the AI evolution.&lt;/p&gt;

</description>
      <category>deepcodr</category>
      <category>aws</category>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>How to install Nginx on Mac</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Wed, 04 Sep 2024 19:25:32 +0000</pubDate>
      <link>https://dev.to/deepcodr/how-to-install-nginx-on-mac-157i</link>
      <guid>https://dev.to/deepcodr/how-to-install-nginx-on-mac-157i</guid>
      <description>&lt;p&gt;Nginx is a widely used web server, valued for its speed and reliability in serving web content. Installing Nginx on macOS allows you to leverage its local development or testing capabilities. In this post, let's understand the steps to install Nginx smoothly on your Mac, making it easy to manage and serve your web projects.&lt;/p&gt;

&lt;p&gt;Although you can install Nginx from the source code on MacOS, it is a bit complex. So, HomeBrew is the best option for installing Nginx.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Steps to install Nginx on MacOS&lt;br&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;h6&gt;
  
  
  Install Homebrew Package Manager
&lt;/h6&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can install Homebrew from official &lt;a href="https://brew.sh/" rel="noopener noreferrer"&gt;website&lt;/a&gt; or Just enter below command to install.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;h6&gt;
  
  
  Install Nginx
&lt;/h6&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use the homebrew command below to install nginx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;h6&gt;
  
  
  Start &amp;amp; Use Nginx
&lt;/h6&gt;
&lt;/blockquote&gt;

&lt;p&gt;Start the Nginx service using brew.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew services start nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now go to &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; and you should see the Nginx welcome page.&lt;br&gt;
Below are some commands you can use for managing nginx service.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Stop&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew services stop nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Restart&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew services restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew services status nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default nginx on Mac uses 8080 port. You can change nginx.conf and update the port number to 80 so that it will serve directly on &lt;em&gt;&lt;em&gt;localhost&lt;/em&gt;&lt;/em&gt;.&lt;/p&gt;


&lt;p&gt;With Nginx now running on your macOS, you're ready to explore and deploy web apps with nginx.&lt;br&gt;&lt;br&gt;
&lt;/p&gt;


</description>
      <category>deepcodr</category>
      <category>webdev</category>
      <category>devops</category>
      <category>macos</category>
    </item>
    <item>
      <title>Using S3 Bucket to host React Application</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Mon, 26 Aug 2024 18:15:25 +0000</pubDate>
      <link>https://dev.to/deepcodr/using-s3-bucket-to-host-react-application-2cc</link>
      <guid>https://dev.to/deepcodr/using-s3-bucket-to-host-react-application-2cc</guid>
      <description>&lt;p&gt;It becomes confusing when it comes to deploying a React application in production. Because there are several ways we can deploy a React application in production. But considering a static single-page website hosting, there is one popular way: AWS S3.&lt;/p&gt;

&lt;p&gt;Hosting the React application in S3 not only provides a simple yet highly available deployment option but also brings other features to the table.S3 provides versioning, logging, and security features to make the experience more seamless. Integrating it with CloudFront makes it highly available, cacheable, and faster. S3 also allows CORS configuration, which can help to control access to the resources. Along with this bucket, it can be attached to a custom domain name configured with Route 53 or DNS, making a complete, full-fledged web application.&lt;/p&gt;

&lt;p&gt;Considering these features, S3 becomes the best option for deploying React in production. It only takes a few steps to deploy a React application to S3.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Create a S3 bucket in AWS&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create an S3 bucket as per the required configuration and storage class. Make sure to allow public access to all objects and remove any other blocking access options.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Generate a Production Build of React application&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Run the below command in the project root to generate a production build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this will create a build folder in the project directory with all static files.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Upload the build folder to S3 Bucket&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Upload the contents of the build folder to the bucket along with the static folder.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Add a policy to a bucket for getObject&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Edit the bucket policy to provide public access to get objects in the bucket. The policy will look like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Id": "Policy1729235341904",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1729235340511",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "YOUR-S3-BUCKET-ARN/*",
      "Principal": "*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Enable Static hosting for S3 Bucket&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the properties of the bucket enable static website hosting. Specify index and error document as index.html (Other names if differ). Save the changes.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Test the running website using the link&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Copy the generated link and paste it into the browser to view your website running. Add a custom domain if required.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;


&lt;p&gt;Thats it! In just a few clicks the React site is live using S3.&lt;br&gt;&lt;br&gt;
&lt;/p&gt;


</description>
      <category>deepcodr</category>
      <category>react</category>
      <category>javascript</category>
      <category>aws</category>
    </item>
    <item>
      <title>Which is the best stack for the web today? MERN vs MEAN vs Spring Boot</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Mon, 12 Aug 2024 13:37:15 +0000</pubDate>
      <link>https://dev.to/deepcodr/which-is-the-best-stack-for-the-web-today-mern-vs-mean-vs-spring-boot-5gkk</link>
      <guid>https://dev.to/deepcodr/which-is-the-best-stack-for-the-web-today-mern-vs-mean-vs-spring-boot-5gkk</guid>
      <description>&lt;p&gt;Many devs nowadays have a common question in their mind, which web frameworks and stacks are best to make a career? Well the question itself is unanswerable looking at the circumstances today. However, I will try to provide the best answer based on my experience and current market trends.&lt;/p&gt;

&lt;p&gt;Let's consider the three most used and popular stacks in the market today which are MERN, MEAN and Spring. All three of these stacks come with unique functionalities and applications fulfilling different use cases. If we look at MERN Or MEAN, They are more likely to be used for complete dynamic web application development while on the other hand, spring boot is suited for microservices and loosely coupled REST API-based enterprise applications.&lt;/p&gt;

&lt;p&gt;MERN and MEAN use javascript which makes it easy to write but still allows us to use it with modern features like NoSQL datasets, Caching etc. Similarly, Spring boot uses Java which is a language that is part of most of the legacy applications. Spring Boot makes a powerful framework that allows us to develop loosely coupled and serverless architectures. Looking at other features all stacks allow support for REST APIs, Scalability, and Fault tolerance by integrating with the cloud. &lt;/p&gt;

&lt;p&gt;key features of &lt;strong&gt;MEAN&lt;/strong&gt;, &lt;strong&gt;MERN&lt;/strong&gt;, and &lt;strong&gt;Spring Boot&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;MEAN Stack&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;MERN Stack&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Spring Boot&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MongoDB (NoSQL)&lt;/td&gt;
&lt;td&gt;MongoDB (NoSQL)&lt;/td&gt;
&lt;td&gt;SQL/NoSQL Databases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Server-Side Framework&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Express.js&lt;/td&gt;
&lt;td&gt;Express.js&lt;/td&gt;
&lt;td&gt;Spring Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Development Paradigm&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-Stack JavaScript, Single Page Application (SPA)&lt;/td&gt;
&lt;td&gt;Full-Stack JavaScript, Component-Based Architecture&lt;/td&gt;
&lt;td&gt;Enterprise-Level Application, Microservices Architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto-Configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Embedded Servers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (e.g., Tomcat, Jetty, Undertow)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microservices Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited, typically not the primary focus&lt;/td&gt;
&lt;td&gt;Limited, typically not the primary focus&lt;/td&gt;
&lt;td&gt;Strong support for microservices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Production-Ready Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Depends on configuration&lt;/td&gt;
&lt;td&gt;Depends on configuration&lt;/td&gt;
&lt;td&gt;Yes, includes metrics, health checks, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Depends on additional libraries&lt;/td&gt;
&lt;td&gt;Depends on additional libraries&lt;/td&gt;
&lt;td&gt;Built-in with Spring Security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MongoDB provides scalability for data&lt;/td&gt;
&lt;td&gt;MongoDB provides scalability for data&lt;/td&gt;
&lt;td&gt;High scalability, especially in microservices architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Angular ecosystem for front-end&lt;/td&gt;
&lt;td&gt;React ecosystem for front-end&lt;/td&gt;
&lt;td&gt;Comprehensive Spring ecosystem, including Spring Cloud, Spring Data, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Development Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast due to full-stack JavaScript and easy to understand&lt;/td&gt;
&lt;td&gt;Fast due to full-stack JavaScript and easy to understand&lt;/td&gt;
&lt;td&gt;Fast with Spring Boot’s auto-configuration and Spring Initializr but little bit complicated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So deciding which is better is not possible. But according to me for learning a framework as a novice, MERN or MEAN stacks are the best. Because it will give a proper understanding of how web applications or REST APIs work. On another hand, if you are already well familiar with working with Java-based applications and technologies like servlets, hibernate etc. It is better to advance yourself with the power of Spring Boot.&lt;/p&gt;

&lt;p&gt;Whichever framework you choose I prefer to dive deeper into it unless you feel lost in it and then you start exploring endless possibilities with it. Once you gain so much knowledge about a particular technology the question of the best stack to make career? becomes trivial.&lt;/p&gt;

</description>
      <category>deepcodr</category>
      <category>java</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>v0.dev :) Future of Web UI. Will UI and Frontend Devs exist in future?</title>
      <dc:creator>Deepak Patil</dc:creator>
      <pubDate>Fri, 26 Jul 2024 13:05:52 +0000</pubDate>
      <link>https://dev.to/deepcodr/v0dev-future-of-web-ui-will-ui-and-frontend-devs-exist-in-future-5h2</link>
      <guid>https://dev.to/deepcodr/v0dev-future-of-web-ui-will-ui-and-frontend-devs-exist-in-future-5h2</guid>
      <description>&lt;p&gt;Building and designing UIs from UI/UX tools like Figma and XD with languages like HTML, CSS, and JS is way too far for today's GenAI Web Development. From these tools to website builders like WordPress and Wix, and from these platforms to AI website builders, is the next step in the world of web development. &lt;strong&gt;v0.dev&lt;/strong&gt; by Vercel is the revolutionary platform that's turning the web development community on its head. With its innovative approach to design and automation, v0.dev raises the important question of &lt;em&gt;whether frontend and UI developers will soon be extinct?&lt;/em&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;In modern web development scenarios, implementing and leveraging the powers of GenAI is a powerful way of automating the entire web development cycle. &lt;strong&gt;v0.dev&lt;/strong&gt; implements a prompt-based UI creation tool based on Shadcn UI components and layouts. It is capable of generating UI within seconds with an elegant combination of components.&amp;nbsp;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Have a look at what it has generated within just a few clicks and prompts.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Generate a UI for product catalog of ecom website&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ja4r41uevrg0j7hhiv9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ja4r41uevrg0j7hhiv9.png" alt="Image description" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;It will take a lot of time for an experienced developer to develop such a page as compared to v0. Not only this, it also provides theming and customization options to make it more beautiful and brandy. We can copy the whole code for the UI in JSX or HTML. Just some configuration for the backend and the full-fledged site will be ready within a few minutes. And how can we forget Vercel? Using which site can be deployed and made live within another few clicks.&lt;/p&gt;

&lt;p&gt;Thus, using v0.dev and Vercel makes it a deadly combination for building web applications. Well, will it kill the jobs of web developers or UI designers is still a question. But the radical evolution in the field of web development with AI is an interesting thing to watch and observe what more it will bring to the table.&lt;/p&gt;

</description>
      <category>deepcodr</category>
      <category>webdev</category>
      <category>ui</category>
      <category>genai</category>
    </item>
  </channel>
</rss>
