<?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: AI Coding Patterns</title>
    <description>The latest articles on DEV Community by AI Coding Patterns (@aicodingpatterns).</description>
    <link>https://dev.to/aicodingpatterns</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%2F4016597%2Fa1af4e5b-9767-4ed6-ad8e-99bb1d82bd7e.png</url>
      <title>DEV Community: AI Coding Patterns</title>
      <link>https://dev.to/aicodingpatterns</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aicodingpatterns"/>
    <language>en</language>
    <item>
      <title>Shieldstral: Why a 3B Guard Model Ties a 20B One</title>
      <dc:creator>AI Coding Patterns</dc:creator>
      <pubDate>Thu, 06 Aug 2026 19:37:39 +0000</pubDate>
      <link>https://dev.to/aicodingpatterns/shieldstral-why-a-3b-guard-model-ties-a-20b-one-179i</link>
      <guid>https://dev.to/aicodingpatterns/shieldstral-why-a-3b-guard-model-ties-a-20b-one-179i</guid>
      <description>&lt;p&gt;Some teams are paying for inference on a 20B model that reasons out loud for several hundred tokens just to decide whether a comment breaks their content policy. On August 4th Mistral released Shieldstral, a 3B classifier that answers the same question with a single token &lt;sup&gt;[1]&lt;/sup&gt;. What's worth digging into is where that difference comes from, because it isn't the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Taxonomy Is Baked Into the Weights
&lt;/h2&gt;

&lt;p&gt;The problem with classic guard models is that the list of harm categories gets fixed during training. A guard model is a small model dedicated to one thing: looking at a piece of text or an image and saying whether it violates a policy. It's the concrete implementation of what I call a &lt;a href="https://aicodingpatterns.com/patterns/que-es-un-guardarrail-en-ia/" rel="noopener noreferrer"&gt;guardrail&lt;/a&gt; in other posts, applied to content. LlamaGuard and ShieldGemma work this way, and both carry their taxonomy inside the weights.&lt;/p&gt;

&lt;p&gt;That breaks down the moment your product isn't the average product. Text describing how to exploit a known vulnerability is normal content in a pentesting tool and material to block in a teen companion app: the same document, two legitimate verdicts. With the taxonomy baked into the weights, adjusting that nuance means relabeling a dataset and retraining.&lt;/p&gt;

&lt;p&gt;And retraining over a policy change is an absurd cost for something that, looked at closely, is just text.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Shieldstral Turn Moderation Into a Yes-or-No Question?
&lt;/h2&gt;

&lt;p&gt;Shieldstral frames moderation as a binary-answer task: it receives a written policy and a question, and answers "yes" or "no". The prompt has three fields &lt;sup&gt;[1]&lt;/sup&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Instruct&amp;gt;
You are a moderator for a cybersecurity community. Be strict about
operational instructions targeting specific systems, and permissive
with theory and educational discussion.
&amp;lt;/Instruct&amp;gt;

&amp;lt;Query&amp;gt;
Does this message give actionable instructions for attacking someone
else's system?
&amp;lt;/Query&amp;gt;

&amp;lt;Document&amp;gt;
[the user's message, the model's response, or an image]
&amp;lt;/Document&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;Instruct&amp;gt;&lt;/code&gt; sets the context and the bar for enforcement, &lt;code&gt;&amp;lt;Query&amp;gt;&lt;/code&gt; is the question being answered, and &lt;code&gt;&amp;lt;Document&amp;gt;&lt;/code&gt; is what's being judged: text, an image, or both at once. With that format, four problems you'd normally solve with four separate models collapse into one: classifying the user's prompt, moderating the model's response, detecting whether the model refused to answer, and detecting toxicity &lt;sup&gt;[1]&lt;/sup&gt;. Change the &lt;code&gt;&amp;lt;Query&amp;gt;&lt;/code&gt; and you change the problem.&lt;/p&gt;

&lt;p&gt;What matters about this design is where your policy ends up living: in the prompt. Adjusting the line between what's acceptable and what isn't becomes editing a paragraph and re-evaluating, not opening a training notebook.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Score Comes From Two Logits, Not Generated Text
&lt;/h2&gt;

&lt;p&gt;At inference time Shieldstral doesn't generate text. It runs a forward pass, reads the logits for the "yes" and "no" tokens, and normalizes with softmax over just those two &lt;sup&gt;[3]&lt;/sup&gt;. A logit is the raw score the model assigns to each candidate token before it's converted into a probability; in &lt;a href="https://aicodingpatterns.com/patterns/respuesta-mas-probable-no-correcta/" rel="noopener noreferrer"&gt;the most probable answer isn't the correct one&lt;/a&gt; I explain what that distribution means.&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;# Safety score without generating a single output token
# pseudocode; the real snippet with transformers is on the HF model card
&lt;/span&gt;&lt;span class="n"&gt;logits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;          &lt;span class="c1"&gt;# next-token distribution
&lt;/span&gt;&lt;span class="n"&gt;z_yes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z_no&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tok_yes&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tok_no&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z_yes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z_yes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z_no&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# softmax over two tokens
&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;                       &lt;span class="c1"&gt;# default threshold
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a continuous number between 0 and 1, with a default threshold of 0.5 &lt;sup&gt;[3]&lt;/sup&gt;, instead of a fixed label. Coming out of a softmax, it behaves like a probability: the score is calibrated, and the threshold becomes your decision. You can raise it where a false positive annoys the user, lower it where a false negative costs you an incident, and route only the middle band to human review. With a plain binary label you don't have that lever.&lt;/p&gt;

&lt;p&gt;The obvious comparison is GPT-OSS-Safeguard-20B, which also accepts your policy in the prompt, but produces a full reasoning chain before the verdict. Same average text F1 (84.9%), a whole different order of cost per call &lt;sup&gt;[2]&lt;/sup&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Shieldstral-1.0-3B&lt;/th&gt;
&lt;th&gt;GPT-OSS-Safeguard-20B&lt;/th&gt;
&lt;th&gt;OmniGuard-7B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Parameters&lt;/td&gt;
&lt;td&gt;3B&lt;/td&gt;
&lt;td&gt;20B&lt;/td&gt;
&lt;td&gt;7B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average text F1&lt;/td&gt;
&lt;td&gt;84.9%&lt;/td&gt;
&lt;td&gt;84.9%&lt;/td&gt;
&lt;td&gt;not reported in the paper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multimodal F1&lt;/td&gt;
&lt;td&gt;83.8% (state of the art)&lt;/td&gt;
&lt;td&gt;text only&lt;/td&gt;
&lt;td&gt;77.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How it emits the verdict&lt;/td&gt;
&lt;td&gt;"yes"/"no" logits in a single forward pass, continuous score&lt;/td&gt;
&lt;td&gt;generates a reasoning trace, then the label&lt;/td&gt;
&lt;td&gt;label&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where the policy lives&lt;/td&gt;
&lt;td&gt;in the prompt&lt;/td&gt;
&lt;td&gt;in the prompt&lt;/td&gt;
&lt;td&gt;training taxonomy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;td&gt;check its model card&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 3B model matching a 20B model on average text benchmarks isn't explained by architecture or by more inference-time compute. It's explained by the dataset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contrastive Pairs: The Same Document, Opposite Verdicts
&lt;/h2&gt;

&lt;p&gt;The most interesting part of the technical report is how they generated the data so the model learns which specific policy is being violated, instead of a crude safe/unsafe distinction. They trained on roughly 54.1M examples, of which 4.4M are synthetic contrastive pairs &lt;sup&gt;[2]&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;A contrastive pair is the same document evaluated twice against two sibling-category questions: for one the correct answer is "yes" and for the other it's "no". A text about drug dosage can violate "unsupervised medical advice" without violating "promotion of illegal substances". If the model only sees examples labeled toxic or non-toxic, it learns a general sense of toxicity and misses the distinction. If it sees the same paragraph with opposite verdicts depending on the question, it has no choice but to read the &lt;code&gt;&amp;lt;Query&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They validated against an evaluation taxonomy deliberately different from the training one, which is the only honest way to measure whether the prompt's policy is actually being used. Without the synthetic data, 61.1% F1. With it, 84.4% &lt;sup&gt;[2]&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Twenty-three points that didn't come from more parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Final Checkpoint Is a Merge of Three Models
&lt;/h2&gt;

&lt;p&gt;Shieldstral isn't the direct output of a single training run: it's a weight merge of three models. Model merging means interpolating the weights of several checkpoints to get a new one without any further training, and here they used SLERP (spherical interpolation between weights, not a linear average) with 0.6 from the checkpoint trained on synthetic data, 0.3 from the one trained on public data, and 0.1 from the starting instruct model &lt;sup&gt;[2]&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The blend outperforms any of its ingredients: on adaptation to new taxonomies it goes from 84.4% to 88.7% F1. Those four points come from an algebra operation on the weights.&lt;/p&gt;

&lt;p&gt;There's an extra data point in the paper that will save you money if you end up adapting it to your domain: LoRA (training a few small matrices added to the model instead of all its weights) performs nearly as well as full fine-tuning on this task, 87.1% versus 87.8% on Aegis v2, one of the safety benchmarks used in the evaluation &lt;sup&gt;[2]&lt;/sup&gt;. Seven-tenths of a point of difference for a fraction of the cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  When It's Worth It, and When It Isn't
&lt;/h2&gt;

&lt;p&gt;Shieldstral makes sense when you have your own policy and volume. The cost per call is a forward pass on a 3B model that fits on a 16 GB GPU &lt;sup&gt;[1]&lt;/sup&gt;, so the economics change compared to billing reasoning tokens for every comment that comes in. If you're also moderating images: 83.8% multimodal F1 versus OmniGuard-7B's 77.6% &lt;sup&gt;[2]&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Where it falls apart is in low-resource languages, and the paper itself publishes this. In Indonesian, prompt classification drops to 55.5% F1 while response classification in that same language scores 94.1% &lt;sup&gt;[2]&lt;/sup&gt;. Same model, same language, and nearly forty points of difference depending on what you ask it to do.&lt;/p&gt;

&lt;p&gt;That's the reading that matters for your decision: the 84.9% average is an average. Before you put this in front of real users, look up your language and your specific task in the appendix tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Choosing the Guard Model by Size
&lt;/h3&gt;

&lt;p&gt;It's the natural instinct, and it doesn't work here. The "more parameters, better result" curve applies to open-ended tasks; on a bounded task like deciding whether a document answers "yes" to a question, what moves the needle is the data. The contrastive-pair ablation is worth more than multiplying the model by seven.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trusting the Average F1
&lt;/h3&gt;

&lt;p&gt;If the appendix's per-language breakdown shows 55.5% in your primary language and you decided based on the front-page 84.9%, you've shipped a moderator that fails almost half the time in your market. Read the breakdown before the headline number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retraining a Classifier When the Policy Fits in the Prompt
&lt;/h3&gt;

&lt;p&gt;This is the expensive mistake. A team with its own classifier in production handles every policy change by opening up the training pipeline, because that's what it knows how to do. With a model that reads the policy from the prompt, that change is editing the &lt;code&gt;&amp;lt;Instruct&amp;gt;&lt;/code&gt; block, running it against your eval set, and comparing results. From weeks to an afternoon. The condition is having that eval set: without it, editing the prompt means changing behavior blind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paying for a Reasoning Trace on Every Message
&lt;/h3&gt;

&lt;p&gt;A judge with explicit reasoning is a great tool for ambiguous cases, quality reviews, or auditing questionable decisions. Using it for 100% of a high-volume platform's traffic means paying for an explanation nobody reads. Reserve reasoning for the middle band of scores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist Before Putting a Guard Model in Production
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] You have your own eval set, built from your product's content and labeled with your policy&lt;/li&gt;
&lt;li&gt;[ ] You've read the model's per-language and per-task breakdown, not just the average&lt;/li&gt;
&lt;li&gt;[ ] The policy is written in the prompt and versioned in the repo, not scattered across the team's heads&lt;/li&gt;
&lt;li&gt;[ ] The threshold is set per product and per surface, not inherited from the default without thinking&lt;/li&gt;
&lt;li&gt;[ ] There's a middle score band that routes to human review or a reasoning model&lt;/li&gt;
&lt;li&gt;[ ] You're measuring false positives in production, not just the benchmark F1&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://mistral.ai/news/shieldstral/" rel="noopener noreferrer"&gt;Shieldstral — Mistral AI&lt;/a&gt; — official announcement from August 4, 2026: the three-field format, the four problems covered, running on a single 16 GB GPU, and the claim of matching models up to seven times its size.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2607.25857" rel="noopener noreferrer"&gt;Shieldstral — arXiv:2607.25857&lt;/a&gt; — technical paper on the multimodal safety classifier: text and multimodal F1, dataset size and composition, the contrastive-pairs ablation, the SLERP merge weights, LoRA versus full fine-tuning, and the per-language breakdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://huggingface.co/mistralai/Shieldstral-1.0-3B" rel="noopener noreferrer"&gt;mistralai/Shieldstral-1.0-3B — Hugging Face&lt;/a&gt; — model card: Ministral-3B base, Pixtral vision encoder, how the score is computed from the "yes"/"no" logits, the default 0.5 threshold, and the list of supported languages.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a guard model and how is it different from a regular LLM?
&lt;/h3&gt;

&lt;p&gt;A guard model is a model trained to classify content against a safety policy, not to converse or write: it takes in a document and returns a verdict on whether it violates a rule. In Shieldstral the output is a probability between 0 and 1 derived from two logits, without generating a single sentence, which is far cheaper than asking a general-purpose model the same question.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Shieldstral replace moderation APIs like OpenAI's or Azure's?
&lt;/h3&gt;

&lt;p&gt;It depends on whether your policy fits theirs. Managed APIs moderate against categories defined by the provider and don't require you to run any infrastructure; Shieldstral requires you to serve the model yourself, but in exchange you write the policy in the prompt and your content never leaves your network.&lt;/p&gt;

&lt;p&gt;If your criteria are standard and your volume is low, the API comes out cheaper in engineering time.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does it mean for the score to be calibrated?
&lt;/h3&gt;

&lt;p&gt;That you can treat the number as a confidence level and cut wherever suits you: above 0.8 you auto-block, between 0.4 and 0.8 you send to human review. The default threshold is 0.5 &lt;sup&gt;[3]&lt;/sup&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I fine-tune Shieldstral with my own policy?
&lt;/h3&gt;

&lt;p&gt;You can, but try editing the prompt first: the model is specifically trained so the policy can live there. If you still need to adapt it after that, the paper measures LoRA against full fine-tuning on this task and the gap is seven-tenths of a point of F1 &lt;sup&gt;[2]&lt;/sup&gt;, so start with LoRA.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does it work in Spanish?
&lt;/h3&gt;

&lt;p&gt;Yes. Spanish is among the supported languages listed on the model card &lt;sup&gt;[3]&lt;/sup&gt;, alongside English, French, German, Italian, Portuguese, Dutch, Chinese, Japanese, Korean, Arabic, and Russian. Even so, the paper's per-language breakdown shows large gaps between languages and tasks, so evaluate it against your own Spanish-language content before trusting the global average.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://aicodingpatterns.com/en/patterns/shieldstral-moderacion-como-pregunta/" rel="noopener noreferrer"&gt;AI Coding Patterns&lt;/a&gt; — visual, interactive courses to learn programming with AI. Explore the &lt;a href="https://aicodingpatterns.com/en/" rel="noopener noreferrer"&gt;courses&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>opensource</category>
      <category>llm</category>
    </item>
    <item>
      <title>Prompt Chaining: How to Break Down Complex Tasks Into Simple Steps</title>
      <dc:creator>AI Coding Patterns</dc:creator>
      <pubDate>Tue, 21 Jul 2026 14:12:02 +0000</pubDate>
      <link>https://dev.to/aicodingpatterns/prompt-chaining-how-to-break-down-complex-tasks-into-simple-steps-4hjp</link>
      <guid>https://dev.to/aicodingpatterns/prompt-chaining-how-to-break-down-complex-tasks-into-simple-steps-4hjp</guid>
      <description>&lt;p&gt;The first time I tried to do something useful with an LLM in code, I asked it to do everything at once: "analyze this review, extract the main emotions, classify it, and return the result in JSON". The model tried, but somewhere in the process it lost the thread, mixed up steps, and the final JSON was useless. The solution wasn't a better model. It was breaking the problem down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before we start:&lt;/strong&gt; to follow this post you need to know what an LLM is (a language model like ChatGPT or Claude that generates text from instructions) and have written some TypeScript or JavaScript. That's all you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: asking it to do everything at once
&lt;/h2&gt;

&lt;p&gt;Imagine going to the supermarket and, right as you walk through the door, someone shouts a list of 10 different things at you without giving you time to write them down. You'll probably manage to get the bread and milk right, but you'll end up forgetting half of it or buying the wrong product. The same thing happens to AI models.&lt;/p&gt;

&lt;p&gt;Every time you send an instruction to a model, that's called a &lt;strong&gt;prompt&lt;/strong&gt;: it's the text you send, the question or task you want it to solve. When a prompt mixes four different tasks, the model has to keep them all "in mind" at the same time. It usually starts well, but at some point it makes an error. And that error carries through to the end.&lt;/p&gt;

&lt;p&gt;The solution is simple: one step, one call.&lt;/p&gt;

&lt;h2&gt;
  
  
  How chaining works
&lt;/h2&gt;

&lt;p&gt;Prompt chaining divides a complex task into a &lt;strong&gt;chain of calls to the LLM&lt;/strong&gt;. Each call solves only one part of the problem, and the response from that step becomes the input to the next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fprompt-chaining%2Fdiagrams%2Fpipeline-flujo-datos.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fprompt-chaining%2Fdiagrams%2Fpipeline-flujo-datos.svg" title="Each LLM call receives only the clean data from the previous step, not the complete accumulated context." alt="1.00" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A concrete example. You want to process the resumes that arrive at your company:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Call 1:&lt;/strong&gt; "Extract only the work experience from this document."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Call 2:&lt;/strong&gt; "Calculate the total years of experience based on that excerpt."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Call 3:&lt;/strong&gt; "Classify the profile as Junior, Mid, or Senior based on those years."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Call 4:&lt;/strong&gt; "Draft a follow-up email for the candidate based on that classification."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each call has a single responsibility. The model in step 4 doesn't need to read the entire three-page resume: it only receives the clean label ('Senior') from step 3 and works with that.&lt;/p&gt;

&lt;p&gt;This pattern has existed in classic software for decades. It's called &lt;strong&gt;Pipe &amp;amp; Filter&lt;/strong&gt;: data passes through a series of independent transformations, and each filter does one thing well. LLMs are simply another type of filter.&lt;/p&gt;

&lt;h2&gt;
  
  
  When does it make sense to use it?
&lt;/h2&gt;

&lt;p&gt;It makes sense when the task has &lt;strong&gt;clear sequential sub-steps&lt;/strong&gt;. Writing an SEO article is the textbook example: first you generate the outline, then you develop each section, then you review the tone. Each step depends on the previous one but does something different.&lt;/p&gt;

&lt;p&gt;It also makes sense when you need to &lt;strong&gt;verify intermediate results&lt;/strong&gt;. If step 1 extracts entities from text and the result comes back empty, there's no point spending money on steps 2 and 3. You can stop there.&lt;/p&gt;

&lt;p&gt;When not to use it is equally important. If the task is straightforward ("summarize this in three points", "translate this sentence"), a single well-written prompt solves it. Adding steps only adds latency and cost. Before designing a pipeline, ask yourself: can I solve this with a single well-structured call? If the answer is yes, do it that way. The post on &lt;a href="https://aicodingpatterns.com/en/patterns/prompt-engineering-patrones-desarrolladores/" rel="noopener noreferrer"&gt;prompt engineering for developers&lt;/a&gt; covers the basic patterns for building those effective prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate: how to prevent errors from multiplying
&lt;/h2&gt;

&lt;p&gt;Between steps, you have to validate. That's a &lt;strong&gt;gate&lt;/strong&gt;: a block of code that checks if the result from the previous step is valid before continuing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fprompt-chaining%2Fdiagrams%2Fgate-early-exit.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fprompt-chaining%2Fdiagrams%2Fgate-early-exit.svg" title="The gate stops the pipeline at the first failure instead of propagating the error to subsequent steps." alt="1.00" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without gates, this happens: step 1 generates text with the wrong format (what's called a &lt;strong&gt;hallucination&lt;/strong&gt; when the model invents or distorts the expected response). Step 2 receives that as input and produces something worse. Step 3 receives what step 2 made. By the time you reach the final output, the original error has multiplied and it's impossible to know where it started.&lt;/p&gt;

&lt;p&gt;The simplest gate is a function that returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. If it returns &lt;code&gt;false&lt;/code&gt;, you apply an &lt;strong&gt;early exit&lt;/strong&gt;: you exit the pipeline before reaching the end, return a clear error message, and don't spend more calls or money.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aicodingpatterns.com/en/patterns/guardarrailes-agentes-ia-como-implementarlos/" rel="noopener noreferrer"&gt;Guardrails in AI agents&lt;/a&gt; are the broader concept (the general boundaries on what the system can do), but in a sequential pipeline the gate is its most concrete and practical version.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pipeline in TypeScript, step by step
&lt;/h2&gt;

&lt;p&gt;Here's a working example. Two steps with a gate between them, no framework, just the official Anthropic SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the client (uses the ANTHROPIC_API_KEY environment variable)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Reusable helper: send a prompt to the LLM and return the text&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;llamarLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;respuesta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-haiku-4-5-20251001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// fast model, ideal for simple steps&lt;/span&gt;
      &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                     &lt;span class="c1"&gt;// maximum tokens it can generate&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// Check the block type: the API can return text, images, or other types&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bloque&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;respuesta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;bloque&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;bloque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;El modelo no devolvió un bloque de texto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;bloque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error calling the LLM: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&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="c1"&gt;// Gate: checks that the summary has reasonable length&lt;/span&gt;
&lt;span class="c1"&gt;// This gate is deliberately simple. In production, typical gates include:&lt;/span&gt;
&lt;span class="c1"&gt;// regex to verify expected format (/^(positive|negative|neutral)$/.test(output)),&lt;/span&gt;
&lt;span class="c1"&gt;// JSON.parse() for structured outputs (try { JSON.parse(output) } catch { early exit }),&lt;/span&gt;
&lt;span class="c1"&gt;// or a second LLM call when validation requires semantic judgment.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;esResumenValido&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;analizarResena&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resena&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// In production: validate and limit user input before interpolating it&lt;/span&gt;
  &lt;span class="c1"&gt;// Step 1: summarize the review&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resumen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;llamarLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`Resume esta reseña de cliente en una sola frase:\n\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resena&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[paso 1] resumen:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Gate: if the summary is invalid, early exit&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;esResumenValido&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No se pudo generar un resumen válido. Revisa el input.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Step 2: classify using ONLY the summary, not the complete review&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clasificacion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;llamarLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`Clasifica este texto como "positivo", "negativo" o "neutral":\n\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="nx"&gt;resumen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clasificacion&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;p&gt;Notice in step 2: we pass &lt;code&gt;resumen&lt;/code&gt;, not &lt;code&gt;resena&lt;/code&gt;. The classification model doesn't need to read the complete original text. Passing less is cheaper and faster.&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;context window&lt;/strong&gt; comes in (the amount of text you can send to a model in a single call, with a maximum limit). In long pipelines, if you don't filter what you pass in each step, the cost explodes without improving results. The post on &lt;a href="https://aicodingpatterns.com/en/patterns/ventana-contexto-buenas-practicas/" rel="noopener noreferrer"&gt;context window and best practices&lt;/a&gt; goes into detail on how to manage it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistakes everyone will make
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Too many steps for too little
&lt;/h3&gt;

&lt;p&gt;A six-step pipeline for something that's solved in two. Each extra step adds latency and a new point of failure. Always start with the minimum number of steps and add only if the result justifies it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passing all context to each call
&lt;/h3&gt;

&lt;p&gt;The most expensive mistake. &lt;strong&gt;Tokens&lt;/strong&gt; are the units that models use to measure text (sort of like word fragments). LLM APIs charge per token: both for what you send and what you receive. If in step 3 you include the complete history from steps 1 and 2, that cost multiplies by the number of steps. Pass only the clean data that step needs. The inverse tradeoff also exists: cutting too much can weaken the result of the next step. Not the entire history, but what's necessary for that step to have enough signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calls without error handling
&lt;/h3&gt;

&lt;p&gt;The mistake I saw repeated most often, especially at the beginning: a pipeline without gates where step 1 fails silently and subsequent steps receive incorrect data. The system fails in cascade, you don't know at which point the error occurred, and the user receives a generic message with no context. Gates aren't an optimization: they're what makes the system usable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unvalidated user input
&lt;/h3&gt;

&lt;p&gt;If the pipeline processes text that comes from the user (a review, a form, any free field), that text gets interpolated directly into the prompt. A user can inject instructions within the content and alter the model's behavior. In production, validate and limit input before using it in a prompt: maximum length, allowed characters, whatever makes sense for your case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using prompt chaining for atomic tasks
&lt;/h3&gt;

&lt;p&gt;"Translate this word to English" doesn't need a pipeline. If you find yourself adding steps to a task that's fundamentally simple, step back and ask yourself if the real problem is in the prompt, not the architecture. Complexity has a cost: more code, more points of failure, more latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;[ ] Each step of the pipeline has a single clear responsibility&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] There's a validation gate between each pair of steps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] The gate implements early exit with an error message that helps debug&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Each step receives only the context it needs, not the complete history&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] The number of steps is the minimum necessary for the task&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Results from each step are logged to facilitate debugging&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What's the difference between prompt chaining and an AI agent?
&lt;/h3&gt;

&lt;p&gt;An agent decides for itself what steps to take, in what order, and when to stop. Prompt chaining is a fixed sequence that you define in advance. If you know exactly what steps you need, use prompt chaining: it's much more predictable and easier to debug when something fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need a framework like LangChain to build a pipeline?
&lt;/h3&gt;

&lt;p&gt;No. The example in this post doesn't use any framework. For pipelines of two or four steps, adding a framework adds unnecessary dependencies and layers of abstraction. A couple of functions in TypeScript do exactly the same thing with much less complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if the model in step 1 generates an incorrect format?
&lt;/h3&gt;

&lt;p&gt;That's what the gate is for. Check the format before continuing and if the output doesn't pass validation, the pipeline stops and returns a clear error. Without a gate, that incorrect format propagates and afterward it's almost impossible to trace the origin of the failure.&lt;/p&gt;

&lt;p&gt;If your step 1 returns JSON, the most direct gate is &lt;code&gt;try { JSON.parse(output) } catch { return { error: "Invalid format" } }&lt;/code&gt;. If you expect an enumerated value ("positive" / "negative" / "neutral"), a regex is enough: &lt;code&gt;/^(positive|negative|neutral)$/i.test(output)&lt;/code&gt;. Catching the failure here, before step 2, is the difference between a clear error and 40 minutes of debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the model in step 2 remember what step 1 did?
&lt;/h3&gt;

&lt;p&gt;No, unless you explicitly pass that information to it. Each call to the LLM starts from zero. There's no memory between calls. If you need step 2 to know something from step 1, you have to pass it yourself in the prompt. It's one of the things that confuses people most at first, and it's also why the design of what information passes between steps matters so much.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many steps is too many?
&lt;/h3&gt;

&lt;p&gt;In practice, more than four or five steps for a single task usually indicates you're over-dividing the problem. Ask yourself if you can merge some steps without losing control over the intermediate results. If the answer is yes, merge them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://aicodingpatterns.com/en/patterns/prompt-chaining/" rel="noopener noreferrer"&gt;AI Coding Patterns&lt;/a&gt; — visual, interactive courses to learn programming with AI. Explore the &lt;a href="https://aicodingpatterns.com/en/" rel="noopener noreferrer"&gt;courses&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Guardrails for AI Agents: How to Implement Them (With Code)</title>
      <dc:creator>AI Coding Patterns</dc:creator>
      <pubDate>Tue, 21 Jul 2026 14:10:33 +0000</pubDate>
      <link>https://dev.to/aicodingpatterns/guardrails-for-ai-agents-how-to-implement-them-with-code-2o3h</link>
      <guid>https://dev.to/aicodingpatterns/guardrails-for-ai-agents-how-to-implement-them-with-code-2o3h</guid>
      <description>&lt;p&gt;Imagine asking an AI assistant: "delete the project's temporary files." The assistant thinks it knows which ones they are, but it's wrong... and deletes an important file (&lt;code&gt;.env.local&lt;/code&gt;) with configuration data you need. The data is lost.&lt;/p&gt;

&lt;p&gt;Why did it happen? Because the assistant did exactly what it understood from your order, without thinking about whether it was safe to do so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guardrails&lt;/strong&gt; are safety boundaries that prevent this from happening. They're like fencing off a dangerous zone: the assistant keeps working, but can't enter areas where it might cause harm.&lt;/p&gt;

&lt;p&gt;Want to understand &lt;strong&gt;what a guardrail is and why you need one&lt;/strong&gt; first, with analogies and no code? Start with the &lt;a href="https://aicodingpatterns.com/en/patterns/que-es-un-guardarrail-en-ia/" rel="noopener noreferrer"&gt;conceptual guide&lt;/a&gt;. Here we go straight to implementing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you start
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is an AI agent?&lt;/strong&gt; It's a program that uses artificial intelligence (like ChatGPT) to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receive your instruction&lt;/li&gt;
&lt;li&gt;Decide what to do&lt;/li&gt;
&lt;li&gt;Execute actions (delete a file, send an email, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The code examples are in TypeScript, but you can follow along even if you're not a heavy programmer—I'll explain them in simple terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a guardrail
&lt;/h2&gt;

&lt;p&gt;Think of a fenced-in playground. The fence doesn't decide where kids go or how they play. It just prevents them from running off toward the road.&lt;/p&gt;

&lt;p&gt;An AI guardrail is basically a boundary you define in advance. The assistant stays intelligent and makes decisions, but there are certain actions it &lt;strong&gt;cannot do&lt;/strong&gt;, no matter what you ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"You can't delete configuration files"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"You can't access the customer database"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"You can't transfer money from the account"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fguardarrailes-agentes-ia-como-implementarlos%2Fdiagrams%2Frequest-lifecycle-guardrails.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fguardarrailes-agentes-ia-como-implementarlos%2Fdiagrams%2Frequest-lifecycle-guardrails.svg" title="Guardrails are applied at three distinct points in the agent execution cycle." alt="1.00" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are three places where you can put guardrails:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Before (input):&lt;/strong&gt; You review what the user asks before passing it to the assistant.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: If someone writes "delete everything," the system blocks it before the assistant tries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. During (execution):&lt;/strong&gt; Limits on the actions the assistant can execute.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: The assistant can read files, but when it tries to delete one, the system checks: "Is this file in the allowed folder? Isn't it a protected file?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. After (output):&lt;/strong&gt; You review what the assistant returns before using it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: If the assistant generates a command to run, you verify the command is safe before executing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why agents without guardrails fail
&lt;/h2&gt;

&lt;p&gt;The problem isn't that AI is bad. The problem is that it does exactly what it understands from your orders, without questioning whether it's safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; You tell it "make the application faster" and the assistant deletes the database because it thinks it's slow. Technically it obeyed your order. But the result is disastrous.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three common problems:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Irreversible actions without confirmation&lt;/strong&gt;&lt;br&gt;
The assistant executes dangerous orders immediately (delete a file, change settings) without asking for confirmation. It's like a worker who executes every order without checking if it's safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Sharing information that shouldn't be shared&lt;/strong&gt;&lt;br&gt;
The assistant has access to sensitive information (passwords, customer data) and shares it in its response, even though it shouldn't. It's not malice—it just uses all the information it has to answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Infinite loops&lt;/strong&gt;&lt;br&gt;
The assistant detects an error, tries to fix it, that generates another error, tries again... and enters an infinite cycle that doesn't stop on its own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The root reason:&lt;/strong&gt; Without guardrails, the assistant doesn't know what's allowed and what isn't in your specific situation.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to implement them in practice
&lt;/h2&gt;

&lt;p&gt;There are four levels of protection, from simplest to strongest. Start with the first ones—you don't need all of them from the beginning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fguardarrailes-agentes-ia-como-implementarlos%2Fdiagrams%2Ffour-levels-robustness.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fguardarrailes-agentes-ia-como-implementarlos%2Fdiagrams%2Ffour-levels-robustness.svg" title="The four levels aren't mutually exclusive: each one covers the blind spots of the previous one." alt="1.00" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Level 1: The rulebook 📋
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt; It's the initial instruction you give the agent. Like a manual that says "this yes, that no." It goes at the beginning of the system prompt and sets expectations from the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world example:&lt;/strong&gt; It's like telling a worker: "you can read the documents, but never touch the safe." It's the golden rule that guides all their decisions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;systemPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
You are a code assistant.

✅ I CAN:
- Read files
- Suggest improvements
- Explain errors

❌ I CAN NEVER:
- Delete files
- View .env files
- Touch the database
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent uses these instructions to interpret each request it receives. If someone says "delete everything," the agent should reject it because it knows it can't delete files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro:&lt;/strong&gt; Fast to implement. With this you block almost all common accidents. It's the agent's psychological filter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con:&lt;/strong&gt; A persistent user might try to get you to ignore these rules. The agent is trained to be obedient, and with the right words it might try to follow orders that contradict the manual. That's why the other levels exist.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 2: The safety filter 🛡️
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt; Before the agent receives the user's message, your code checks: "Does this seem safe?" This filter runs between the user and the agent, analyzing dangerous text patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world example:&lt;/strong&gt; It's like having a guard at the door checking if someone tries to enter with a weapon. If someone says a dangerous keyword, they never enter the building.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isSecure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dangers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sr"&gt;/delete.*database/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sr"&gt;/drop.*production/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sr"&gt;/DELETE FROM/i&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;danger&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;dangers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;danger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// blocked here, agent never sees it&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&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;p&gt;The advantage is that the agent never processes dangerous messages. If the message is blocked here, the AI model never tries to process it or justify why it should do it anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customization options:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can also implement a &lt;strong&gt;lightweight classification model&lt;/strong&gt; to evaluate messages before they reach the main agent. Small, fast models can be used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intent classification:&lt;/strong&gt; Determine if the request is asking for an allowed action&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety scoring:&lt;/strong&gt; Assign a risk level (low, medium, high) to each message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content filtering:&lt;/strong&gt; Detect sensitive topics or patterns more accurately than regex patterns
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;classifyMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;safe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;riskLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-3-5-haiku-20241022&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Fast, small model&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are a security classifier. Analyze if a message is safe for an AI agent to process.
    Respond with JSON: {"safe": boolean, "riskLevel": "low|medium|high", "reason": "brief explanation"}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&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="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&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="na"&gt;safe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;riskLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Could not classify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use it before sending to the main agent&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;classifyMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;safe&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;riskLevel&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Send to main agent&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mainAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`❌ Blocked: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;p&gt;This approach is more accurate than pattern matching but slightly slower. Choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pattern-based filtering&lt;/strong&gt; (regex) for speed and simplicity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model-based classification&lt;/strong&gt; (lightweight AI model) for accuracy and nuance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro:&lt;/strong&gt; The agent never sees malicious messages. It can't try to interpret them weirdly because the input never reaches it. Model-based classification catches sophisticated attempts to bypass simple pattern rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con:&lt;/strong&gt; It's a list of patterns (if pattern-based). There's always someone who finds a new way to write the same thing without triggering any pattern (for example, "remove production data" instead of "delete production"). Model-based classification adds latency and cost, though using a small, fast model minimizes both.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 3: Limits on each tool 🔒
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt; Every action the agent can take has its own guardrail in the code. The agent asks for something, and before executing it, we verify if it's allowed. It's function-level protection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world example:&lt;/strong&gt; It's like having a waiter who can serve water, but the bottle system only allows water, not alcohol. Even if the waiter asks for something from the bar, the machine only gives water.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deleteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Is it in the allowed folder?&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/tmp/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ I can only delete in /tmp/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Is it a special file we don't touch?&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ This file is protected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// If it passed both checks, ok&lt;/span&gt;
  &lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;✅ File deleted&lt;/span&gt;&lt;span class="dl"&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;p&gt;This level is the most robust because the limits are in the code, not in the agent's interpretation. Even if the agent tries to bypass the rules, the code itself prevents it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro:&lt;/strong&gt; The agent can try whatever it wants; the code won't allow it. It's very hard to circumvent because it doesn't depend on words or patterns, but on pure logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con:&lt;/strong&gt; You need to write this code for each important action. It's more work, but it's the one that works best in practice.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 4: Output review 👀
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt; Before using the response or commands the agent generates, your code reviews them. If the agent generates a dangerous SQL command, you block it before executing it. It's the final filter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world example:&lt;/strong&gt; It's like an editor reviewing a document before publishing it: "this paragraph doesn't get published." Or a security director validating each action before it happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isSQLSafe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DROP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TRUNCATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// blocked before executing&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Before executing:&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isSQLSafe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agentSQL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agentSQL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ This command is not safe&lt;/span&gt;&lt;span class="dl"&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;p&gt;This level is especially useful when the agent generates code or commands that will be executed. Even if the agent passed all previous filters, this is the last one checking that what's about to happen is really safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro:&lt;/strong&gt; You're the final filter. Even if everything else fails, this catches it. It's especially important if the agent generates SQL commands, executable code, or actions that affect real systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con:&lt;/strong&gt; If you're generating a lot of content to review, the user waits longer. Also, it requires extra effort to analyze each output before executing it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Quick summary:&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;Level&lt;/th&gt;
&lt;th&gt;Think of it as&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Security&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1️⃣ Manual&lt;/td&gt;
&lt;td&gt;A sign that says "don't touch"&lt;/td&gt;
&lt;td&gt;Very fast&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2️⃣ Filter&lt;/td&gt;
&lt;td&gt;A guard at the door&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3️⃣ Tools&lt;/td&gt;
&lt;td&gt;A technician who checks each tool&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4️⃣ Output&lt;/td&gt;
&lt;td&gt;A final editor&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;How many do you need?&lt;/strong&gt; Start with the first two. If the agent does dangerous things (delete, send emails), add the 3rd. If the result is used to execute code, add the 4th.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Trusting only the system prompt
&lt;/h3&gt;

&lt;p&gt;The system prompt is the starting point, not the complete system. If the agent has tools that can delete data, instructions saying "don't delete anything" aren't enough. Code-level limits don't depend on model interpretation and are harder to bypass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guardrails that block too much
&lt;/h3&gt;

&lt;p&gt;An agent that rejects almost every request because filters are too aggressive is useless. The goal isn't to make the agent useless: it's to make it predictable. Start with few guardrails and add only those that address problems you've actually seen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not logging rejections
&lt;/h3&gt;

&lt;p&gt;When a guardrail blocks something, keep a log. That record tells you what the agent (or user) tried to do, how often it happens, and whether your guardrail is well-calibrated or being too restrictive. Without logs, you're flying blind. When logging rejections though, avoid saving the complete user message if it might contain sensitive data. Save only the pattern that blocked it and the timestamp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guardrails only on the client
&lt;/h3&gt;

&lt;p&gt;If your agent calls an API or executes code on the server, guardrails need to be on the server too. A client-only guardrail can be bypassed by directly calling the endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation checklist
&lt;/h2&gt;

&lt;p&gt;For infinite correction loops, attempt limit is the simplest thing that works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attempt limit to prevent infinite correction loops&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_RETRIES&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_RETRIES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;successful&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Agent didn't complete the task in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MAX_RETRIES&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; attempts`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;[ ] The system prompt explicitly lists what the agent can and cannot do&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] There's input validation before sending requests to the model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Each tool with destructive effects (delete, modify, send) has its own guardrail in its implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Guardrail rejections are logged&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Critical validations are on the server, not just the client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] There's an attempt limit to prevent infinite correction loops&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do guardrails slow down the agent?
&lt;/h3&gt;

&lt;p&gt;The ones in the system prompt and input validation have almost no performance impact: they're local checks that execute in microseconds. What can add latency is using a second model to classify intentions or validate outputs. To start, stick with pure code validations.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if a user tries to bypass guardrails with an elaborate instruction?
&lt;/h3&gt;

&lt;p&gt;It's possible. Text pattern-based guardrails have blind spots. For systems where this is critical, the most robust approach is combining tool-level guardrails (hardest to bypass) with human review before executing irreversible actions. Without that second level, there will always be edge cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need guardrails if the agent only answers questions and doesn't execute actions?
&lt;/h3&gt;

&lt;p&gt;The risk is lower, yes. But output validation is still useful to prevent the agent from including in its responses data it shouldn't share: fragments of configuration files it has in context, for example.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many guardrails are enough?
&lt;/h3&gt;

&lt;p&gt;One irreversible action, one guardrail. An agent that only reads and responds needs few. An agent that writes to a database, sends emails, or modifies files needs guardrails on each of those actions. Start with actions that can't be undone.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://aicodingpatterns.com/en/patterns/guardarrailes-agentes-ia-como-implementarlos/" rel="noopener noreferrer"&gt;AI Coding Patterns&lt;/a&gt; — visual, interactive courses to learn programming with AI. Explore the &lt;a href="https://aicodingpatterns.com/en/" rel="noopener noreferrer"&gt;courses&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>GoF Patterns in AI Agents: The Complete Map</title>
      <dc:creator>AI Coding Patterns</dc:creator>
      <pubDate>Fri, 10 Jul 2026 14:12:06 +0000</pubDate>
      <link>https://dev.to/aicodingpatterns/gof-patterns-in-ai-agents-the-complete-map-1g80</link>
      <guid>https://dev.to/aicodingpatterns/gof-patterns-in-ai-agents-the-complete-map-1g80</guid>
      <description>&lt;p&gt;GoF patterns have existed for thirty years: Factory, Observer, Command, Singleton. They are proven ways to organize code.&lt;/p&gt;

&lt;p&gt;In AI agents, these patterns reappear with new names and a clearer purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before you continue&lt;/strong&gt;: this article is technical, but you don't need to be an expert. It's helpful to know some basic concepts, but we'll explain it step by step with easy-to-understand examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  GoF Patterns in Thirty Seconds
&lt;/h2&gt;

&lt;p&gt;In 1994, a very famous book came out with 23 solutions to problems every programmer faces. They're not lines of code, but &lt;strong&gt;proven ways to organize your program&lt;/strong&gt; so it's easier to change and understand.&lt;/p&gt;

&lt;p&gt;Imagine they're like construction blueprints: instead of inventing how to build each house, you use a blueprint that already worked.&lt;/p&gt;

&lt;p&gt;Patterns are divided into groups by what they solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creational&lt;/strong&gt;: how to create things (like telling a machine to fabricate an object)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structural&lt;/strong&gt;: how to connect things together (like assembling pieces)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavioral&lt;/strong&gt;: who does what and in what order (how actions are coordinated)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enterprise&lt;/strong&gt;: how to organize very large systems&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;strong&gt;AI agent systems&lt;/strong&gt; (machines that think and act on their own), almost all these patterns reappear with new names. The following table shows how old patterns serve modern agents. Don't worry if you don't understand the full table now—we'll explain the most important ones step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Complete Map
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Classic Pattern&lt;/th&gt;
&lt;th&gt;Family&lt;/th&gt;
&lt;th&gt;Agentic Equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Factory&lt;/td&gt;
&lt;td&gt;Creational&lt;/td&gt;
&lt;td&gt;Creates the right subagent based on task type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Builder&lt;/td&gt;
&lt;td&gt;Creational&lt;/td&gt;
&lt;td&gt;Incrementally builds agent context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prototype&lt;/td&gt;
&lt;td&gt;Creational&lt;/td&gt;
&lt;td&gt;Reusable and cloneable prompt templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Singleton&lt;/td&gt;
&lt;td&gt;Creational&lt;/td&gt;
&lt;td&gt;Centralized tool registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adapter&lt;/td&gt;
&lt;td&gt;Structural&lt;/td&gt;
&lt;td&gt;MCP: adapts any API to the format the model expects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decorator&lt;/td&gt;
&lt;td&gt;Structural&lt;/td&gt;
&lt;td&gt;Guardrails: wrap the agent without touching its logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxy&lt;/td&gt;
&lt;td&gt;Structural&lt;/td&gt;
&lt;td&gt;Model router: redirects by cost or capacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composite&lt;/td&gt;
&lt;td&gt;Structural&lt;/td&gt;
&lt;td&gt;Agent-of-agents: one agent coordinating other agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command&lt;/td&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Tool call: encapsulated action the model can invoke&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observer&lt;/td&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Hooks: react to agent events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strategy&lt;/td&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Model selection based on task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mediator&lt;/td&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Orchestrator: coordinates agents without direct communication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chain of Responsibility&lt;/td&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Pipeline of chained agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Template Method&lt;/td&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;System prompt: defines expected response structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repository&lt;/td&gt;
&lt;td&gt;PoEAA&lt;/td&gt;
&lt;td&gt;RAG: abstracts external knowledge retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DTO&lt;/td&gt;
&lt;td&gt;PoEAA&lt;/td&gt;
&lt;td&gt;Structured outputs: schema-defined objects between agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service Layer&lt;/td&gt;
&lt;td&gt;PoEAA&lt;/td&gt;
&lt;td&gt;Layer of orchestrator agents with clear responsibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saga&lt;/td&gt;
&lt;td&gt;EIP&lt;/td&gt;
&lt;td&gt;Long-running agentic transactions with compensation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pub-Sub&lt;/td&gt;
&lt;td&gt;EIP&lt;/td&gt;
&lt;td&gt;Agents reacting to async events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scatter-Gather&lt;/td&gt;
&lt;td&gt;EIP&lt;/td&gt;
&lt;td&gt;Multi-agent debate and best-answer synthesis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Circuit Breaker&lt;/td&gt;
&lt;td&gt;Resilience&lt;/td&gt;
&lt;td&gt;Maximum iteration limit in the tool loop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bulkhead&lt;/td&gt;
&lt;td&gt;Resilience&lt;/td&gt;
&lt;td&gt;Budget and context isolation per agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fallback&lt;/td&gt;
&lt;td&gt;Resilience&lt;/td&gt;
&lt;td&gt;Chain of alternative models if primary fails&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table gives you the map. The following sections explain the patterns that appear most in early real-world agentic systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creational Patterns: How an Agent is Born
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Factory&lt;/strong&gt; is like a worker who picks the right specialist for each task.&lt;/p&gt;

&lt;p&gt;If you need code written, call the programming expert. If you need to search the web, call the search expert. If you need to analyze a document, call the analysis expert. Factory automatically picks the right specialist without you having to tell it manually which one to use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Factory: returns the correct agent based on task type&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document-analysis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DocumentAnalysisAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-4-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extractText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;summarizeContent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are an expert in analyzing complex documents...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code-generation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CodeGenerationAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-4-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;runTests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;linter&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a senior software engineer...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;web-research&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResearchAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-haiku-4-5-20251001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;webSearch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchArticle&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a researcher gathering up-to-date information...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unsupported agent type: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;taskType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="c1"&gt;// Usage: the system automatically picks the best agent for the task&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document-analysis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agent&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="nx"&gt;newTask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Builder&lt;/strong&gt; is useful when you need to prepare an agent step by step, like putting together a puzzle.&lt;/p&gt;

&lt;p&gt;First you give it basic instructions ("you're an analysis expert"). Then you add the history of previous conversations. Then the documents it needs. Instead of giving it everything at once, you do it in steps, and each step is a piece that fits into place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prototype&lt;/strong&gt; is when you have a model or template you reuse.&lt;/p&gt;

&lt;p&gt;For example: you have a "prompt" (instruction) that works well for analyzing code. Instead of writing new instructions for each project, you copy this template and adapt it slightly for each case. It's like having a form you fill with different data, but the structure is always the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Singleton&lt;/strong&gt; solves a specific problem: the tool registry. A single point from which the system knows all available tools. Each tool registers once; agents invoke it by name. Without this centralized registry, you end up with tools defined in multiple places with mismatched schemas. Small, but it fixes an error that appears early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structural Patterns: How Everything Connects
&lt;/h2&gt;

&lt;p&gt;Imagine your AI agent is like a person in an office. These four patterns are the "infrastructures" that make everything work together:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adapter&lt;/strong&gt;: it's like a translator between languages&lt;/p&gt;

&lt;p&gt;Suppose your agent needs to use different external tools: Google, a database, a private API from your company. The problem is each one "speaks" in a different format. Adapter is a translator that converts each format to one your agent understands. That way, your agent doesn't need to learn 10 different languages. The translator handles the conversion automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decorator&lt;/strong&gt;: it's like a bodyguard who reviews your actions (without getting into your head)&lt;/p&gt;

&lt;p&gt;Your agent wants to execute an action: delete files, change a setting, send money. Before it does, you wrap it with a control layer that checks: "Are you sure you want to do this?" or "Does this action follow safety rules?" The agent doesn't know there's a bodyguard reviewing. It keeps thinking normally. The Decorator just acts as an external filter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proxy&lt;/strong&gt;: it's like an intelligent receptionist who routes requests&lt;/p&gt;

&lt;p&gt;When someone enters the office, the receptionist decides: "This simple question goes to a Junior. This complex question goes to the Senior." Proxy is like that: it receives the request, evaluates how complicated it is, and routes to the right model (Haiku for simple tasks, Opus for complex tasks). Your code stays the same; the receptionist makes the decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Composite&lt;/strong&gt;: it's like a project director who coordinates specialists&lt;/p&gt;

&lt;p&gt;Imagine your main agent is a director who doesn't do all the work alone. It's smarter: it has specialists under its command (an analysis agent, another for search, another for writing). From the outside, it looks like one person is working on the project. Inside, it's a coordinated team. The director (main agent) decides who does what, but the effort is collective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fpatrones-gof-patrones-agenticos-mapeo-completo%2Fdiagrams%2Fpatrones-estructurales-sistema-agente.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Fpatrones-gof-patrones-agenticos-mapeo-completo%2Fdiagrams%2Fpatrones-estructurales-sistema-agente.svg" title="The four key structural patterns in an agentic system: Adapter translates APIs to model format, Decorator adds guardrails without touching the agent, Proxy routes by cost/capacity, and Composite coordinates subagents from the orchestrator." alt="1.00" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Behavioral Patterns: How the Agent Acts
&lt;/h2&gt;

&lt;p&gt;Imagine your AI agent is like an assistant that needs to do things. These patterns explain how that assistant works, what actions it can take, and how all those actions are coordinated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command&lt;/strong&gt; is like giving a to-do list written on a note&lt;/p&gt;

&lt;p&gt;Your agent has a list of things it can do: search the web, write a document, analyze an image, etc. Each task is written clearly on a note with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it's called (for example: "search the web")&lt;/li&gt;
&lt;li&gt;What it does (for example: "find up-to-date information")&lt;/li&gt;
&lt;li&gt;What information it needs (for example: "text to search")&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the agent needs to do something, you give it a note with that specific task. The agent reads the note, understands what it needs to do, and executes it. You control which tasks are available in the list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observer&lt;/strong&gt; is like having alarms that go off at specific moments&lt;/p&gt;

&lt;p&gt;Imagine you have alarms that go off when certain things happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An alarm that goes off when the agent finishes a search&lt;/li&gt;
&lt;li&gt;An alarm that goes off when the agent starts writing&lt;/li&gt;
&lt;li&gt;An alarm that goes off when it finishes completely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When each alarm goes off, you execute an action (for example: save the result, send a notification, update a database). The agent doesn't know there are alarms. It just does its work, and the alarms respond to what it does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strategy&lt;/strong&gt; is like having different paths to the same destination&lt;/p&gt;

&lt;p&gt;You have several ways to solve a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask model A (fast but less accurate)&lt;/li&gt;
&lt;li&gt;Ask model B (slow but more exact)&lt;/li&gt;
&lt;li&gt;Ask model C (very precise but very expensive)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the situation, you pick a path: if the task is urgent and not important, use the fast model. If you need precision, use the exact model. The agent's logic stays the same; you only change which model it uses based on what you need at that moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mediator&lt;/strong&gt; is like having an orchestra conductor&lt;/p&gt;

&lt;p&gt;Imagine you have several specialists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One searches for information&lt;/li&gt;
&lt;li&gt;Another analyzes documents&lt;/li&gt;
&lt;li&gt;Another writes reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without a conductor, each specialist would need to know how to communicate with the others, who needs what information, etc. It's chaos.&lt;/p&gt;

&lt;p&gt;With a conductor (Mediator), everyone talks only to the conductor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The searcher says: "I found this information"&lt;/li&gt;
&lt;li&gt;The conductor receives it and sends it to the analyst&lt;/li&gt;
&lt;li&gt;The analyst says: "I've analyzed this"&lt;/li&gt;
&lt;li&gt;The conductor sends it to the writer&lt;/li&gt;
&lt;li&gt;The writer delivers the final report&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The conductor is the only one who knows how all the parts work. The specialists only need to know the conductor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enterprise Patterns: PoEAA and EIP
&lt;/h2&gt;

&lt;p&gt;They're ways to organize large, complex systems. We'll explain with simple examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt;: it's like a "gateway to data"&lt;/p&gt;

&lt;p&gt;Your agent needs to search for information. Instead of the agent knowing where the data is (Is it in a database? In files? On the internet?), there's a single gateway: ask for the information and someone finds it wherever it is. &lt;a href="https://aicodingpatterns.com/en/patterns/rag-empresarial-completo/" rel="noopener noreferrer"&gt;RAG (pattern for agents to access external knowledge)&lt;/a&gt; works like this: your agent just asks, without caring where the answer comes from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DTO&lt;/strong&gt; (sending structured information): it's like an envelope with clearly defined fields&lt;/p&gt;

&lt;p&gt;When two agents need to communicate, they don't send loose text. They send an "envelope" with clear structure: this is a name, this is a number, this is a date. Less confusion, fewer errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scatter-Gather&lt;/strong&gt;: ask several at once and gather the answers&lt;/p&gt;

&lt;p&gt;You have a difficult problem. Instead of asking one model (who might be wrong), you ask three models in parallel. They all solve the same problem from their perspectives. Then you gather the answers and reach the best conclusion. It's like asking advice from several friends instead of one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saga&lt;/strong&gt;: it's a plan with "Plan B" if something goes wrong&lt;/p&gt;

&lt;p&gt;Your agent needs to do five steps in sequence (step 1, step 2, step 3, step 4, step 5). If step 4 fails, what happens to steps 1, 2, and 3? Saga is a plan that says: if it fails here, undo this; if it fails there, undo that. That way the system keeps working without getting stuck halfway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resilience: When the Agent Fails or Gets Stuck
&lt;/h2&gt;

&lt;p&gt;Imagine your agent is like a person working on a task. Sometimes it gets stuck: it keeps trying the same thing over and over without making progress, wasting time and money without results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circuit Breaker&lt;/strong&gt;: it's like an emergency button&lt;/p&gt;

&lt;p&gt;The agent tries to do something up to 10 times (or whatever number you set). If after those 10 attempts it can't succeed, the system stops. Without this limit, the stuck agent would keep trying forever, wasting your money on tokens without ever finishing the task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Emergency button: stop if it tries more than 10 times&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;attemptsAttempted&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;stopNow&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;p&gt;&lt;strong&gt;Bulkhead&lt;/strong&gt;: it's like giving each agent its own budget&lt;/p&gt;

&lt;p&gt;If you have several agents working at once, each gets its budget limit (tokens). If one goes overboard and uses up its limit, the others keep working with their budget. One doesn't ruin everyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fallback chains&lt;/strong&gt;: it's like having a Plan B&lt;/p&gt;

&lt;p&gt;If the agent tries the Claude model (the most powerful but expensive) and fails, it automatically tries the Sonnet model (cheaper). If that also fails, it tries Haiku (the fastest). The system always has an alternative option.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Has No Classic Equivalent
&lt;/h2&gt;

&lt;p&gt;These are genuinely new agentic patterns. They're not in GoF, not in Fowler, not in Hohpe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context engineering&lt;/strong&gt;: actively managing what information enters the &lt;a href="https://aicodingpatterns.com/en/patterns/ventana-contexto-buenas-practicas/" rel="noopener noreferrer"&gt;context window (the memory space the model has during a conversation)&lt;/a&gt; at each moment. It's not caching or lazy loading. It's an explicit decision about what the model knows and doesn't know, made step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eval harness&lt;/strong&gt;: infrastructure to measure whether the agent works well. Classic testing doesn't apply because model outputs are probabilistic, not deterministic. An eval harness defines test cases, runs the agent multiple times, and aggregates metrics to detect degradation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM-as-Judge&lt;/strong&gt;: &lt;a href="https://aicodingpatterns.com/en/patterns/modelo-como-juez/" rel="noopener noreferrer"&gt;use one model to evaluate the quality of another model's response&lt;/a&gt;. There's no classic equivalent because in traditional software tests are binary. Here the "judge" reasons about quality, coherence, or semantic correctness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandbox execution&lt;/strong&gt;: run code generated by the agent in an isolated environment before it touches production. The agent writes. The sandbox verifies. Only if it passes does it deploy. Without this pattern, every agent run is a gamble.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost/latency-aware routing&lt;/strong&gt;: route requests to different models not just by capability, but with explicit constraints on cost and latency. Strategy solves the "how to choose". This pattern adds "how much can you spend and how long can you wait" as first-class citizens in the decision.&lt;/p&gt;

&lt;p&gt;The difference between these five and GoF patterns is they require reasoning about uncertainty. GoF assumes code does what you tell it to. Agentic patterns assume the model can surprise you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes When Mapping These Patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Confusing Decorator with Proxy
&lt;/h3&gt;

&lt;p&gt;They're structurally similar, but the intent is different. Decorator adds behavior to the agent's output (verify, filter, enrich). Proxy controls access to the agent or model (redirect, limit, authenticate). If you're checking output, it's Decorator. If you're redirecting requests, it's Proxy. Mixing them leads to guardrails that do too much, or routers that also validate, and neither can change without breaking the other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applying Factory When You Only Have One Agent Type
&lt;/h3&gt;

&lt;p&gt;Factory makes sense when you have two or more variants with different logic. If you only have one agent with one configuration, Factory is pure over-engineering. Start with a direct function. Add Factory when the second agent type actually appears.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ignoring Circuit Breaker Until the Problem Happens
&lt;/h3&gt;

&lt;p&gt;I've seen this in early agentic projects I worked on in production: the tool loop gets stuck in a loop, the agent keeps calling the same tool expecting a different result, and token spending multiplies without anyone noticing until the bill arrives. The iteration limit isn't an optimization. It's the first line of defense.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Saga Without Defining Compensations First
&lt;/h3&gt;

&lt;p&gt;Saga without compensations is just a sequence of steps that doesn't know how to recover if something fails. Before implementing Saga, write on paper what the system does if step 3 of 5 fails. If you can't answer that question, you're not ready for Saga yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;[ ] Subagents are created with Factory based on task type, not scattered conditional logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Each tool call is modeled as a Command object with explicit schema and clear description&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Guardrails are implemented as Decorator, external to agent logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] The orchestrator centralizes communication between agents (Mediator), agents don't call each other&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] The tool loop has a Circuit Breaker with iteration limit defined before production deployment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] RAG abstracts access to external knowledge (Repository), the agent doesn't know the data source&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Outputs between agents use structured outputs with typed schema (DTO)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] The system has at least a basic eval harness before deployment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[ ] Tools that execute user code run in an isolated sandbox before touching production&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I need to know GoF patterns to start with agents?
&lt;/h3&gt;

&lt;p&gt;No. You can build functional agents without having read the 1994 book. But if you already know them, this map gives you an advantage: instead of learning agentic concepts from scratch, you recognize familiar structures with new roles. You already know how to use Factory. That it now creates subagents instead of business objects is a small step.&lt;/p&gt;

&lt;h3&gt;
  
  
  What pattern should I learn first if I'm starting from zero?
&lt;/h3&gt;

&lt;p&gt;Command=tool call. It's the most fundamental of all. If you don't understand that each tool you give the model is a Command object with name, description, and schema, the rest of the patterns have no solid foundation. Everything else builds on that concept.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between Decorator and Proxy in an agentic system?
&lt;/h3&gt;

&lt;p&gt;Decorator adds behavior: the guardrails that verify or filter agent output. Proxy controls access: the router that decides which model to send the request to. The code structure is almost identical, but the intent is different. In practice: if you're modifying or checking output, it's Decorator. If you're redirecting requests, it's Proxy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the Singleton pattern serve any purpose in agents?
&lt;/h3&gt;

&lt;p&gt;Yes, for the tool registry: a centralized registry of all available tools, accessible from anywhere in the system. Each tool registers once. Agents invoke it by name. Without this registry, you end up with tools defined in multiple places with inconsistent schemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are resilience patterns (Circuit Breaker, Bulkhead) for advanced systems?
&lt;/h3&gt;

&lt;p&gt;Circuit Breaker is not. It's the first you should implement, before even any orchestration pattern. An agent without an iteration limit is one that can cost you money unpredictably. Bulkhead is more relevant when you have multiple agents running in parallel and need one's failure not to affect the others.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://aicodingpatterns.com/en/patterns/patrones-gof-patrones-agenticos-mapeo-completo/" rel="noopener noreferrer"&gt;AI Coding Patterns&lt;/a&gt; — visual, interactive courses to learn programming with AI. Explore the &lt;a href="https://aicodingpatterns.com/en/" rel="noopener noreferrer"&gt;courses&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Loop engineering: the loop is the product, not the code</title>
      <dc:creator>AI Coding Patterns</dc:creator>
      <pubDate>Fri, 10 Jul 2026 14:12:03 +0000</pubDate>
      <link>https://dev.to/aicodingpatterns/loop-engineering-the-loop-is-the-product-not-the-code-107l</link>
      <guid>https://dev.to/aicodingpatterns/loop-engineering-the-loop-is-the-product-not-the-code-107l</guid>
      <description>&lt;p&gt;For years my job was writing the code. Now I describe a goal, and an agent writes it, runs the tests, reads the error, and tries again. The real work has moved up one level: I no longer write the code — I design the loop in which the agent writes it. I call this loop engineering. And the idea that organizes everything else is uncomfortably simple: the loop is the product, not the code.&lt;/p&gt;

&lt;p&gt;If you've already built an agent with Claude Code or your own orchestrator, this will ring a bell. It works, but you iterate by gut feel. You tweak a prompt, run it, see if the result looks better, repeat. The quality leap almost never comes from a smarter prompt. It comes from designing a better loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is "the loop," exactly?
&lt;/h2&gt;

&lt;p&gt;The loop is the cycle an agent repeats until it finishes a task: it receives context, decides on an action, observes the result, compares it against what you wanted, and decides whether to try again or stop. It's the classic perception-decision-action of agents, with one addition that almost everyone skips: the explicit comparison against an objective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Floop-engineering%2Fdiagrams%2Fbucle-agente.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Floop-engineering%2Fdiagrams%2Fbucle-agente.svg" title="Anatomy of the agentic loop: the five pieces of each iteration" alt="Agentic loop cycle: context receives the objective and state, the agent chooses an action/tool, the observation returns the real-world result, feedback measures whether this iteration is better than the previous one, and the stopping condition decides whether the loop continues or exits to the final product" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Five pieces make up each iteration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt; is everything the model can see at that moment: the objective, the code state, the error from the previous iteration, the available tools. What's not in the context doesn't exist for the agent, so managing it well is half the battle. If you've never thought of context as a scarce resource, start with &lt;a href="https://aicodingpatterns.com/patterns/ventana-contexto-buenas-practicas/" rel="noopener noreferrer"&gt;context window best practices&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;action&lt;/strong&gt; is the tool the model chooses and executes: writing a file, running a test, querying the database. That's tool calling.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;observation&lt;/strong&gt; is the result the system feeds back into the context after executing the action. An important detail: the model reads the observation, it doesn't invent it. It's produced by the real world (the test runner, the compiler, the API), which is why the observation is the only part of the loop that the agent cannot fabricate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feedback&lt;/strong&gt; is the signal that says whether this iteration is going better or worse than the previous one. Observing is not the same as knowing whether you're making progress. A failing test is an observation; that the failure count is one fewer than the previous iteration is feedback.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;stopping condition&lt;/strong&gt; decides when the loop halts: objective achieved, budget exhausted, or lack of progress.&lt;/p&gt;

&lt;p&gt;If you want the full breakdown, you'll find it in &lt;a href="https://aicodingpatterns.com/patterns/que-es-bucle-agentico/" rel="noopener noreferrer"&gt;what exactly is an agentic loop&lt;/a&gt; and in &lt;a href="https://aicodingpatterns.com/patterns/ciclo-agente-ia-explicado/" rel="noopener noreferrer"&gt;the AI agent cycle explained step by step&lt;/a&gt;. What I'm interested in here is what happens when you scale that simple cycle: does this loop live inside a single task, or does it govern the entire system?&lt;/p&gt;

&lt;h2&gt;
  
  
  Inner loop and outer loop: two loops, two jobs
&lt;/h2&gt;

&lt;p&gt;In an agentic system, two loops are operating at the same time, and confusing them is the primary source of poor design. The inner loop is the short cycle within a task. The agent generates a piece of code, runs the test, sees it fail, and corrects itself — all within the same reasoning session. It's the try-and-fix that Claude Code runs on every turn without you doing anything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Floop-engineering%2Fdiagrams%2Finner-outer-loop.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faicodingpatterns.com%2Fen%2Fpatterns%2Floop-engineering%2Fdiagrams%2Finner-outer-loop.svg" title="Inner loop vs outer loop: the short correction cycle within the long system cycle" alt="Two concentric rings: the inner loop (write code → run tests, short correction cycle within the session) nested inside the outer loop (orchestrator → measure progress → strategy adjustment, long cycle between runs)" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The outer loop is the long cycle. It's the system that launches that inner loop over and over: it gives it work, reviews the result, decides what comes next, and starts again — without you typing each prompt. This is where improvement between runs lives, the part that turns an agent that solves a task into an agent that solves tasks increasingly well.&lt;/p&gt;

&lt;p&gt;The distinction isn't academic — it changes where you optimize. Improving the inner loop means faster, more readable feedback within the session: tests that run in seconds, errors the model can understand. Improving the outer loop is about orchestration, budget, and memory between runs. And there's a rule you learn the hard way: when the inner loop gets stuck, the outer loop must rethink the entire strategy, not repeat the same step hoping for a different result. &lt;a href="https://aicodingpatterns.com/patterns/feedback-loop-agentes-ia/" rel="noopener noreferrer"&gt;Feedback loops in AI agents&lt;/a&gt; deserve their own article, because they're the mechanism that connects the two.&lt;/p&gt;

&lt;p&gt;Both loops share one requirement. Without a good feedback signal, neither converges. It doesn't matter how elegant your orchestration is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes a loop converge
&lt;/h2&gt;

&lt;p&gt;A loop converges when each iteration brings it closer to the objective, and that only happens if it has a feedback signal that distinguishes between better and worse. There are two ways to get that signal, and choosing well between them is a significant part of the design.&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;deterministic feedback&lt;/strong&gt;: tests, linters, type-checkers, gates. Pass or fail. It's cheap, unambiguous, and non-negotiable. A red test is a red test, and the agent can't argue with it. When the problem can be reduced to a checkable rule, this is always the best signal. &lt;a href="https://aicodingpatterns.com/patterns/buenas-practicas-proyectos-mantenibles/" rel="noopener noreferrer"&gt;Claude Code hooks for deterministic quality&lt;/a&gt; are exactly this: walls the loop cannot jump over. And if the agent is writing code, &lt;a href="https://aicodingpatterns.com/patterns/ai-writes-code-fast-but-breaks-things-testing-strategy/" rel="noopener noreferrer"&gt;the testing strategy when AI codes fast&lt;/a&gt; is what gives the loop a reliable signal.&lt;/p&gt;

&lt;p&gt;The second is &lt;strong&gt;model judgment&lt;/strong&gt;: one LLM evaluates what another produces. It covers what no test captures — things like "is this response clear?" or "does this text sound natural?" It's more expensive and noisier, but it covers the territory that deterministic verification can't reach. The pattern is in &lt;a href="https://aicodingpatterns.com/patterns/modelo-como-juez/" rel="noopener noreferrer"&gt;a model as judge&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Deterministic feedback&lt;/th&gt;
&lt;th&gt;Model judgment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What it measures&lt;/td&gt;
&lt;td&gt;Anything reducible to a rule: compiles, passes the test, matches the type&lt;/td&gt;
&lt;td&gt;Qualitative aspects: clarity, tone, whether the solution makes sense&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost per iteration&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High: it's another model call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;High and repeatable&lt;/td&gt;
&lt;td&gt;Variable; needs calibration to avoid scoring everything the same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When to use it&lt;/td&gt;
&lt;td&gt;Whenever the problem allows it&lt;/td&gt;
&lt;td&gt;Only for what can't be reduced to a rule&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The practical rule is to prefer deterministic feedback whenever you can and reserve model judgment for what genuinely cannot be turned into a rule. A loop with ambiguous feedback doesn't converge — it spins because the signal doesn't tell it which direction to go. Designing that signal is such a big topic that I dedicate an entire article to it: &lt;a href="https://aicodingpatterns.com/patterns/como-evaluar-agentes-ia-produccion/" rel="noopener noreferrer"&gt;how to evaluate AI agents in production&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A reliable signal tells you which direction to go. It doesn't tell you when to stop. And that's a different problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a loop doesn't terminate
&lt;/h2&gt;

&lt;p&gt;A loop without an explicit stopping condition doesn't terminate: it keeps repeating the same state or burns through its budget until someone kills it. Unchecked autonomy isn't autonomy — it's a runaway.&lt;/p&gt;

&lt;p&gt;Every loop needs a budget (a maximum number of iterations or tokens) and a definition of "done" that the loop itself can verify. But the most insidious failure is different: the lack of no-progress detection. If two consecutive iterations produce the same diff or the same error, the agent isn't advancing — it's stuck. Retrying the same thing expecting a different result isn't iterating. When that happens, the right move is to reframe or escalate, not take another identical turn. The extreme case, &lt;a href="https://aicodingpatterns.com/patterns/agente-ia-bucle-infinito/" rel="noopener noreferrer"&gt;an AI agent stuck in an infinite loop&lt;/a&gt;, is almost always exactly this, without a brake.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// El bucle para por objetivo cumplido, presupuesto agotado o falta de progreso&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runLoop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agente&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objetivo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Objetivo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Budget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;estado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;estadoInicial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objetivo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;vuelta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;vuelta&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxVueltas&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;vuelta&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agente&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decidir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;estado&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observacion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ejecutar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;señal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;verificar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observacion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objetivo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// tests, lint o juez&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;señal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cumplido&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;observacion&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sinProgreso&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;estado&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;observacion&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mismo diff/error: atascado&lt;/span&gt;
    &lt;span class="nx"&gt;estado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;actualizar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;estado&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;observacion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;señal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;);&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;escalarAHumano&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;estado&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// el bucle no decide solo cuándo rendirse&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The guardrails that prevent a loop from going off the rails have their own name and their own design: &lt;a href="https://aicodingpatterns.com/patterns/guardarrailes-agentes-ia-como-implementarlos/" rel="noopener noreferrer"&gt;guardrails for AI agents&lt;/a&gt;. Setting a limit is the easy part. The hard part is that each iteration has a cost, and deciding how many iterations are worth it is part of the design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cost of each iteration
&lt;/h2&gt;

&lt;p&gt;Each loop iteration costs tokens, latency, money, and the risk of breaking something that was already working — so designing the loop also means deciding how many iterations are worth it. A loop that iterates twenty times to fix a typo is worse than one that stops at three and hands it back to you. More iterations don't mean a better result. Past a certain point, a loop with no new signal just burns budget.&lt;/p&gt;

&lt;p&gt;The tradeoff shows up in every decision. Richer feedback per iteration — like running the full test suite — costs more per iteration but tends to converge in fewer iterations. Cheap feedback, like running only the linter, is fast but may need many more. And there's a cost that grows on its own: context accumulates with each iteration, more history means more tokens per call, and past a certain size the model starts losing track of what you originally asked for.&lt;/p&gt;

&lt;p&gt;The iteration budget is a business decision disguised as a technical parameter. And like any costly decision, it shouldn't be made by the agent alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the human belongs in the loop
&lt;/h2&gt;

&lt;p&gt;The human shouldn't be on every iteration of the loop, but at the costly, irreversible decision points. Reviewing every iteration turns the agent into a slow and expensive autocomplete: you lose the advantage of automation and keep doing the tedious work by hand.&lt;/p&gt;

&lt;p&gt;Your place is where mistakes are expensive to undo: approving a hypothesis before spending to implement it, or authorizing a merge to &lt;code&gt;main&lt;/code&gt; that the agent can't revert without consequences. The best example I know of this done right is the &lt;a href="https://aicodingpatterns.com/patterns/experiment-driven-optimization/" rel="noopener noreferrer"&gt;how I make my agents improve themselves&lt;/a&gt; methodology, where the only human intervention point is approving each hypothesis before it's implemented. Everything else runs on its own.&lt;/p&gt;

&lt;p&gt;That pattern — human at the hypothesis, machine at the iteration — has a name when you take it to the extreme.&lt;/p&gt;

&lt;h2&gt;
  
  
  A loop that improves itself
&lt;/h2&gt;

&lt;p&gt;The outer loop taken to the extreme is a loop that doesn't just solve the task — it improves the way it solves it. Instead of iterating over the code, you iterate over the system that writes the code.&lt;/p&gt;

&lt;p&gt;The complete case study is the &lt;a href="https://aicodingpatterns.com/patterns/experiment-driven-optimization/" rel="noopener noreferrer"&gt;experiment-driven optimization&lt;/a&gt; methodology: measure against a frozen baseline, propose a hypothesis, implement it, validate whether the number improves, and document the experiment even when you discard it. Each run doesn't just produce a result — it produces information about how to produce better results. That's the ceiling of loop engineering: the system optimizes itself, and you only approve hypotheses.&lt;/p&gt;



&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Iterating because "it looks better"
&lt;/h3&gt;

&lt;p&gt;Without a signal that compares against the previous iteration, "looks better" is an opinion, and opinions don't converge. A number or a test that says why this iteration beats the previous one is the only way to know whether you're actually iterating.&lt;/p&gt;

&lt;h3&gt;
  
  
  The runaway loop
&lt;/h3&gt;

&lt;p&gt;A loop without a budget or no-progress detection is a runaway waiting to happen. Set an iteration limit before you add anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  The human reviewing every iteration
&lt;/h3&gt;

&lt;p&gt;If you approve every step, you haven't automated anything — you've just added latency to your own work. Save your attention for decisions that are expensive to undo and let the loop run on everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confusing more iterations with higher quality
&lt;/h3&gt;

&lt;p&gt;Past a certain point, each additional iteration without a new signal only adds cost and the risk that the agent breaks something that was already working. A loop that converges in a few iterations and stops is better than one that takes twenty and keeps going.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feedback that doesn't discriminate
&lt;/h3&gt;

&lt;p&gt;The most subtle of all. A judge that scores everything a 7, or a test suite that always passes, gives the illusion of a signal without actually being one. Before trusting your feedback mechanism, verify that it genuinely separates good output from bad. If it can't tell the difference, the loop is blind even when it appears to see — and no number of iterations will fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist for designing your loop
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Each iteration has a feedback signal that says whether it's going better or worse than the previous one&lt;/li&gt;
&lt;li&gt;[ ] The signal is deterministic (tests, lint, type-check) whenever the problem allows it, and model judgment is reserved for what can't be reduced to a rule&lt;/li&gt;
&lt;li&gt;[ ] The loop has an explicit stopping condition, with at least two exits beyond "objective achieved": budget exhausted and no-progress detected&lt;/li&gt;
&lt;li&gt;[ ] There is an iteration budget (maximum iterations or tokens) defined before launching&lt;/li&gt;
&lt;li&gt;[ ] The human only intervenes on costly or irreversible decisions, not on every iteration&lt;/li&gt;
&lt;li&gt;[ ] When the loop gets stuck, it escalates or reframes instead of repeating the same step&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is loop engineering the same as prompt engineering?
&lt;/h3&gt;

&lt;p&gt;No: prompt engineering fine-tunes a single model call; loop engineering designs the complete cycle surrounding it, including what context goes in, how the output is verified, and when it stops.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between inner loop and outer loop?
&lt;/h3&gt;

&lt;p&gt;The inner loop is the short cycle of testing and correcting within a single task — like when an agent writes code, runs the test, and corrects itself in the same session. The outer loop is the long cycle that launches that task many times, reviews the result, and decides what comes next — and it's where the system improves between runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many iterations are too many?
&lt;/h3&gt;

&lt;p&gt;It depends on the cost of each iteration and the value of getting it right, but the alarm bell isn't the number — it's the lack of progress. If two consecutive iterations produce the same result or the same error, you've over-iterated even if you're only on iteration three. Set a maximum budget as a safety net and no-progress detection for the normal case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does loop engineering apply to any agent?
&lt;/h3&gt;

&lt;p&gt;It applies to any agent whose task has a quality metric you can calculate, even if that metric requires a model as a judge. The problem appears with tasks that have no definable metric: "write an email that convinces this client" has no test and no clear success criterion — and without a way to say whether one draft beats another, the loop has nothing to hold on to. That's usually the first piece of work before automating anything: turning "make it good" into something you can measure.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://aicodingpatterns.com/en/patterns/loop-engineering/" rel="noopener noreferrer"&gt;AI Coding Patterns&lt;/a&gt; — visual, interactive courses to learn programming with AI. Explore the &lt;a href="https://aicodingpatterns.com/en/" rel="noopener noreferrer"&gt;courses&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Create a Claude Project: Step-by-Step Guide (2026)</title>
      <dc:creator>AI Coding Patterns</dc:creator>
      <pubDate>Sun, 05 Jul 2026 19:17:03 +0000</pubDate>
      <link>https://dev.to/aicodingpatterns/how-to-create-a-claude-project-step-by-step-guide-2026-4ni6</link>
      <guid>https://dev.to/aicodingpatterns/how-to-create-a-claude-project-step-by-step-guide-2026-4ni6</guid>
      <description>&lt;p&gt;Every time you open a new chat with Claude, it starts from scratch. It doesn't know you're a developer. It doesn't know what company you work for or what tone you prefer. You have to explain the context each time, and when you do it in every conversation, you end up writing the same introductory paragraph over and over.&lt;/p&gt;

&lt;p&gt;Claude Projects solve that problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All you need to follow this post is an account on claude.ai&lt;/strong&gt;—free or paid. No coding knowledge required.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Project in Claude?
&lt;/h2&gt;

&lt;p&gt;Before the technical definition, here's an analogy: imagine you have a fixed desk in an office. On that desk you have your notes pinned up, the documents for the project you're working on, and your tools organized. When you come back the next day, everything is still where you left it.&lt;/p&gt;

&lt;p&gt;A normal chat with Claude is like a shared desk that someone cleans every time you leave. A Project is your fixed desk.&lt;/p&gt;

&lt;p&gt;A Project has three parts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom instructions&lt;/strong&gt;: a text you write once that Claude reads at the start of each conversation in the project. It tells Claude who you are, what context you work in, what format you prefer, and any restrictions that matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Knowledge files&lt;/strong&gt;: documents you upload to the project (PDFs, Markdown, code, plain text) that Claude can consult automatically when relevant. No need to paste them into the chat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conversation history&lt;/strong&gt;: conversations you have in the project are saved and you can refer back to them anytime. But what Claude automatically loads at the start of each new conversation are the instructions and files; content from previous chats doesn't load.&lt;/p&gt;

&lt;p&gt;Projects are available to all Claude users, including the free plan. With the free account you can create up to five projects and use the Sonnet model. Paid plans (Pro, Max, Team, Enterprise) add access to the more powerful Opus model and advanced support for large volumes of documents in the knowledge section.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Find Projects in Claude.ai
&lt;/h2&gt;

&lt;p&gt;On &lt;a href="https://claude.ai" rel="noopener noreferrer"&gt;claude.ai&lt;/a&gt;, Projects appear in the left sidebar below your recent conversations. You'll see a &lt;strong&gt;"+ New Project"&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;When you click it, it asks for a project name. Give it a descriptive one: "Work — Your Company Name" or "Learning React" work much better than "My Project".&lt;/p&gt;

&lt;p&gt;Once inside the project, the interface has two main areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project header&lt;/strong&gt;: at the top of the screen you'll see the name you gave it. Just below is an &lt;strong&gt;"Edit project"&lt;/strong&gt; button. That button opens a side panel with two fields: one for the name and one for custom instructions. The instructions field is a free text box with no visible length limit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Project Knowledge" tab&lt;/strong&gt;: it's at the top of the central area, next to the conversations tab. From there you can drag files or use the upload button. Each uploaded file appears listed with its name, and you can delete or replace it anytime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;New conversations you create in the project automatically inherit the instructions and have access to the files. You don't need to do anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Instructions: What Actually Works
&lt;/h2&gt;

&lt;p&gt;Most people using custom instructions write things like "always respond in English" or "be concise". That's fine. But it's just the surface layer.&lt;/p&gt;

&lt;p&gt;The real value is giving Claude the context it would need to help you well from the first message, without you having to explain it every time.&lt;/p&gt;

&lt;p&gt;Four useful questions for writing your instructions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What should Claude know about me or my company to respond well?&lt;/li&gt;
&lt;li&gt;What response format saves me time?&lt;/li&gt;
&lt;li&gt;What constraints or preferences matter here?&lt;/li&gt;
&lt;li&gt;What should Claude not do in this context?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below you'll find three complete examples you can copy and adapt.&lt;/p&gt;

&lt;h3&gt;
  
  
  For someone learning to code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm a student in the final module of a web development bootcamp.
I work with React, TypeScript, and Node.js. My level is beginner.

When you explain code to me:
- Use comments in the code itself to explain each important part
- If there's a simpler way to do what I'm asking, tell me even if I didn't ask for it
- Avoid advanced concepts (decorators, complex generics) until I mention them first

When you review my code:
- Prioritize errors that would cause production bugs over style issues
- Explain why something is wrong, not just how to fix it

Always in English.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For someone doing content marketing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I work as a content marketer for a SaaS company that makes project management tools for small businesses.
Our customers are operations directors and CEOs of companies with 10-50 people.
Our company tone is professional but approachable, never corporate.

For written content:
- Short paragraphs, maximum three sentences
- No marketing jargon: nothing like "synergies", "added value", or "end-to-end solutions"
- Headlines that speak to the reader's problem, not our features

When you review my writing, tell me first if the main message is clear
before getting into writing details.

Language: American English.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For someone launching their own startup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm the founder of a startup in validation phase in the logistics sector.
I'm building the MVP alone, with no technical team yet.

Important context:
- Very limited budget, I prioritize free or cheap solutions
- I'm not technical, so explain the technical implications of decisions in simple terms
- My priority now is validating the product quickly, not building something scalable

When you suggest tools, always note whether they have a free plan.
When we talk about technology, explain trade-offs in terms of cost
and development speed, not architecture.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Cases by Profile
&lt;/h2&gt;

&lt;p&gt;So you can recognize yourself in one, here's a quick reference by professional profile:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Profile&lt;/th&gt;
&lt;th&gt;What Goes in Instructions&lt;/th&gt;
&lt;th&gt;What Files to Upload&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Developer&lt;/td&gt;
&lt;td&gt;Tech stack, level, code format preferences&lt;/td&gt;
&lt;td&gt;API documentation, project specifications you're building, team style guide&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Marketer&lt;/td&gt;
&lt;td&gt;Company, brand tone, target audience&lt;/td&gt;
&lt;td&gt;Campaign briefs, brand voice guides, approved templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consultant&lt;/td&gt;
&lt;td&gt;Specialization, working methodology, current client&lt;/td&gt;
&lt;td&gt;Meeting notes, previous proposals, industry context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entrepreneur&lt;/td&gt;
&lt;td&gt;Startup stage, budget constraints, priorities&lt;/td&gt;
&lt;td&gt;Summary business plan, user feedback, list of assumptions to validate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Student&lt;/td&gt;
&lt;td&gt;Area of study, level, how you prefer concepts explained&lt;/td&gt;
&lt;td&gt;Your own notes, exercise descriptions, course materials&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Same Question, Two Very Different Answers
&lt;/h2&gt;

&lt;p&gt;To show you the contrast in practice, here's the same message in two contexts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The message:&lt;/strong&gt; "Can you review this email before I send it to clients?"&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;In a generic chat, no project:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sure, paste the email and I'll review it. Do you want me to focus on tone, grammar, or structure?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude knows nothing about the context. It asks for clarification before starting. Reasonable, but slow. And next time it will ask the same thing.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;In a project configured with the marketer profile's instructions from above, with the client brief uploaded as a file:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've reviewed the email. The main message doesn't appear until the third paragraph—the reader should understand what you're offering in the first sentence.&lt;/p&gt;

&lt;p&gt;The subject line "October Updates" won't generate much open rate. Something like "How [Company X] Cut Their Check-in Meetings in Half" connects better with the problem you describe in the body.&lt;/p&gt;

&lt;p&gt;The tone is good, approachable without losing professionalism. One adjustment: the closing "we hope we can help" sounds passive. "Email us if you want to try it this week" is more direct and has a clear call to action.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The difference isn't that Claude is smarter in one case than the other. It's that it has the context it needs to give you specific feedback without you having to write it every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge Files: What to Upload
&lt;/h2&gt;

&lt;p&gt;Files are useful when you have documents Claude would need to consult in many different conversations. Some concrete examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your app's design document or a project's specifications&lt;/li&gt;
&lt;li&gt;A client brief: their company, their products, their audience&lt;/li&gt;
&lt;li&gt;Your own decision notes and things you've already ruled out&lt;/li&gt;
&lt;li&gt;Documentation for an obscure library or tool that Claude usually gets wrong&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What doesn't work as well: scanned PDFs (they're images, not text), documents with very complex tables, or files that change constantly. For information that changes, it's better to write it directly in the project instructions or update the file when it changes.&lt;/p&gt;

&lt;p&gt;Before uploading a document, consider whether it contains sensitive client data or confidential company information that shouldn't leave your internal systems. Claude.ai is an external service, and what you upload there leaves your systems.&lt;/p&gt;

&lt;p&gt;Claude doesn't read all files in every response. It reads the ones that are relevant to what you're asking at that moment. If you upload a client brief but ask something about code, it won't read the brief unless it's related.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aicodingpatterns.com/en/patterns/ventana-contexto-buenas-practicas/" rel="noopener noreferrer"&gt;context window&lt;/a&gt; explains why: Claude can only process a certain amount of information at a time. Files are designed to be retrieved when needed, not all loaded together.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Organize Your Projects
&lt;/h2&gt;

&lt;p&gt;A common mistake is creating one giant project for everything. The problem is that contexts mix and instructions become vague trying to cover everything.&lt;/p&gt;

&lt;p&gt;An organization that works well: one project per coherent, stable context. Work at your current company, learning something specific, a particular client. The sign you need a new project is when you find yourself writing the same introductory context at the start of a chat over and over.&lt;/p&gt;

&lt;p&gt;With the free plan you get up to five projects. For most use cases, that's more than enough if you define them well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Instructions that try to cover everything
&lt;/h3&gt;

&lt;p&gt;Three-page instructions that anticipate every possible situation. The result is Claude gets lost in the details and ends up ignoring parts. Better twenty well-chosen lines than two hundred that contradict each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Poorly prepared files
&lt;/h3&gt;

&lt;p&gt;The filename matters: &lt;code&gt;brief-client-acme-2024.md&lt;/code&gt; is easier to reference than &lt;code&gt;document_final_v3.pdf&lt;/code&gt;. And format matters most: plain text and Markdown are read with much more accuracy than scanned PDFs or documents with complex tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  A project that's too generic
&lt;/h3&gt;

&lt;p&gt;A project called "General" with instructions like "be helpful and respond well" adds nothing over normal chat. A Project has value when the context it contains is specific and stable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Files that never get updated
&lt;/h3&gt;

&lt;p&gt;You upload a client brief in January and in April it's still there with data from the previous launch. Claude doesn't know that document is outdated: it responds with what it has. The same criteria you apply to instructions apply to files: when reality changes, the file needs to change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing instructions once and forgetting them
&lt;/h3&gt;

&lt;p&gt;Instructions aren't forever. A concrete example: I started a consulting project with instructions that mentioned a specific client as a tone reference. Three months later that client no longer existed and the instructions still pointed to them. Claude kept adjusting the tone to a context that no longer existed, and it took several weird conversations before I noticed the problem.&lt;/p&gt;

&lt;p&gt;If you change roles, if you start with a new client, if you learn that Claude does something you don't want in that context, update the instructions. They're a living document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your First Project in Less Than 10 Minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://claude.ai" rel="noopener noreferrer"&gt;claude.ai&lt;/a&gt; and click &lt;strong&gt;"+ New Project"&lt;/strong&gt; in the left sidebar.&lt;/li&gt;
&lt;li&gt;Give it a name that describes the context: "Work — [Your Company]" or "Learning [Technology]".&lt;/li&gt;
&lt;li&gt;Enter the newly created project. At the top you'll see the project name and just below it the &lt;strong&gt;"Edit project"&lt;/strong&gt; button: click it to open the custom instructions field.&lt;/li&gt;
&lt;li&gt;Write your instructions using one of the examples above as a starting point. Don't try to make them perfect now.&lt;/li&gt;
&lt;li&gt;If you have a relevant document (a brief, specifications, your notes), upload it from the "Project Knowledge" tab.&lt;/li&gt;
&lt;li&gt;Create your first conversation inside the project and ask a real question you'd normally ask.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Instructions and files are already saved. The next conversation starts with that context loaded from the beginning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] The project has a name that describes the context, not a generic one&lt;/li&gt;
&lt;li&gt;[ ] Instructions include who you are and what context you work in&lt;/li&gt;
&lt;li&gt;[ ] Instructions specify the response format you prefer&lt;/li&gt;
&lt;li&gt;[ ] Instructions indicate what Claude shouldn't do in that context&lt;/li&gt;
&lt;li&gt;[ ] If you uploaded files, they're in text format (not scanned PDFs)&lt;/li&gt;
&lt;li&gt;[ ] You've done at least one test conversation to verify Claude uses the context&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How many projects can I have?
&lt;/h3&gt;

&lt;p&gt;With the free plan, up to five. With paid plans you can create unlimited projects. For how to organize the ones you have, the organization section above has the logic that works.&lt;/p&gt;

&lt;h3&gt;
  
  
  What file types does Claude accept in projects?
&lt;/h3&gt;

&lt;p&gt;Plain text (.txt), Markdown (.md), PDF, Word (.docx), spreadsheets (.csv), and code files (JavaScript, Python, TypeScript, among others). PDFs work well when they're digitized text. Scanned PDFs, which are really images, aren't read with the same accuracy. The free plan has a total file size limit per project; if you work with very large document corpora, that expanded capacity is only on paid plans.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a project's context affect my normal chats outside it?
&lt;/h3&gt;

&lt;p&gt;No. A project's instructions, files, and history are only active inside that project. A new conversation you open outside any project starts from scratch with no access to any project's context.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I know if Claude is using the instructions I gave it properly?
&lt;/h3&gt;

&lt;p&gt;Ask a question where the instructions should change the response. If in your instructions you asked "always give me a two-sentence summary first" and Claude doesn't do it, something needs adjusting, either in the instructions' wording or in length (too long and it might ignore parts). You can also ask directly: "What instructions do you have for this project?" and it will tell you what it has read.&lt;/p&gt;

&lt;p&gt;With files the behavior is different. Claude only retrieves them when it considers them relevant to the specific question. If you upload a document and it seems like it's not using it, check two things: that the name is descriptive (&lt;code&gt;client-acme-brief.md&lt;/code&gt; works better than &lt;code&gt;v3_final.pdf&lt;/code&gt;) and that the format is text, not an image. Then ask the question by explicitly mentioning the document: "Based on the client brief I uploaded, what tone would be appropriate for this email?" That detail tells it exactly where to look.&lt;/p&gt;




&lt;p&gt;If you've made it this far, you have everything you need to set up your first project today. Choose the context where you use Claude the most, write ten lines of instructions using the examples above as a starting point, and test it. You'll see the contrast with generic chat in the first response.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://aicodingpatterns.com/en/patterns/proyectos-claude-guia-practica/" rel="noopener noreferrer"&gt;AI Coding Patterns&lt;/a&gt; — visual, interactive courses to learn programming with AI. Explore the &lt;a href="https://aicodingpatterns.com/en/" rel="noopener noreferrer"&gt;courses&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
