<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Avarile's Coding Hub]]></title><description><![CDATA[Programming AI Tech and Fucking Awesome]]></description><link>https://blog.avarile.com/</link><image><url>https://blog.avarile.com/favicon.png</url><title>Avarile&apos;s Coding Hub</title><link>https://blog.avarile.com/</link></image><generator>Ghost 5.79</generator><lastBuildDate>Wed, 06 May 2026 11:29:26 GMT</lastBuildDate><atom:link href="https://blog.avarile.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[New video recording]]></title><description><![CDATA[<figure class="kg-card kg-video-card kg-width-full" data-kg-thumbnail="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-13-10-34-06_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-13-10-34-06.mp4" poster="https://img.spacergif.org/v1/2560x1600/0a/spacer.png" width="2560" height="1600" loop autoplay muted playsinline preload="metadata" style="background: transparent url(&apos;https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-13-10-34-06_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">1:43</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure>]]></description><link>https://blog.avarile.com/new-video-recording/</link><guid isPermaLink="false">69dc3c327f99e80001ba24e1</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Mon, 13 Apr 2026 00:44:04 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-video-card kg-width-full" data-kg-thumbnail="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-13-10-34-06_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-13-10-34-06.mp4" poster="https://img.spacergif.org/v1/2560x1600/0a/spacer.png" width="2560" height="1600" loop autoplay muted playsinline preload="metadata" style="background: transparent url(&apos;https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-13-10-34-06_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">1:43</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure>]]></content:encoded></item><item><title><![CDATA[A newly designed UI]]></title><description><![CDATA[<figure class="kg-card kg-video-card kg-width-wide" data-kg-thumbnail="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-08-11-37-31_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-08-11-37-31.mp4" poster="https://img.spacergif.org/v1/2560x1600/0a/spacer.png" width="2560" height="1600" loop autoplay muted playsinline preload="metadata" style="background: transparent url(&apos;https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-08-11-37-31_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:46</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure>]]></description><link>https://blog.avarile.com/a-newly-designed-ui/</link><guid isPermaLink="false">69d5b2507f99e80001ba24d4</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Wed, 08 Apr 2026 01:41:51 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-video-card kg-width-wide" data-kg-thumbnail="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-08-11-37-31_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-08-11-37-31.mp4" poster="https://img.spacergif.org/v1/2560x1600/0a/spacer.png" width="2560" height="1600" loop autoplay muted playsinline preload="metadata" style="background: transparent url(&apos;https://blog.avarile.com/content/media/2026/04/Screencast-From-2026-04-08-11-37-31_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:46</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure>]]></content:encoded></item><item><title><![CDATA[Agents Platform is Just a Temporary, Transitional Existence]]></title><description><![CDATA[<p></p><h2 id="the-discipline-thats-revealing-why-most-ai-agent-platforms-will-disappear-by-2027">The discipline that&apos;s revealing why most AI agent platforms will disappear by 2027</h2><h3 id="tldrthe-bottom-line">TL;DR - The Bottom Line</h3><p><strong>Agent platforms are building on quicksand.</strong>&#xA0;While the AI agents market explodes from $5.4 billion in 2024 to a projected $50.31 billion by 2030, foundational LLM</p>]]></description><link>https://blog.avarile.com/agents-platform-is-just-a-temporary-transitional-existence/</link><guid isPermaLink="false">6886a3d8f0886e0001e0f01c</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Sun, 27 Jul 2025 22:11:10 GMT</pubDate><content:encoded><![CDATA[<p></p><h2 id="the-discipline-thats-revealing-why-most-ai-agent-platforms-will-disappear-by-2027">The discipline that&apos;s revealing why most AI agent platforms will disappear by 2027</h2><h3 id="tldrthe-bottom-line">TL;DR - The Bottom Line</h3><p><strong>Agent platforms are building on quicksand.</strong>&#xA0;While the AI agents market explodes from $5.4 billion in 2024 to a projected $50.31 billion by 2030, foundational LLM providers (OpenAI, Anthropic, Google) are systematically absorbing the functionality that makes specialized platforms valuable. The platforms that survive won&apos;t be those with the best AI&#x2014;they&apos;ll be those that own irreplaceable business data and processes.</p><p><strong>Key takeaway:</strong>&#xA0;The difference between a temporary demo platform and a defensible business is the switching cost created by deep data integration, not AI capability.</p><hr><h2 id="the-evolution-why-agent-platform-consolidation-is-inevitable">The Evolution: Why Agent Platform Consolidation is Inevitable</h2><h3 id="from-wrappers-to-acquisitions">From Wrappers to Acquisitions</h3><p>The numbers tell a stark story of ongoing consolidation:</p><ul><li><strong>ServiceNow acquired Moveworks</strong>&#xA0;for close to $3 billion (March 2025)</li><li><strong>Google orchestrated a $2.7 billion reverse acquihire</strong>&#xA0;with Character.AI (August 2024)</li><li><strong>Salesforce acquired Convergence.ai</strong>&#xA0;to strengthen Agentforce (May 2025)</li><li><strong>AI agent companies led M&amp;A activity</strong>&#xA0;in Q1 2025, securing the 3 largest deals among 85 acquisitions</li></ul><p><strong>The AI landscape has fundamentally shifted:</strong></p><ul><li><strong>2023:</strong>&#xA0;Specialized agent platforms carve out niches (Platform Building Era)</li><li><strong>2024:</strong>&#xA0;Foundational providers begin vertical integration</li><li><strong>2025:</strong>&#xA0;Most platform failures are not AI failures anymore&#x2014;they are&#xA0;<strong>moat failures</strong></li></ul><h3 id="the-critical-business-reality">The Critical Business Reality</h3><p><strong>Market Transformation:</strong>&#xA0;Organizations building agent platforms are seeing survival rates drop from promising early adoption to brutal consolidation as foundational providers expand their capabilities.</p><p><strong>Resource Efficiency:</strong>&#xA0;Studies show that foundational providers can:</p><ul><li>Replicate specialized platform features in 6-12 months</li><li>Offer direct model access without API overhead</li><li>Leverage existing user bases for instant distribution</li><li>Undercut pricing through vertical integration</li></ul><p><strong>Strategic Positioning:</strong>&#xA0;The question shifts from &quot;How do we build better agents?&quot; to &quot;How do we become irreplaceable to our users&apos; business operations?&quot;</p><hr><h2 id="what-makes-agent-platforms-vulnerable">What Makes Agent Platforms Vulnerable?</h2><h3 id="the-core-dependency-problem">The Core Dependency Problem</h3><p><strong>Agent platforms &#x2260; Defensible businesses</strong></p><p><strong>Traditional View:</strong>&#xA0;Platform = AI capabilities + user interface&#xA0;<strong>Reality:</strong>&#xA0;Platform = Everything users depend on for critical business functions</p><h3 id="the-complete-vulnerability-assessment">The Complete Vulnerability Assessment</h3><p>Most current agent platforms are built on five foundational weaknesses:</p><h4 id="1-model-dependency">1.&#xA0;<strong>Model Dependency</strong></h4><ul><li><strong>Platform Reality:</strong>&#xA0;&quot;Choose the brain behind your agent. Use OpenAI, Claude, Gemini, and more&quot;</li><li><strong>Strategic Problem:</strong>&#xA0;Core value proposition controlled by others</li><li><strong>Example:</strong>&#xA0;Khoj explicitly states it can &quot;chat with any local or online LLM (e.g llama3, qwen, gemma, mistral, gpt, claude, gemini, deepseek)&quot;&#x2014;highlighting their fundamental dependency</li></ul><h4 id="2-feature-replication-risk">2.&#xA0;<strong>Feature Replication Risk</strong></h4><ul><li><strong>Current Capabilities:</strong>&#xA0;Workflow automation, knowledge retrieval, conversational interfaces</li><li><strong>Provider Response:</strong>&#xA0;OpenAI&apos;s Codex for developers, Anthropic&apos;s computer-use agents, Google&apos;s Workspace integration</li><li><strong>Time to Replication:</strong>&#xA0;6-18 months for most specialized features</li></ul><h4 id="3-distribution-disadvantage">3.&#xA0;<strong>Distribution Disadvantage</strong></h4><ul><li><strong>Platform Reach:</strong>&#xA0;Thousands to millions of users</li><li><strong>Provider Reach:</strong>&#xA0;Hundreds of millions (ChatGPT: 200M+ weekly active users)</li><li><strong>Integration Advantage:</strong>&#xA0;Microsoft 365 Copilot already used by 70% of Fortune 500 companies</li></ul><h4 id="4-cost-structure-vulnerability">4.&#xA0;<strong>Cost Structure Vulnerability</strong></h4><ul><li><strong>Platform Economics:</strong>&#xA0;Pay API costs + infrastructure + development</li><li><strong>Provider Economics:</strong>&#xA0;Direct model access + existing infrastructure + amortized R&amp;D</li><li><strong>Inevitable Outcome:</strong>&#xA0;Foundational providers can always undercut pricing</li></ul><h4 id="5-innovation-lag">5.&#xA0;<strong>Innovation Lag</strong></h4><ul><li><strong>Platform Development:</strong>&#xA0;Months to integrate new model capabilities</li><li><strong>Provider Development:</strong>&#xA0;Instant access to cutting-edge features</li><li><strong>Market Impact:</strong>&#xA0;Users migrate to latest capabilities regardless of platform loyalty</li></ul><hr><h2 id="agent-platforms-vs-foundational-providers-the-decisive-comparison">Agent Platforms vs. Foundational Providers: The Decisive Comparison</h2>
<!--kg-card-begin: html-->
<table style="font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-align: start; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);"><thead><tr><th>Aspect</th><th>Current Agent Platforms</th><th>Foundational Providers</th></tr></thead><tbody><tr><td><strong>AI Capabilities</strong></td><td>Dependent on APIs</td><td>Direct model control</td></tr><tr><td><strong>Cost Structure</strong></td><td>API fees + markup</td><td>Direct compute costs</td></tr><tr><td><strong>Feature Velocity</strong></td><td>Months to integrate</td><td>Real-time deployment</td></tr><tr><td><strong>User Base</strong></td><td>Platform-specific</td><td>Cross-platform reach</td></tr><tr><td><strong>Data Access</strong></td><td>User-provided only</td><td>Training + user data</td></tr><tr><td><strong>Integration</strong></td><td>Third-party APIs</td><td>Native ecosystems</td></tr><tr><td><strong>Defensibility</strong></td><td>Interface convenience</td><td>Foundational technology</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="beyond-features-the-next-competitive-battlefield">Beyond Features: The Next Competitive Battlefield</h3><p><strong>The Consolidation Pattern:</strong></p><ul><li><strong>Traditional Platforms:</strong>&#xA0;Compete on AI model performance and features</li><li><strong>Foundational Providers:</strong>&#xA0;Own the models and can replicate any feature</li><li><strong>Survivor Platforms:</strong>&#xA0;Own irreplaceable business processes and data</li></ul><p><strong>Example: The Relevance AI Reality Check</strong></p><ul><li><strong>Funding:</strong>&#xA0;$37 million Series B with impressive metrics</li><li><strong>Architecture:</strong>&#xA0;&quot;Model-agnostic&#x2014;use OpenAI, Claude, Gemini, and more&quot;</li><li><strong>Vulnerability:</strong>&#xA0;40,000 agents created in January 2025, but all dependent on external AI providers</li><li><strong>Strategic Problem:</strong>&#xA0;Building sophisticated wrappers around capabilities they don&apos;t control</li></ul><hr><h2 id="what-creates-defensible-agent-platforms">What Creates Defensible Agent Platforms?</h2><h3 id="the-data-moat-framework">The Data Moat Framework</h3><p><strong>The Four Pillars of Platform Survival:</strong></p><h4 id="1-proprietary-business-data">1.&#xA0;<strong>Proprietary Business Data</strong></h4><ul><li>Customer transaction histories and behavioral patterns</li><li>Industry-specific knowledge bases and best practices</li><li>Compliance documentation and audit trails</li><li>Institutional memory and decision-making frameworks</li></ul><h4 id="2-deep-process-integration">2.&#xA0;<strong>Deep Process Integration</strong></h4><ul><li>Multi-system workflow orchestration</li><li>Role-based approval hierarchies</li><li>Custom business logic and rules</li><li>Legacy system interconnections</li></ul><h4 id="3-regulatory-lock-in">3.&#xA0;<strong>Regulatory Lock-in</strong></h4><ul><li>Industry-specific compliance requirements</li><li>Data sovereignty and governance policies</li><li>Security certifications and audit frameworks</li><li>Legal and contractual obligations</li></ul><h4 id="4-network-effects">4.&#xA0;<strong>Network Effects</strong></h4><ul><li>User-generated content and configurations</li><li>Team collaboration and shared knowledge</li><li>Vendor ecosystem integrations</li><li>Platform-specific training and expertise</li></ul><h3 id="implementation-architecture-the-survival-blueprint">Implementation Architecture: The Survival Blueprint</h3><h4 id="foundation-layer-business-critical-functions">Foundation Layer: Business-Critical Functions</h4><pre><code class="language-plaintext"># Integrated Business Platform Structure
class DefensiblePlatform:
    core_business_functions = {
        &apos;customer_management&apos;: &apos;CRM with historical data&apos;,
        &apos;project_orchestration&apos;: &apos;Team workflows and approvals&apos;,
        &apos;financial_systems&apos;: &apos;Billing, reporting, compliance&apos;,
        &apos;knowledge_management&apos;: &apos;Institutional documentation&apos;,
        &apos;communication_workflows&apos;: &apos;Internal processes and approvals&apos;
    }
    
    ai_enhancement_layer = {
        &apos;intelligent_insights&apos;: &apos;Data analysis using proprietary datasets&apos;,
        &apos;workflow_optimization&apos;: &apos;Process improvement based on usage patterns&apos;,
        &apos;predictive_analytics&apos;: &apos;Forecasting using business-specific models&apos;,
        &apos;automation_suggestions&apos;: &apos;AI recommendations based on institutional knowledge&apos;
    }
</code></pre><h4 id="strategic-layer-switching-cost-creation">Strategic Layer: Switching Cost Creation</h4><p>The magic isn&apos;t in a smarter AI model or a more clever interface. It&apos;s about becoming integral to daily business operations that cannot be easily replaced.</p><pre><code class="language-plaintext"># Switching Cost Calculator
def calculate_replacement_cost(platform_integration):
    return {
        &apos;data_migration&apos;: estimate_data_transfer_complexity(),
        &apos;process_reconfiguration&apos;: map_workflow_dependencies(),
        &apos;compliance_recertification&apos;: assess_regulatory_requirements(),
        &apos;team_retraining&apos;: calculate_productivity_loss(),
        &apos;integration_rebuilding&apos;: evaluate_system_connections(),
        &apos;institutional_knowledge_loss&apos;: quantify_embedded_expertise()
    }
</code></pre><hr><h2 id="real-world-implementation-examples">Real-World Implementation Examples</h2><h3 id="case-study-1-professional-services-transformation">Case Study 1: Professional Services Transformation</h3><p><strong>The &quot;Demo Platform&quot; Approach:</strong></p><ul><li>AI agent that answers questions about project management</li><li>Generic workflow templates and basic automation</li><li>Dependent on external AI APIs for all intelligence</li></ul><p><strong>The &quot;Defensible Platform&quot; Approach:</strong></p><ul><li>Integrated project management system with years of historical data</li><li>AI agents that predict project risks based on past performance patterns</li><li>Custom billing workflows integrated with financial systems</li><li>Client communication history informing AI response personalization</li></ul><p><strong>Result:</strong>&#xA0;60% reduction in project delivery time, but more importantly,&#xA0;<strong>18 months of accumulated client data and process customization that cannot be easily replicated</strong>.</p><h3 id="case-study-2-healthcare-operations-integration">Case Study 2: Healthcare Operations Integration</h3><p><strong>Traditional Agent Platform:</strong></p><ul><li>Chatbot for answering medical questions</li><li>Basic appointment scheduling automation</li><li>General medical knowledge retrieval</li></ul><p><strong>Integrated Healthcare Platform:</strong></p><ul><li>Electronic health record system with patient history</li><li>AI diagnostic assistance based on institutional treatment outcomes</li><li>Compliance management integrated with regulatory requirements</li><li>Billing and insurance processing with historical optimization</li></ul><p><strong>Strategic Advantage:</strong>&#xA0;<strong>HIPAA compliance, patient data sovereignty, and institutional clinical knowledge create 24+ month switching costs.</strong></p><h3 id="case-study-3-manufacturing-operations-intelligence">Case Study 3: Manufacturing Operations Intelligence</h3><p><strong>Commoditized Approach:</strong></p><ul><li>AI agent for supply chain inquiries</li><li>Basic inventory management automation</li><li>Generic manufacturing optimization recommendations</li></ul><p><strong>Defensible Integration:</strong></p><ul><li>Equipment maintenance history and performance data</li><li>Quality control documentation with AI-powered pattern recognition</li><li>Supplier relationship management with predictive analytics</li><li>Regulatory compliance tracking with automated reporting</li></ul><p><strong>Competitive Moat:</strong>&#xA0;<strong>Years of operational data, compliance documentation, and process optimization that foundational providers cannot access or replicate.</strong></p><hr><h2 id="implementation-guide-from-vulnerable-to-defensible">Implementation Guide: From Vulnerable to Defensible</h2><h3 id="phase-1-assessment-foundation-weeks-1-2">Phase 1: Assessment &amp; Foundation (Weeks 1-2)</h3><h4 id="step-1-vulnerability-audit">Step 1: Vulnerability Audit</h4><pre><code class="language-plaintext"># Platform Defensibility Assessment
def audit_platform_defensibility():
    return {
        &apos;ai_dependency_risk&apos;: measure_external_ai_reliance(),
        &apos;data_ownership&apos;: assess_proprietary_information(),
        &apos;switching_costs&apos;: calculate_user_migration_difficulty(),
        &apos;process_integration&apos;: evaluate_business_criticality(),
        &apos;competitive_moats&apos;: identify_unique_advantages()
    }
</code></pre><h4 id="step-2-business-integration-mapping">Step 2: Business Integration Mapping</h4><p><strong>Identify Integration Opportunities:</strong></p><ul><li>Map existing business processes that could benefit from AI enhancement</li><li>Assess data assets that could create competitive advantages</li><li>Evaluate regulatory and compliance requirements that create lock-in</li><li>Analyze workflow dependencies that increase switching costs</li></ul><h3 id="phase-2-strategic-pivot-weeks-3-6">Phase 2: Strategic Pivot (Weeks 3-6)</h3><h4 id="business-first-development-framework">Business-First Development Framework:</h4><p>Agent platforms that survive will answer this question:&#xA0;<strong>&quot;If our AI capabilities disappeared tomorrow, would users still depend on our platform for critical business functions?&quot;</strong></p><p><strong>Implementation Strategy:</strong></p><ol><li><strong>Start with business functions</strong>&#xA0;that users cannot easily replace</li><li><strong>Add AI enhancement</strong>&#xA0;to improve these core functions</li><li><strong>Create data flywheel</strong>&#xA0;where more usage improves AI performance</li><li><strong>Build switching costs</strong>&#xA0;through customization and integration</li></ol><h4 id="integration-pattern-example">Integration Pattern Example:</h4><pre><code class="language-plaintext"># Business-Critical Platform Architecture
integrated_platform = {
    &apos;core_value&apos;: &apos;Customer relationship management system&apos;,
    &apos;proprietary_data&apos;: &apos;Customer interaction history and preferences&apos;,
    &apos;ai_enhancement&apos;: &apos;Predictive lead scoring based on historical success&apos;,
    &apos;switching_cost&apos;: &apos;Years of sales data and team workflow customization&apos;,
    &apos;network_effect&apos;: &apos;Better data improves AI, driving more usage&apos;
}
</code></pre><h3 id="phase-3-competitive-moat-construction-weeks-7-12">Phase 3: Competitive Moat Construction (Weeks 7-12)</h3><h4 id="advanced-defensibility-patterns">Advanced Defensibility Patterns:</h4><p><strong>Pattern 1: Regulatory Fortress</strong></p><ul><li>Build compliance workflows that are industry-specific</li><li>Create audit trails and documentation that satisfy regulatory requirements</li><li>Develop certification processes that lock in usage patterns</li></ul><p><strong>Pattern 2: Data Network Effects</strong></p><ul><li>Design systems where more users create better AI performance</li><li>Build shared knowledge bases that improve with organization usage</li><li>Create collaborative workflows that become more valuable over time</li></ul><p><strong>Pattern 3: Process Automation Lock-in</strong></p><ul><li>Integrate with critical business systems (ERP, CRM, financial)</li><li>Automate approval workflows and business logic</li><li>Become integral to daily operations rather than nice-to-have enhancement</li></ul><h3 id="phase-4-optimization-scale-ongoing">Phase 4: Optimization &amp; Scale (Ongoing)</h3><h4 id="performance-monitoring-framework">Performance Monitoring Framework:</h4><pre><code class="language-plaintext"># Defensibility Metrics
class PlatformSurvival:
    def __init__(self):
        self.switching_cost_score = 0.0  # Months to replace platform
        self.data_moat_strength = 0.0    # Uniqueness of proprietary data
        self.process_integration_depth = 0.0  # Business criticality
        self.network_effect_momentum = 0.0    # Value increase with usage
        self.competitive_replication_time = 0.0  # Time for competitors to match
</code></pre><hr><h2 id="common-pitfalls-how-to-avoid-them">Common Pitfalls &amp; How to Avoid Them</h2><h3 id="pitfall-1-ai-first-thinking">Pitfall 1: AI-First Thinking</h3><p><strong>The Problem:</strong>&#xA0;Building around AI capabilities rather than business needs&#xA0;<strong>The Solution:</strong>&#xA0;Start with irreplaceable business functions, then add AI enhancement</p><p><strong>Example:</strong></p><ul><li><strong>Wrong:</strong>&#xA0;&quot;We build the best customer service AI agent&quot;</li><li><strong>Right:</strong>&#xA0;&quot;We build customer service workflow systems that get smarter with AI&quot;</li></ul><h3 id="pitfall-2-feature-competition">Pitfall 2: Feature Competition</h3><p><strong>The Problem:</strong>&#xA0;Trying to out-feature foundational providers&#xA0;<strong>The Solution:</strong>&#xA0;Focus on integration depth and switching costs</p><p><strong>Strategic Framework:</strong>&#xA0;Instead of asking: &quot;How can we make our AI better?&quot; Ask: &quot;How can we make our platform irreplaceable?&quot;</p><h3 id="pitfall-3-model-dependency">Pitfall 3: Model Dependency</h3><p><strong>The Problem:</strong>&#xA0;Building core value proposition around AI model performance&#xA0;<strong>The Solution:</strong>&#xA0;Make AI model selection invisible to users while focusing on business outcomes</p><pre><code class="language-plaintext"># Strategic Positioning
value_proposition = {
    &apos;wrong&apos;: &apos;We provide access to the best AI models&apos;,
    &apos;right&apos;: &apos;We solve your business problems, and AI makes us better at it&apos;
}
</code></pre><hr><h2 id="the-future-of-agent-platform-survival">The Future of Agent Platform Survival</h2><h3 id="emerging-survival-patterns-for-2025-and-beyond">Emerging Survival Patterns for 2025 and Beyond</h3><h4 id="industry-vertical-dominance">Industry Vertical Dominance</h4><p>Platforms that survive will own specific industry verticals with deep regulatory and process integration rather than trying to be horizontal AI solutions.</p><p><strong>Winning Examples:</strong></p><ul><li><strong>Healthcare:</strong>&#xA0;EHR systems with AI diagnostic assistance</li><li><strong>Legal:</strong>&#xA0;Case management platforms with AI research capabilities</li><li><strong>Manufacturing:</strong>&#xA0;Operations management systems with AI optimization</li><li><strong>Financial Services:</strong>&#xA0;Compliance platforms with AI risk assessment</li></ul><h4 id="platform-ecosystem-strategy">Platform Ecosystem Strategy</h4><p>Future platforms will become ecosystems where removing the platform breaks multiple business-critical workflows, not just AI functionality.</p><p><strong>Strategic Elements:</strong></p><ul><li><strong>API Ecosystem:</strong>&#xA0;Third-party integrations that depend on the platform</li><li><strong>Data Partnerships:</strong>&#xA0;Industry data sharing that creates network effects</li><li><strong>Compliance Frameworks:</strong>&#xA0;Regulatory adherence that locks in usage</li><li><strong>Workflow Orchestration:</strong>&#xA0;Business process automation that becomes institutional knowledge</li></ul><h3 id="the-consolidation-timeline">The Consolidation Timeline</h3><p><strong>2025:</strong>&#xA0;Continued aggressive acquisition by foundational providers&#xA0;<strong>2026:</strong>&#xA0;Survival platforms emerge with strong business integration moats&#xA0;<strong>2027:</strong>&#xA0;Market settles into integrated business platforms vs. foundational AI providers</p><p><strong>Investment Priorities:</strong></p><ul><li><strong>Infrastructure:</strong>&#xA0;Business process integration systems</li><li><strong>Data Architecture:</strong>&#xA0;Proprietary data collection and analysis</li><li><strong>Compliance Engineering:</strong>&#xA0;Industry-specific regulatory frameworks</li><li><strong>Integration Platforms:</strong>&#xA0;Deep connections with existing business systems</li></ul><hr><h2 id="getting-started-your-platform-survival-strategy">Getting Started: Your Platform Survival Strategy</h2><h3 id="week-1-critical-assessment">Week 1: Critical Assessment</h3><ul><li><strong>Audit current AI dependencies</strong>&#xA0;and identify vulnerability points</li><li><strong>Map business functions</strong>&#xA0;that users depend on beyond AI capabilities</li><li><strong>Assess proprietary data assets</strong>&#xA0;that could create competitive advantages</li><li><strong>Evaluate switching costs</strong>&#xA0;users would face to replace your platform</li></ul><h3 id="week-2-strategic-planning">Week 2: Strategic Planning</h3><ul><li><strong>Identify integration opportunities</strong>&#xA0;with critical business systems</li><li><strong>Design data collection strategies</strong>&#xA0;that improve with usage</li><li><strong>Plan compliance and regulatory positioning</strong>&#xA0;for your industry</li><li><strong>Develop switching cost creation roadmap</strong></li></ul><h3 id="week-3-4-foundation-building">Week 3-4: Foundation Building</h3><ul><li><strong>Begin business function integration</strong>&#xA0;that creates user dependency</li><li><strong>Implement data collection systems</strong>&#xA0;that improve AI performance over time</li><li><strong>Design workflow automation</strong>&#xA0;that becomes integral to daily operations</li><li><strong>Launch pilot programs</strong>&#xA0;with deep business integration</li></ul><h3 id="beyond-competitive-moat-construction">Beyond: Competitive Moat Construction</h3><p><strong>The agent platform future will be built one business integration at a time. Engineer them to be irreplaceable.</strong></p><hr><h2 id="essential-resources-tools">Essential Resources &amp; Tools</h2><h3 id="survival-frameworks-platforms">Survival Frameworks &amp; Platforms</h3><ul><li><strong>Salesforce Platform:</strong>&#xA0;Study Agentforce integration with core CRM functions</li><li><strong>ServiceNow:</strong>&#xA0;Analyze Moveworks acquisition and integration strategy</li><li><strong>Microsoft Power Platform:</strong>&#xA0;Observe AI integration within business workflows</li><li><strong>Industry-Specific Platforms:</strong>&#xA0;Research vertical-specific survival strategies</li></ul><h3 id="strategic-learning-resources">Strategic Learning Resources</h3><ul><li><a href="https://www.cbinsights.com/research/report/tech-merger-acquisition-predictions-2025/?ref=blog.avarile.com">CB Insights AI M&amp;A Report 2025</a></li><li><a href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/superagency-in-the-workplace-empowering-people-to-unlock-ais-full-potential-at-work?ref=blog.avarile.com">McKinsey AI in the Workplace Report</a></li><li><a href="https://www.deloitte.com/us/en/insights/industry/technology/technology-media-and-telecom-predictions/2025/autonomous-generative-ai-agents-still-under-development.html?ref=blog.avarile.com">Deloitte Autonomous AI Agents Study</a></li></ul><h3 id="community-analysis">Community &amp; Analysis</h3><ul><li>Industry consolidation tracking and M&amp;A analysis</li><li>Platform survival case studies and failure analysis</li><li>Business integration patterns and switching cost creation strategies</li></ul><hr><h2 id="conclusion-the-platform-survival-imperative">Conclusion: The Platform Survival Imperative</h2><p>Agent platform survival represents more than just an evolution in AI development&#x2014;it&apos;s a fundamental paradigm shift that separates businesses that will exist in 2027 from those that won&apos;t.&#xA0;<strong>Building defensible AI platforms is becoming less about AI model performance and more about business integration depth and switching cost creation.</strong></p><p>The organizations that master business-first platform design today will have insurmountable advantages tomorrow. They&apos;ll build irreplaceable systems, create sustainable competitive moats, and solve business problems that foundational providers cannot easily replicate.</p><p><strong>Key Strategic Insight:</strong>&#xA0;The future belongs to platforms that make AI invisible by embedding it in irreplaceable business functions, not those that make AI the primary value proposition.</p><p><strong>Remember:</strong>&#xA0;Foundational providers can replicate features, interfaces, and even user experiences. They cannot replicate years of accumulated business data, institutional processes, and regulatory compliance that becomes embedded in well-integrated platforms.</p><h3 id="the-bottom-line">The Bottom Line</h3><p><strong>The age of &quot;AI-first platforms&quot; is ending before it truly began.</strong>&#xA0;Welcome to the era of&#xA0;<strong>business-first platforms enhanced by AI</strong>.</p><p>Ready to transform your vulnerable agent platform into a defensible business? Start by asking: &quot;If we removed all AI functionality tomorrow, would our users still depend on us for critical business operations?&quot; If the answer is no, you know exactly where to begin.</p><p><strong>The time for building on others&apos; foundations is over. The time for building foundations that others depend on has begun.</strong></p>]]></content:encoded></item><item><title><![CDATA[Context Engineering: From Prompt Crafting to Production-Grade AI Systems]]></title><description><![CDATA[<p></p><p><em>The discipline that&apos;s redefining how we build intelligent AI applications in 2025</em></p><hr><h2 id="tldrthe-bottom-line"><strong>TL;DR - The Bottom Line</strong></h2><p>Context Engineering is the discipline of designing and building dynamic systems that provides the right information and tools, in the right format, at the right time, to give a LLM</p>]]></description><link>https://blog.avarile.com/context-engineering-from-prompt-crafting-to-production-grade-ai-systems/</link><guid isPermaLink="false">687fc0dbf0886e0001e0effe</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Tue, 22 Jul 2025 16:51:01 GMT</pubDate><content:encoded><![CDATA[<p></p><p><em>The discipline that&apos;s redefining how we build intelligent AI applications in 2025</em></p><hr><h2 id="tldrthe-bottom-line"><strong>TL;DR - The Bottom Line</strong></h2><p>Context Engineering is the discipline of designing and building dynamic systems that provides the right information and tools, in the right format, at the right time, to give a LLM everything it needs to accomplish a task. While prompt engineering focused on crafting clever single instructions, context engineering is about architecting complete information environments that enable AI systems to handle complex, multi-step tasks reliably.</p><p><strong>Key takeaway:</strong>&#xA0;The difference between a cheap demo and a &quot;magical&quot; agent is about the quality of the context you provide.</p><hr><h2 id="the-evolution-why-context-engineering-matters-now"><strong>The Evolution: Why Context Engineering Matters Now</strong></h2><h3 id="from-prompts-to-systems"><strong>From Prompts to Systems</strong></h3><p>Early on, developers focused on phrasing prompts cleverly to coax better answers. But as applications grow more complex, it&apos;s becoming clear that providing complete and structured context to the AI is far more important than any magic wording.</p><p>The AI landscape has fundamentally shifted:</p><ul><li><strong>2023</strong>: &quot;You are an expert. Do X like Y&quot; (Prompt Engineering Era)</li><li><strong>2024</strong>: Building systems that dynamically gather, structure, and provide context</li><li><strong>2025</strong>: Most agent failures are not model failures anymore, they are context failures</li></ul><h3 id="the-critical-business-impact"><strong>The Critical Business Impact</strong></h3><p><strong>Performance Transformation</strong>: Organizations implementing proper context engineering principles see success rates jump from about 30% to over 90%</p><p><strong>Cost Efficiency</strong>: Studies show that well-engineered context can:</p><ul><li>Reduce token usage by 20-50% in commercial AI operations</li><li>Improve task completion rates by up to 40%</li><li>Minimize computational resources needed for desired outcomes</li></ul><p><strong>Production Readiness</strong>: Context engineering shifts the mindset from just writing prompts to designing a system. The prompt you write becomes only a subset of that system.</p><hr><h2 id="what-is-context-engineering"><strong> What Is Context Engineering?</strong></h2><h3 id="the-core-definition"><strong>The Core Definition</strong></h3><p>Context engineering is the delicate art and science of filling the context window with just the right information for the next step &#x2014; a definition that&apos;s gained traction from AI luminaries like Andrej Karpathy.</p><p>But let&apos;s break this down further:</p><p><strong>Context &#x2260; Just Your Prompt</strong></p><pre><code>Traditional View: Context = Single prompt/instruction
Reality: Context = Everything the model sees before generating
</code></pre><h3 id="the-complete-context-architecture"><strong>The Complete Context Architecture</strong></h3><p>Context engineering involves assembling a variety of components, including a basic prompt, memory, output from RAG pipelines, output from tool invocation, well-defined and structured output format, and guardrails.</p><p><strong>The Five Pillars of Context:</strong></p><ol><li><strong>Instructions &amp; System Prompts</strong><ul><li>Role definitions and behavioral guidelines</li><li>Task-specific instructions and constraints</li><li>Examples and few-shot learning patterns</li></ul></li><li><strong>Memory &amp; Historical Context</strong><ul><li>Conversation history and session state</li><li>User preferences and behavioral patterns</li><li>Long-term interaction memory</li></ul></li><li><strong>Retrieved Knowledge (RAG)</strong><ul><li>External documents and knowledge bases</li><li>Real-time data feeds and API responses</li><li>Domain-specific information injection</li></ul></li><li><strong>Tool &amp; Environment Context</strong><ul><li>Available functions and their descriptions</li><li>System capabilities and limitations</li><li>External service integrations</li></ul></li><li><strong>Output Formatting &amp; Constraints</strong><ul><li>Response structure and style guidelines</li><li>Safety guardrails and content policies</li><li>Quality control mechanisms</li></ul></li></ol><hr><h2 id="context-engineering-vs-traditional-approaches"><strong>Context Engineering vs. Traditional Approaches</strong></h2><h3 id="the-fundamental-differences"><strong>The Fundamental Differences</strong></h3>
<!--kg-card-begin: html-->
<table style="font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-align: start; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);"><thead><tr><th><strong>Aspect</strong></th><th><strong>Prompt Engineering</strong></th><th><strong>Context Engineering</strong></th></tr></thead><tbody><tr><td><strong>Scope</strong></td><td>Single instruction crafting</td><td>System-wide information architecture</td></tr><tr><td><strong>Focus</strong></td><td>&quot;What you say&quot;</td><td>&quot;Everything the model sees&quot;</td></tr><tr><td><strong>Approach</strong></td><td>Static templates</td><td>Dynamic information systems</td></tr><tr><td><strong>Scale</strong></td><td>Individual queries</td><td>Production applications</td></tr><tr><td><strong>Complexity</strong></td><td>Linear instructions</td><td>Multi-dimensional context orchestration</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="beyond-rag-the-next-evolution"><strong>Beyond RAG: The Next Evolution</strong></h3><p>GraphRAG and knowledge graphs are to context engineering, what RAG and vector databases are to prompt engineering.</p><p><strong>Traditional RAG Limitations:</strong></p><ul><li>Documents lose context when chunked, which affects the retrieval quality and subsequent response quality</li><li>The vector embedding approach to storing and retrieving information is inherently lossy and may miss out on retrieving chunks with exact lexical matches</li></ul><p><strong>Context Engineering Solutions:</strong></p><ul><li>Multi-modal context integration</li><li>Hierarchical information structures</li><li>Dynamic context adaptation</li><li>Cross-domain knowledge synthesis</li></ul><hr><h2 id="implementation-architecture-best-practices"><strong>Implementation Architecture &amp; Best Practices</strong></h2><h3 id="the-four-layer-context-stack"><strong>The Four-Layer Context Stack</strong></h3><p><strong>1. Foundation Layer: Information Architecture</strong></p><pre><code class="language-python"># Context Template Structure
class ContextTemplate:
    role: str              # Define AI&apos;s expertise and behavior
    task: str              # Specific objective or goal  
    background: str        # Relevant domain context
    constraints: str       # Limitations and requirements
    examples: List[str]    # Few-shot learning samples
    format: str           # Output structure specification
</code></pre><p><strong>2. Dynamic Layer: Real-Time Context Assembly</strong>&#xA0;The magic isn&apos;t in a smarter model or a more clever algorithm. It&apos;s about providing the right context for the right task.</p><pre><code class="language-python"># Dynamic Context Pipeline
def assemble_context(user_query, session_state):
    context = {
        &apos;instructions&apos;: load_task_instructions(user_query),
        &apos;memory&apos;: retrieve_relevant_history(session_state),
        &apos;knowledge&apos;: rag_retrieve(user_query),
        &apos;tools&apos;: select_relevant_tools(user_query),
        &apos;constraints&apos;: apply_safety_guardrails()
    }
    return optimize_context_window(context)
</code></pre><p><strong>3. Orchestration Layer: Multi-Agent Coordination</strong>&#xA0;Instead of cramming everything into a single LLM call and hoping for the best, you can break complex tasks into focused steps, each with its own optimized context window.</p><p><strong>4. Optimization Layer: Context Management</strong></p><h3 id="advanced-techniques-for-production-systems"><strong>Advanced Techniques for Production Systems</strong></h3><p><strong>Context Compression &amp; Optimization</strong>&#xA0;Context pruning means removing outdated or conflicting information as new details arrive. Context offloading, like Anthropic&apos;s &quot;think&quot; tool, gives models a separate workspace to process information without cluttering the main context.</p><p><strong>Memory Selection Strategies</strong>&#xA0;Embeddings and / or knowledge graphs for memory indexing are commonly used to assist with selection. Still, memory selection is challenging.</p><p><strong>Tool Context Management</strong>&#xA0;Agents use tools, but can become overloaded if they are provided with too many. One approach is to apply RAG to tool descriptions in order to fetch the most relevant tools for a task based upon semantic similarity.</p><hr><h2 id="real-world-applications-case-studies"><strong>Real-World Applications &amp; Case Studies</strong></h2><h3 id="enterprise-knowledge-integration"><strong>Enterprise Knowledge Integration</strong></h3><p>Enterprises often struggle with knowledge fragmented across countless silos: Confluence, Jira, SharePoint, Slack, CRMs, and various databases. Context engineering provides the architecture to unify these disparate sources.</p><p><strong>Case Study: Financial Services AI Assistant</strong></p><ul><li><strong>Challenge</strong>: Integrate customer data, regulatory documents, and market data</li><li><strong>Solution</strong>: Multi-source RAG with hierarchical context prioritization</li><li><strong>Result</strong>: 60% reduction in resolution time, 35% improvement in accuracy</li></ul><h3 id="advanced-code-generation-systems"><strong>Advanced Code Generation Systems</strong></h3><p>The next evolution of coding assistants is moving beyond simple autocomplete. Systems are being built that have full context of an entire codebase, integrating with Language Server Protocols (LSP) to understand type errors, parsing production logs to identify bugs, and reading recent commits to maintain coding style.</p><p><strong>Implementation Pattern:</strong></p><pre><code class="language-python"># Agentic Code Assistant Context
code_context = {
    &apos;codebase_analysis&apos;: analyze_project_structure(),
    &apos;recent_commits&apos;: get_git_history(days=7),
    &apos;error_logs&apos;: parse_production_errors(),
    &apos;coding_standards&apos;: load_style_guide(),
    &apos;dependencies&apos;: analyze_package_dependencies()
}
</code></pre><h3 id="customer-service-automation"><strong>Customer Service Automation</strong></h3><p><strong>The &quot;Magical&quot; vs &quot;Demo&quot; Agent Example:</strong></p><p>The &quot;Cheap Demo&quot; Agent has poor context. It sees only the user&apos;s request and nothing else. The &quot;Magical&quot; Agent is powered by rich context.</p><p><strong>Demo Agent Response:</strong></p><pre><code>User: &quot;Hey, just checking if you&apos;re around for a quick sync tomorrow.&quot;
Demo: &quot;Thank you for your message. Tomorrow works for me. 
May I ask what time you had in mind?&quot;
</code></pre><p><strong>Magical Agent Context:</strong></p><ul><li>Calendar integration showing availability</li><li>Previous meeting patterns with this contact</li><li>Project context and urgency levels</li><li>Communication style preferences</li></ul><p><strong>Magical Agent Response:</strong></p><pre><code>&quot;Hi! I see you&apos;re working on the Q4 launch project. I have a 
30-minute slot open tomorrow at 2 PM EST, which aligns with 
our usual check-in time. Should I send a calendar invite?&quot;
</code></pre><hr><h2 id="implementation-guide-from-theory-to-production"><strong>Implementation Guide: From Theory to Production</strong></h2><h3 id="phase-1-foundation-setup-weeks-1-2"><strong>Phase 1: Foundation Setup (Weeks 1-2)</strong></h3><p><strong>Step 1: Context Audit</strong></p><pre><code class="language-python"># Assess current context usage
def audit_existing_prompts():
    return {
        &apos;static_elements&apos;: extract_reusable_components(),
        &apos;dynamic_needs&apos;: identify_variable_content(),
        &apos;failure_points&apos;: analyze_poor_responses(),
        &apos;optimization_opportunities&apos;: find_efficiency_gaps()
    }
</code></pre><p><strong>Step 2: Template Framework</strong>&#xA0;Context Engineering is 10x better than prompt engineering and 100x better than vibe coding.</p><h3 id="phase-2-dynamic-context-systems-weeks-3-4"><strong>Phase 2: Dynamic Context Systems (Weeks 3-4)</strong></h3><p><strong>RAG Integration Best Practices:</strong>&#xA0;Introduce context back into the chunks. This can be as simple as prepending chunks with the document and section titles, a method sometimes known as contextual chunk headers.</p><pre><code class="language-python"># Enhanced RAG Context
def enhance_chunks_with_context(chunks, document_metadata):
    enhanced_chunks = []
    for chunk in chunks:
        enhanced_chunk = {
            &apos;content&apos;: chunk[&apos;text&apos;],
            &apos;context_header&apos;: f&quot;Document: {document_metadata[&apos;title&apos;]}\n&quot;
                             f&quot;Section: {chunk[&apos;section&apos;]}\n&quot;
                             f&quot;Context: {chunk[&apos;summary&apos;]}&quot;,
            &apos;metadata&apos;: document_metadata
        }
        enhanced_chunks.append(enhanced_chunk)
    return enhanced_chunks
</code></pre><h3 id="phase-3-advanced-optimization-weeks-5-6"><strong>Phase 3: Advanced Optimization (Weeks 5-6)</strong></h3><p><strong>Context Engineering Patterns:</strong>&#xA0;Patterns for agent context engineering are still evolving, but we can group common approaches into 4 buckets &#x2014; write, select, compress, and isolate</p><ol><li><strong>Write</strong>: Store context externally for future retrieval</li><li><strong>Select</strong>: Intelligently choose relevant context for current task</li><li><strong>Compress</strong>: Distill information to essential elements</li><li><strong>Isolate</strong>: Separate contexts to prevent interference</li></ol><h3 id="phase-4-production-deployment"><strong>Phase 4: Production Deployment</strong></h3><p><strong>Performance Monitoring Framework:</strong></p><pre><code class="language-python"># Context Engineering Metrics
class ContextMetrics:
    def __init__(self):
        self.task_completion_rate = 0.0
        self.context_efficiency_ratio = 0.0
        self.user_satisfaction_score = 0.0
        self.cost_per_successful_interaction = 0.0
        self.context_window_utilization = 0.0
</code></pre><hr><h2 id="advanced-techniques-emerging-patterns"><strong>Advanced Techniques &amp; Emerging Patterns</strong></h2><h3 id="hierarchical-context-architecture"><strong>Hierarchical Context Architecture</strong></h3><p>Enterprise experts in 2025 often highlight RAG as a key to prevent hallucinations and enforce truthfulness in AI outputs. They also emphasize long-term session memory so that AI assistants can be truly helpful.</p><p><strong>Multi-Layer Context Design:</strong></p><pre><code>&#x251C;&#x2500;&#x2500; Global Context (System-wide)
&#x2502;   &#x251C;&#x2500;&#x2500; Organization policies and guidelines
&#x2502;   &#x251C;&#x2500;&#x2500; Security and compliance requirements
&#x2502;   &#x2514;&#x2500;&#x2500; Brand voice and communication standards
&#x251C;&#x2500;&#x2500; Session Context (User-specific)
&#x2502;   &#x251C;&#x2500;&#x2500; User profile and preferences
&#x2502;   &#x251C;&#x2500;&#x2500; Conversation history and patterns
&#x2502;   &#x2514;&#x2500;&#x2500; Current task and project context
&#x2514;&#x2500;&#x2500; Task Context (Request-specific)
    &#x251C;&#x2500;&#x2500; Immediate query requirements
    &#x251C;&#x2500;&#x2500; Retrieved knowledge and tools
    &#x2514;&#x2500;&#x2500; Real-time environmental data
</code></pre><h3 id="context-versioning-ab-testing"><strong>Context Versioning &amp; A/B Testing</strong></h3><p>Context engineering turned out to be anything but straightforward. It&apos;s an experimental science&#x2014;and we&apos;ve rebuilt our agent framework four times, each time after discovering a better way to shape context.</p><p><strong>Implementation Strategy:</strong></p><pre><code class="language-python"># Context Version Control
class ContextVersion:
    def __init__(self, version_id, context_config):
        self.version_id = version_id
        self.config = context_config
        self.performance_metrics = {}
        self.last_updated = datetime.now()
    
    def compare_performance(self, other_version):
        return self.performance_metrics.compare(other_version.performance_metrics)
</code></pre><h3 id="structured-context-encoding"><strong>Structured Context Encoding</strong></h3><p>A 2025 article suggests using an &quot;XML-like structure to pack various types of information&quot; (messages, tool outputs, errors) into the context. This is an example of low-level context engineering.</p><p><strong>Example Implementation:</strong></p><pre><code class="language-xml">&lt;context&gt;
    &lt;role&gt;Senior Software Architect&lt;/role&gt;
    &lt;task&gt;Design microservices architecture&lt;/task&gt;
    &lt;knowledge&gt;
        &lt;document source=&quot;company_guidelines.pdf&quot;&gt;
            Architecture must follow 12-factor app principles...
        &lt;/document&gt;
        &lt;api_docs&gt;Current service endpoints and schemas&lt;/api_docs&gt;
    &lt;/knowledge&gt;
    &lt;constraints&gt;
        &lt;security&gt;SOC2 compliance required&lt;/security&gt;
        &lt;performance&gt;Sub-100ms response time&lt;/performance&gt;
    &lt;/constraints&gt;
&lt;/context&gt;
</code></pre><hr><h2 id="common-pitfalls-how-to-avoid-them"><strong>Common Pitfalls &amp; How to Avoid Them</strong></h2><h3 id="context-poisoning-mitigation"><strong>Context Poisoning &amp; Mitigation</strong></h3><p>Context Poisoning: When a hallucination makes it into the context</p><p><strong>Prevention Strategies:</strong></p><ul><li>Implement context validation layers</li><li>Use source attribution and confidence scoring</li><li>Regular context auditing and cleanup procedures</li></ul><h3 id="the-context-window-management-challenge"><strong>The Context Window Management Challenge</strong></h3><p>The problem happens because when information comes in stages, the assembled context contains early attempts by the model to answer questions before it has all the information.</p><p><strong>Solution Framework:</strong></p><ol><li><strong>Priority-based Context Ranking</strong></li><li><strong>Dynamic Context Compression</strong></li><li><strong>Staged Information Assembly</strong></li><li><strong>Conflict Resolution Protocols</strong></li></ol><h3 id="memory-selection-gone-wrong"><strong>Memory Selection Gone Wrong</strong></h3><p>At the AIEngineer World&apos;s Fair, Simon Willison shared an example of memory selection gone wrong: ChatGPT fetched his location from memories and unexpectedly injected it into a requested image.</p><p><strong>Best Practices:</strong></p><ul><li>Implement explicit memory consent mechanisms</li><li>Use context relevance scoring</li><li>Provide memory transparency to users</li></ul><hr><h2 id="the-future-of-context-engineering"><strong>The Future of Context Engineering</strong></h2><h3 id="emerging-trends-for-2025-and-beyond"><strong>Emerging Trends for 2025 and Beyond</strong></h3><p><strong>Autonomous Context Optimization</strong>&#xA0;Context learning systems that adapt context strategies automatically represent the next frontier, where systems learn optimal context patterns from successful interactions.</p><p><strong>Multi-Modal Context Integration</strong>&#xA0;Future systems will seamlessly blend text, images, audio, and structured data into coherent context frameworks that mirror human multi-sensory understanding.</p><p><strong>Context Sovereignty</strong>&#xA0;I&apos;ve been working through the idea of context engineering lately (as well as the related context sovereignty) &#x2014; ensuring users maintain control over their contextual information and how it&apos;s utilized.</p><h3 id="the-strategic-imperative"><strong>The Strategic Imperative</strong></h3><p>LLM applications are evolving from single prompts to more complex, dynamic agentic systems. As such, context engineering is becoming the most important skill an AI engineer can develop.</p><p><strong>Key Investment Areas:</strong></p><ul><li><strong>Infrastructure</strong>: Context storage and retrieval systems</li><li><strong>Tooling</strong>: Context engineering development environments</li><li><strong>Talent</strong>: Engineers skilled in information architecture</li><li><strong>Processes</strong>: Context testing and optimization workflows</li></ul><hr><h2 id="getting-started-your-context-engineering-journey"><strong>Getting Started: Your Context Engineering Journey</strong></h2><h3 id="week-1-assessment-foundation"><strong>Week 1: Assessment &amp; Foundation</strong></h3><ol><li><strong>Audit existing AI implementations</strong>&#xA0;for context usage patterns</li><li><strong>Identify failure modes</strong>&#xA0;related to insufficient or poor context</li><li><strong>Map information sources</strong>&#xA0;available in your organization</li><li><strong>Establish baseline metrics</strong>&#xA0;for current AI performance</li></ol><h3 id="week-2-template-development"><strong>Week 2: Template Development</strong></h3><ol><li><strong>Create context templates</strong>&#xA0;for your most common use cases</li><li><strong>Implement basic RAG integration</strong>&#xA0;for knowledge retrieval</li><li><strong>Design context versioning system</strong>&#xA0;for A/B testing</li><li><strong>Set up monitoring</strong>&#xA0;for context effectiveness</li></ol><h3 id="week-3-4-advanced-implementation"><strong>Week 3-4: Advanced Implementation</strong></h3><ol><li><strong>Deploy dynamic context assembly</strong>&#xA0;pipelines</li><li><strong>Integrate multiple information sources</strong>&#xA0;(databases, APIs, documents)</li><li><strong>Implement context compression</strong>&#xA0;and optimization techniques</li><li><strong>Launch pilot applications</strong>&#xA0;with enhanced context engineering</li></ol><h3 id="beyond-continuous-optimization"><strong>Beyond: Continuous Optimization</strong></h3><p>The agentic future will be built one context at a time. Engineer them well.</p><hr><h2 id="essential-resources-tools"><strong>Essential Resources &amp; Tools</strong></h2><h3 id="frameworks-platforms"><strong>Frameworks &amp; Platforms</strong></h3><ul><li><strong>LlamaIndex</strong>: Context-aware AI application framework</li><li><strong>LangChain</strong>: Multi-modal context orchestration</li><li><strong>Anthropic Claude</strong>: Advanced context window management</li><li><strong>OpenAI API</strong>: System message and context integration</li></ul><h3 id="learning-resources"><strong>Learning Resources</strong></h3><ul><li><a href="https://blog.langchain.com/the-rise-of-context-engineering/?ref=blog.avarile.com">Context Engineering Guide by LangChain</a></li><li><a href="https://github.com/Meirtz/Awesome-Context-Engineering?ref=blog.avarile.com">Awesome Context Engineering GitHub Repository</a></li><li><a href="https://www.datacamp.com/blog/context-engineering?ref=blog.avarile.com">DataCamp Context Engineering Tutorial</a></li></ul><h3 id="community-discussion"><strong>Community &amp; Discussion</strong></h3><ul><li>AI Engineer World&apos;s Fair presentations on context engineering</li><li>Industry blogs from practitioners at Manus, Anthropic, and OpenAI</li><li>Research papers on retrieval-augmented generation and memory systems</li></ul><hr><h2 id="conclusion-the-context-engineering-imperative"><strong>Conclusion: The Context Engineering Imperative</strong></h2><p>Context engineering represents more than just an evolution in AI development&#x2014;it&apos;s a fundamental paradigm shift that separates production-grade AI systems from experimental prototypes. Building powerful and reliable AI Agents is becoming less about finding a magic prompt or model updates. It is about the engineering of context and providing the right information and tools, in the right format, at the right time.</p><p>The organizations and individuals who master context engineering today will have a decisive advantage in the AI-driven economy of tomorrow. They&apos;ll build more reliable systems, deliver better user experiences, and solve more complex problems with greater efficiency and accuracy.</p><p>As we move forward, remember:&#xA0;<strong>the future belongs to those who can architect intelligence, not just prompt it.</strong>Context engineering is your blueprint for that architectural mastery.</p><hr><p><em>Ready to transform your AI implementations? Start with a single use case, apply these context engineering principles, and experience the difference that systematic context design can make. The age of &quot;prompt and hope&quot; is over&#x2014;welcome to the era of engineered intelligence.</em></p>]]></content:encoded></item><item><title><![CDATA[Building Sophisticated AI Agents: ReAct, Context Awareness, and Specification-Driven Design]]></title><description><![CDATA[<h1 id></h1><p><em>A deep dive into creating intelligent agents that can reason, act, and operate within their computational constraints</em></p><hr><h2 id="introduction">Introduction</h2><p>As AI agents become increasingly sophisticated, developers are discovering that building truly effective autonomous systems requires more than just powerful language models. The key lies in understanding three fundamental principles: how to</p>]]></description><link>https://blog.avarile.com/building-sophisticated-ai-agents-react-context-awareness-and-specification-driven-design/</link><guid isPermaLink="false">687f9fedf0886e0001e0efe1</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Tue, 22 Jul 2025 14:29:41 GMT</pubDate><content:encoded><![CDATA[<h1 id></h1><p><em>A deep dive into creating intelligent agents that can reason, act, and operate within their computational constraints</em></p><hr><h2 id="introduction">Introduction</h2><p>As AI agents become increasingly sophisticated, developers are discovering that building truly effective autonomous systems requires more than just powerful language models. The key lies in understanding three fundamental principles: how to structure multi-step reasoning and action cycles, how agents perceive and work within their computational boundaries, and why specifications trump creative prompting.</p><p>In this post, we&apos;ll explore how to build &quot;manus-like&quot; agents&#x2014;systems capable of complex, multi-round interactions&#x2014;while understanding their inherent limitations and designing robust specification frameworks.</p><h2 id="understanding-the-react-paradigm">Understanding the ReAct Paradigm</h2><h3 id="what-is-react">What is ReAct?</h3><p>ReAct (Reasoning and Acting) represents a fundamental shift in how we architect AI agents. Unlike simple request-response systems, ReAct agents can:</p><ul><li><strong>Reason</strong>&#xA0;about problems step by step</li><li><strong>Act</strong>&#xA0;by invoking tools and gathering information</li><li><strong>Reflect</strong>&#xA0;on results and adjust their approach</li><li><strong>Iterate</strong>&#xA0;through multiple cycles until completion</li></ul><h3 id="the-multi-round-action-architecture">The Multi-Round Action Architecture</h3><p>A manus-like agent operates through discrete cycles, each containing three phases:</p><p><strong>Phase 1: Observation &amp; Analysis</strong></p><pre><code>Agent receives input &#x2192; Analyzes current state &#x2192; Identifies required actions
</code></pre><p><strong>Phase 2: Tool Invocation &amp; Execution</strong></p><pre><code>Selects appropriate tools &#x2192; Executes actions &#x2192; Gathers results
</code></pre><p><strong>Phase 3: Synthesis &amp; Planning</strong></p><pre><code>Processes results &#x2192; Updates mental model &#x2192; Plans next actions
</code></pre><h3 id="implementing-the-react-loop">Implementing the ReAct Loop</h3><p>Here&apos;s how to structure a robust ReAct agent:</p><p><strong>Step 1: Define the Reasoning Framework</strong></p><p>Your agent needs explicit instructions for each phase:</p><ul><li>How to analyze problems systematically</li><li>When to gather more information vs. when to act</li><li>How to evaluate the success of each action</li><li>When to conclude the task is complete</li></ul><p><strong>Step 2: Create Action Boundaries</strong></p><p>Establish clear rules for:</p><ul><li>Maximum number of iterations per task</li><li>Fallback strategies when tools fail</li><li>Escalation paths for complex problems</li><li>Resource usage limits</li></ul><p><strong>Step 3: Build Reflection Mechanisms</strong></p><p>After each action, the agent should:</p><ul><li>Evaluate whether the action achieved its intended goal</li><li>Identify any new information that changes the problem space</li><li>Adjust the strategy if the current approach isn&apos;t working</li><li>Maintain a running summary of progress</li></ul><h3 id="example-react-structure">Example ReAct Structure</h3><pre><code>TASK: Research competitor pricing and create analysis report

ITERATION 1:
Thought: I need to gather pricing data from multiple competitors
Action: web_search(&quot;competitor A pricing 2024&quot;)
Result: Found pricing page with basic tier info
Reflection: Good start, but need more comprehensive data

ITERATION 2: 
Thought: Need to get detailed pricing for all tiers from competitor A
Action: web_fetch(&quot;https://competitor-a.com/pricing&quot;)
Result: Complete pricing matrix obtained
Reflection: Have comp A data, need competitors B and C

ITERATION 3:
Thought: Should search for competitor B pricing information  
Action: web_search(&quot;competitor B enterprise pricing&quot;)
...
</code></pre><h2 id="the-context-window-constraint-an-agents-limited-worldview">The Context Window Constraint: An Agent&apos;s Limited Worldview</h2><h3 id="understanding-agent-perception">Understanding Agent Perception</h3><p>One of the most crucial concepts for agent developers is understanding that&#xA0;<strong>agents can only work with information present in their context window</strong>. This creates fundamental limitations that shape how we must design agent systems.</p><h3 id="what-agents-can-and-cannot-see">What Agents Can and Cannot See</h3><p><strong>Agents CAN access:</strong></p><ul><li>The initial prompt and instructions</li><li>Previous messages in the current conversation</li><li>Results from tool calls within the current session</li><li>Data retrieved from MCP servers during the current execution</li><li>Their own reasoning and reflection from previous iterations</li></ul><p><strong>Agents CANNOT access:</strong></p><ul><li>Information from previous conversations or sessions</li><li>Data not explicitly retrieved through tool calls</li><li>Real-time information unless specifically fetched</li><li>Cached results from previous tool invocations</li><li>&quot;Hidden&quot; or implied context not present in the window</li></ul><h3 id="designing-for-context-limitations">Designing for Context Limitations</h3><p><strong>Strategy 1: Comprehensive Information Gathering</strong></p><p>Since agents forget everything outside their context, ensure they gather all necessary information within each session:</p><pre><code>Instead of assuming: &quot;The user mentioned their company&apos;s Q3 goals yesterday&quot;
Design for: &quot;Let me search for this user&apos;s Q3 goals in their documents&quot;
</code></pre><p><strong>Strategy 2: Explicit State Management</strong></p><p>Build agents that maintain explicit state within their context:</p><pre><code>CURRENT SESSION STATE:
- Task: Create marketing analysis
- Data gathered: [list of sources]
- Analysis completed: [list of sections] 
- Remaining work: [list of pending items]
</code></pre><p><strong>Strategy 3: Tool-First Information Architecture</strong></p><p>Design your agent to immediately gather context through tools rather than making assumptions:</p><pre><code>WRONG: &quot;Based on our previous discussion about your company...&quot;
RIGHT: &quot;Let me search your documents to understand your company context...&quot;
</code></pre><h3 id="context-window-best-practices">Context Window Best Practices</h3><p><strong>Optimize for Retention:</strong></p><ul><li>Summarize key findings after each major tool call</li><li>Maintain running lists of important data points</li><li>Use structured formats that are easy to parse later in the conversation</li></ul><p><strong>Plan for Forgetting:</strong></p><ul><li>Design tools that can re-establish context quickly</li><li>Build redundancy into information gathering</li><li>Create clear handoff mechanisms when context limits are reached</li></ul><h2 id="specifications-over-prompts-the-foundation-of-reliable-agents">Specifications Over Prompts: The Foundation of Reliable Agents</h2><h3 id="why-specifications-matter-more-than-creative-writing">Why Specifications Matter More Than Creative Writing</h3><p>Many developers approach agent design like creative writing&#x2014;crafting clever prompts with personality and flair. However, production-ready agents require engineering precision, not creative prose.</p><h3 id="the-specification-first-approach">The Specification-First Approach</h3><p><strong>Define Before You Write:</strong></p><p>Instead of starting with &quot;You are a helpful AI assistant who...&quot;, begin with:</p><ul><li><strong>Input specifications:</strong>&#xA0;Exactly what data formats the agent should expect</li><li><strong>Output specifications:</strong>&#xA0;Precise formatting requirements for responses</li><li><strong>Behavioral specifications:</strong>&#xA0;Clear rules for decision-making</li><li><strong>Error handling specifications:</strong>&#xA0;How to respond to edge cases</li><li><strong>Performance specifications:</strong>&#xA0;Success criteria and quality metrics</li></ul><h3 id="building-robust-specifications">Building Robust Specifications</h3><p><strong>Input Specification Example:</strong></p><pre><code>INPUT FORMAT:
- Task type: [research|analysis|creation|review]
- Scope: [specific parameters and boundaries]
- Required outputs: [list of deliverable formats]
- Constraints: [time, resources, quality requirements]
- Context: [relevant background information]

VALIDATION RULES:
- All required fields must be present
- Task type must match supported capabilities
- Scope must be achievable within context limits
</code></pre><p><strong>Behavioral Specification Example:</strong></p><pre><code>DECISION FRAMEWORK:
1. If task requires external data &#x2192; use tools to gather information
2. If multiple sources conflict &#x2192; present options with analysis
3. If insufficient information &#x2192; explicitly list missing data
4. If task is beyond scope &#x2192; explain limitations and suggest alternatives
5. If tools fail &#x2192; implement fallback strategy [defined procedure]

ERROR HANDLING:
- Tool timeout &#x2192; retry once, then fallback to alternative approach
- Invalid data &#x2192; clean and validate, or request clarification  
- Partial results &#x2192; clearly indicate completeness level
</code></pre><h3 id="specification-categories">Specification Categories</h3><p><strong>Functional Specifications:</strong></p><ul><li>What the agent must do</li><li>Required capabilities and tools</li><li>Success criteria for each task type</li></ul><p><strong>Interface Specifications:</strong></p><ul><li>How users interact with the agent</li><li>Expected input/output formats</li><li>Communication protocols</li></ul><p><strong>Quality Specifications:</strong></p><ul><li>Accuracy requirements</li><li>Response time limits</li><li>Error rate tolerances</li></ul><p><strong>Operational Specifications:</strong></p><ul><li>Resource usage limits</li><li>Security and privacy requirements</li><li>Integration requirements with other systems</li></ul><h3 id="testing-your-specifications">Testing Your Specifications</h3><p><strong>Specification Validation Process:</strong></p><ol><li><strong>Edge Case Testing:</strong>&#xA0;Create scenarios that push boundary conditions</li><li><strong>Ambiguity Detection:</strong>&#xA0;Identify areas where multiple interpretations are possible</li><li><strong>Completeness Checking:</strong>&#xA0;Ensure all scenarios have defined behaviors</li><li><strong>Consistency Verification:</strong>&#xA0;Check that specifications don&apos;t contradict each other</li></ol><h2 id="putting-it-all-together-a-complete-agent-architecture">Putting It All Together: A Complete Agent Architecture</h2><h3 id="the-integrated-approach">The Integrated Approach</h3><p>A production-ready agent combines all three principles:</p><p><strong>ReAct Foundation:</strong>&#xA0;Multi-round reasoning and action capabilities&#xA0;<strong>Context Awareness:</strong>&#xA0;Design that works within computational limits<br><strong>Specification-Driven:</strong>&#xA0;Precise behavioral definitions</p><h3 id="implementation-checklist">Implementation Checklist</h3><p><strong>ReAct Implementation:</strong></p><ul><li>[ ] Multi-phase reasoning structure defined</li><li>[ ] Tool invocation patterns established</li><li>[ ] Iteration limits and fallbacks configured</li><li>[ ] Reflection and adjustment mechanisms built</li></ul><p><strong>Context Management:</strong></p><ul><li>[ ] Information gathering strategies implemented</li><li>[ ] State management within context window</li><li>[ ] Tool-first architecture established</li><li>[ ] Context optimization techniques applied</li></ul><p><strong>Specification Framework:</strong></p><ul><li>[ ] Comprehensive input/output specifications</li><li>[ ] Behavioral rules clearly defined</li><li>[ ] Error handling procedures documented</li><li>[ ] Quality and performance criteria established</li></ul><h2 id="advanced-patterns-and-considerations">Advanced Patterns and Considerations</h2><h3 id="compound-agent-architectures">Compound Agent Architectures</h3><p>For complex tasks, consider breaking work across multiple specialized agents:</p><ul><li><strong>Research Agent:</strong>&#xA0;Focused on information gathering</li><li><strong>Analysis Agent:</strong>&#xA0;Specialized in data interpretation</li><li><strong>Synthesis Agent:</strong>&#xA0;Expert in combining insights into final deliverables</li></ul><h3 id="dynamic-specification-adjustment">Dynamic Specification Adjustment</h3><p>Build agents that can adjust their specifications based on:</p><ul><li>Task complexity assessment</li><li>Available time and resources</li><li>User expertise level</li><li>Context richness</li></ul><h3 id="monitoring-and-improvement">Monitoring and Improvement</h3><p>Implement logging and analytics to track:</p><ul><li>Tool usage patterns and success rates</li><li>Context window utilization efficiency</li><li>Specification adherence and violation patterns</li><li>User satisfaction with agent performance</li></ul><h2 id="conclusion">Conclusion</h2><p>Building sophisticated AI agents requires moving beyond prompt engineering toward systems engineering. The combination of ReAct reasoning patterns, context-aware design, and specification-driven development creates agents that are both powerful and reliable.</p><p>Remember: great agents aren&apos;t just well-prompted&#x2014;they&apos;re well-specified, context-aware, and designed to operate effectively within their computational boundaries. Focus on these engineering fundamentals, and you&apos;ll build agents that deliver consistent value in production environments.</p><p>The future of AI agents lies not in more creative prompts, but in more rigorous engineering. Start with specifications, design for constraints, and implement systematic reasoning&#x2014;your users will thank you for the reliability.</p><hr><p><em>This post represents current best practices in agent development. As the field evolves rapidly, continue to validate these approaches against your specific use cases and emerging research.</em></p>]]></content:encoded></item><item><title><![CDATA[Postgres tsvector with TypeORM]]></title><description><![CDATA[<p>PostgreSQL offers two specific data types that make full-text search easier.<br>Full-text search is basically the process of scanning through natural-language documents to find the ones that align most closely with a given query.</p><ul><li>The tsvector type is used to represent a document in a way that&#x2019;s fine-tuned</li></ul>]]></description><link>https://blog.avarile.com/postgres-tsvector-with-typeorm/</link><guid isPermaLink="false">68595c8394d164000175b40a</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Mon, 23 Jun 2025 13:54:36 GMT</pubDate><content:encoded><![CDATA[<p>PostgreSQL offers two specific data types that make full-text search easier.<br>Full-text search is basically the process of scanning through natural-language documents to find the ones that align most closely with a given query.</p><ul><li>The tsvector type is used to represent a document in a way that&#x2019;s fine-tuned for this kind of search.</li><li>The tsquery type is used to structure the text query itself.</li></ul><p>Using&#xA0;<a href="https://typeorm.io/?ref=blog.avarile.com" rel="noopener noreferrer">TypeORM</a>&#xA0;in Node.js application gives you nice support of Typescript for ORM models.<br>Lets see how can we setup PostgreSQL and&#xA0;<strong>tsvector</strong>&#xA0;with TypeORM</p><h2 id="background">Background</h2><p>Lets assume we have product and categories tables and corresponding models. We want to search products by product name, ean and category name.</p><p><strong>Product model:</strong><br></p><pre><code>@Entity()
export class Product {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({
    type: &apos;varchar&apos;,
  })
  name: string;

  @Column({
    type: &apos;varchar&apos;,
  })
  ean: string;

  @Column({
    type: &apos;int&apos;,
  })
  categoryId: number;
}
</code></pre><p><strong>Category model:</strong><br></p><pre><code>@Entity()
export class Category {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({
    type: &apos;varchar&apos;,
  })
  name: string;
}
</code></pre><h2 id="setup-tsvector">Setup tsvector</h2><p>We need to create a column in the table where we want to store the search vectors and retrieve search results from.</p><h3 id="add-full-text-search-column-to-product-model">Add full text search column to Product model</h3><pre><code>  @Column({
    type: &apos;tsvector&apos;,
    nullable: true,
  })
  fullTextSearch: string;
</code></pre><h3 id="create-migration">Create migration</h3><pre><code>import { MigrationInterface, QueryRunner } from &apos;typeorm&apos;

export class SearchVector1724418715424 implements MigrationInterface {
  name = &apos;SearchVector1724418715424&apos;

  public async up(queryRunner: QueryRunner): Promise&lt;void&gt; {
    await queryRunner.query(`ALTER TABLE &quot;product&quot; ADD &quot;fullTextSearch&quot; tsvector`)

    await queryRunner.query(`
        CREATE INDEX &quot;IDX_fullTextSearch&quot; 
        ON &quot;product&quot; 
        USING GIN (&quot;fullTextSearch&quot;);
    `)

    // Populate the fullTextSearch column for existing records
    await queryRunner.query(`
        UPDATE &quot;product&quot; p
        SET &quot;fullTextSearch&quot; = 
            setweight(to_tsvector(coalesce(p.&quot;ean&quot;, &apos;&apos;)), &apos;A&apos;) || 
            setweight(to_tsvector(coalesce(p.&quot;name&quot;, &apos;&apos;)), &apos;B&apos;) ||
            setweight(to_tsvector(coalesce(c.&quot;name&quot;, &apos;&apos;)), &apos;C&apos;)
        FROM &quot;category&quot; c
        WHERE p.&quot;categoryId&quot; = c.&quot;id&quot;;
    `)
  }

  public async down(queryRunner: QueryRunner): Promise&lt;void&gt; {
    await queryRunner.query(`
            DROP INDEX &quot;IDX_fullTextSearch&quot;;
        `)
    await queryRunner.query(`ALTER TABLE &quot;product&quot; DROP COLUMN &quot;fullTextSearch&quot;`)
  }
}

</code></pre><h3 id="updating-fulltextsearch-column-with-vectors">Updating fullTextSearch column with vectors</h3><p>This can be done 2 ways - database trigger and using TypeORM subscribers.</p><h4 id="database-triggercan-be-added-within-migration">Database trigger - can be added within migration</h4><pre><code>await queryRunner.query(`
    CREATE OR REPLACE FUNCTION update_fullTextSearch_trigger()
    RETURNS TRIGGER AS $$
    BEGIN
        NEW.&quot;fullTextSearch&quot; :=
            setweight(to_tsvector(coalesce(NEW.&quot;gtin&quot;, &apos;&apos;)), &apos;A&apos;) ||
            setweight(to_tsvector(coalesce(NEW.&quot;name&quot;, &apos;&apos;)), &apos;B&apos;) ||
            setweight(to_tsvector(coalesce((SELECT &quot;name&quot; FROM &quot;category&quot; WHERE &quot;id&quot; = NEW.&quot;categoryId&quot;), &apos;&apos;)), &apos;C&apos;);
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;

    CREATE TRIGGER &quot;update_fullTextSearch&quot;
    BEFORE INSERT OR UPDATE ON &quot;product&quot;
    FOR EACH ROW EXECUTE FUNCTION update_fullTextSearch_trigger();
`);
</code></pre><h4 id="typeorm-subscribers">TypeORM subscribers</h4><p>Using TypeORM subscribers offers a more controlled and maintainable way to update the search vector. This approach integrates directly with your application code, making it easier to manage, test, and version-control the logic.</p><ul><li>Create subscriber class</li></ul><pre><code>@EventSubscriber()
export class ProductSubscriber implements EntitySubscriberInterface&lt;Product&gt; {
  listenTo() {
    return Product
  }

  async afterInsert(event: InsertEvent&lt;Product&gt;) {
    await this.updateSearchVector(event)
  }

  async afterUpdate(event: UpdateEvent&lt;Product&gt;) {
    await this.updateSearchVector(event)
  }

  private async updateSearchVector(event: UpdateEvent&lt;Product&gt; | InsertEvent&lt;Product&gt;) {
    if (!event.entity) return
    await event.manager.query(
      `
        UPDATE product
        SET &quot;fullTextSearch&quot; = 
            setweight(to_tsvector(coalesce(product.gtin, &apos;&apos;)), &apos;A&apos;) || 
            setweight(to_tsvector(coalesce(product.name, &apos;&apos;)), &apos;B&apos;) || 
            setweight(to_tsvector(coalesce(category.name, &apos;&apos;)), &apos;C&apos;)
        FROM category
        WHERE product.&quot;categoryId&quot; = category.id
        AND product.id = $1
        `,
      [event.entity.id],
    )
  }
}

</code></pre><ul><li>Add subscriber to TypeORM DataSource</li></ul><pre><code>{
    type: &apos;postgres&apos;,
    host: process.env.DB_HOST,
    port: process.env.DB_PORT as number | undefined,
    username: process.env.DB_USER,
    password: process.env.DB_PASS,
    database: process.env.DB_NAME,
    entities: [
      Category,
      Product,
    ],
    subscribers: [ProductSubscriber],
  }
</code></pre><h3 id="apply-migration-to-your-database">Apply migration to your database</h3><p>Now we all set to use tsvector for full text search!</p><h2 id="usage">Usage</h2><p>The usage is very straightforward with&#xA0;<strong>tsquery</strong>:<br></p><pre><code>const queryBuilder = this.createQueryBuilder(&apos;product&apos;)

queryBuilder.where(&apos;product.fullTextSearch @@ plainto_tsquery(:value)&apos;, { value })


const result = await queryBuilder.getManyAndCount()

</code></pre><h2 id="summary">Summary</h2><p>In this article, we&#x2019;ve demonstrated how to integrate PostgreSQL&#x2019;s full-text search capabilities using the tsvector and tsquery data types within a Node.js application using TypeORM. We walked through setting up the tsvector column in the Product model, creating a migration to populate and index this column, and explored methods to keep the search vector updated&#x2014;whether through a database trigger or a TypeORM subscriber. By the end, you can now efficiently search across multiple fields like product name, EAN, and category name using full-text search, making it a powerful tool for optimizing search functionality in your applications.</p>]]></content:encoded></item><item><title><![CDATA[Nestjs --- Class validator]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1><p>In the fast-paced world of development, data integrity and reliability are paramount. Robust data validation and efficient handling of user data can make the difference between a smooth experience and an inconsistent application state.</p><p>George Fuechsel&#x2019;s quote below summarizes what this article is about.</p><blockquote>&#x201C;Garbage in,</blockquote>]]></description><link>https://blog.avarile.com/nestjs-class-validator/</link><guid isPermaLink="false">68189f2e4ff2db00015bb2eb</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Mon, 05 May 2025 11:31:25 GMT</pubDate><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1><p>In the fast-paced world of development, data integrity and reliability are paramount. Robust data validation and efficient handling of user data can make the difference between a smooth experience and an inconsistent application state.</p><p>George Fuechsel&#x2019;s quote below summarizes what this article is about.</p><blockquote>&#x201C;Garbage in, garbage out.&#x201D; &#x2014; George Fuechsel</blockquote><p>In this article, we will dive into data validation in NestJS. We will explore some complex use cases of class-validator and class-transformer to ensure data are valid and properly formatted. Along the way, we will discuss best practices, some advanced techniques, and common pitfalls to take your skills to the next level. My motive is to equip you to build more resilient and error-proof applications with NestJS.</p><p>Whiles we go through this journey together, keep in mind that we should never trust any inputs submitted by a user or client external to the application, regardless of whether it is part of a larger service(micro-service).</p><h1 id="table-of-contents">Table Of Contents</h1><ul><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#7a29" rel="noopener ugc nofollow">Introduction</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#bd0a" rel="noopener ugc nofollow">Data Transfer Object (DTO). What is it?</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#40fa" rel="noopener ugc nofollow">Initial Configuration: Setting Up Your NestJS Project</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#cde3" rel="noopener ugc nofollow">Creating User DTOs</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#af88" rel="noopener ugc nofollow">Adding Class Validators to Fields</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#bcb3" rel="noopener ugc nofollow">Validating Nested Objects</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#2ba9" rel="noopener ugc nofollow">Using Transform() and Type() from Class-transformer</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#c92e" rel="noopener ugc nofollow">Conditional Validation</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#f0a0" rel="noopener ugc nofollow">Handling Validation Errors</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#d450" rel="noopener ugc nofollow">Understanding Pipes</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#29c1" rel="noopener ugc nofollow">Setting Up a Global Validation Pipe</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#f83f" rel="noopener ugc nofollow">Formatting Validation Errors</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#e126" rel="noopener ugc nofollow">Creating Custom Validators</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#9def" rel="noopener ugc nofollow">Custom Password Validator</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#a0af" rel="noopener ugc nofollow">Asynchronous Custom Validator With Custom Validation Options</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#91af" rel="noopener ugc nofollow">Common Pitfalls and Best Practices</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#6040" rel="noopener ugc nofollow">Conclusion</a></li><li><a href="https://medium.com/@ahureinebenezer/mastering-data-validation-in-nestjs-a-complete-guide-with-class-validator-and-class-transformer-02a029db6ecf?ref=blog.avarile.com#911c" rel="noopener ugc nofollow">Additional Resources</a></li></ul><h1 id="data-transfer-object-dto-what-is-it">Data Transfer Object (DTO). What is it?</h1><p>DTO is a pattern we can leverage to encapsulate data and transfer it to different layers of the application. They are useful for managing the data that flows in(request) and out(response) of the app.</p><h2 id="immutable-dtos">Immutable DTOs</h2><p>As we have already established, the main idea for using DTOs is to transfer data and as such, the data should not be changed after they have been created. In general, DTOs are designed to be immutable, meaning that once they are created their properties can not be modified. Some benefit that comes with this include but not limited to:</p><ul><li>Predictable behavior: The confidence that its data remains unchanged.</li><li>Consistency: Once it is created, its state remains unchanged throughout its lifecycle until it&#x2019;s garbage collected.</li></ul><p>JavaScript does not have a built-in type for creating immutable types like we have&#xA0;<strong>record&#xA0;</strong>types<strong>&#xA0;</strong>in Java and C#. We can achieve similar behavior by making our fields&#xA0;<code>readonly</code>.</p><h1 id="initial-configuration-setting-up-your-nestjs-project">Initial Configuration: Setting Up Your NestJS Project</h1><p>We will start with a mini user management project, which will include basic CRUD operations to manage users. If you&#x2019;d like to explore the full source code, you can&#xA0;<a href="https://github.com/Ahurein/tech-articles/tree/main/user-mgt?ref=blog.avarile.com" rel="noopener ugc nofollow">click here</a>&#xA0;to access the project on GitHub.</p><p>Install NestJS CLI</p><p>$ npm i -g @nestjs/cli<br>$ nest new user-mgt</p><p>Install class-validator and class-transformer</p><p>npm i --save class-validator class-transformer</p><p>Generate the user module</p><p>$ nest g resource users<br>? What transport layer do you use? REST API<br>? Would you like to generate CRUD entry points? No</p><p>Create an empty DTO and entities folder. After everything, you should have this structure</p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:403/1*RPKtVFKAiabjL244LdSxPA.jpeg" class="kg-image" alt loading="lazy" width="403" height="596"></figure><h1 id="creating-user-dtos">Creating User DTOs</h1><p>Let&#x2019;s begin by creating the necessary DTOs. This tutorial will focus on only two actions, creating and updating a user. Create two files in the DTO folder</p><ul><li><code>user-create.dto.ts</code></li></ul><p>export class UserCreateDto {<br>  public readonly name: string;<br>  public readonly email: string;<br>  public readonly password: string;<br>  public readonly age: number;<br>  public readonly dateOfBirth: Date;<br>  public readonly photos: string[];<br>}<br></p><ul><li><code>user-update.dto.ts</code></li></ul><p>import { PartialType } from &apos;@nestjs/mapped-types&apos;;<br>import { UserCreateDto } from &apos;./user-create.dto&apos;;<br><br>export class UserUpdateDto extends PartialType(UserCreateDto) {}</p><p><code>UserUpdateDto</code>&#xA0;extends&#xA0;<code>UserCreateDto</code>&#xA0;to inherit all properties, the&#xA0;<code>PartialType</code>&#xA0;ensures that all fields are optional allowing for partial update. This saves us time so we don&#x2019;t have to repeat it.</p><h1 id="adding-class-validators-to-fields">Adding Class Validators to Fields</h1><p>Let&#x2019;s break down how to add validation to the fields. Class-validator provides us with a lot of already-made&#xA0;<a href="https://github.com/typestack/class-validator?tab=readme-ov-file&amp;ref=blog.avarile.com#validation-decorators" rel="noopener ugc nofollow">validation decorators</a>&#xA0;to which we can apply these rules to our DTOs. For now, we will use a few to validate&#xA0;<code>UserCreateDto</code>. click&#xA0;<a href="https://github.com/typestack/class-validator?tab=readme-ov-file&amp;ref=blog.avarile.com#validation-decorators" rel="noopener ugc nofollow">here</a>&#xA0;for the full list.</p><p>import {<br>  IsString,<br>  IsEmail,<br>  IsInt,<br>  Min,<br>  Max,<br>  Length,<br>  IsDate,<br>  IsArray,<br>  ArrayNotEmpty,<br>  ValidateNested,<br>  IsUrl,<br>} from &apos;class-validator&apos;;<br>import { Transform, Type } from &apos;class-transformer&apos;;<br><br>export class UserCreateDto {<br>  @IsString()<br>  @Length(2, 30, { message: &apos;Name must be between 2 and 30 characters&apos; })<br>  @Transform(({ value }) =&gt; value.trim())<br>  public readonly name: string;<br><br>  @IsEmail({}, { message: &apos;Invalid email address&apos; })<br>  public readonly email: string;<br><br>  @IsString()<br>  @Length(8, 50, { message: &apos;Password must be between 8 and 50 characters&apos; })<br>  public readonly password: string;<br><br>  @IsInt()<br>  @Min(18, { message: &apos;Age must be at least 18&apos; })<br>  @Max(100, { message: &apos;Age must not exceed 100&apos; })<br>  public readonly age: number;<br><br>  @IsDate({ message: &apos;Invalid date format&apos; })<br>  @Type(() =&gt; Date)<br>  public readonly dateOfBirth: Date;<br><br>  @IsArray()<br>  @ValidateNested()<br>  @ArrayNotEmpty({ message: &apos;Photos array should not be empty&apos; })<br>  @IsString({ each: true, message: &apos;Each photo URL must be a string&apos; })<br>  @IsUrl({}, { each: true, message: &apos;Each photo must be a valid URL&apos; })<br>  public readonly photos: string[];<br>}</p><p>Our simple class has grown in size, we have annotated the fields with decorators from&#xA0;<code>Class-Validator</code>. These decorators apply validation rules to the fields. You may have questions about the decorators if you are new to this. For example, what do they mean? Let&#x2019;s break down some of the basic validators we have used.</p><ul><li><code>IsString()</code>&#xA0;&#x2192; This decorator ensures that a value is a string.</li><li><code>Length(min, max)</code>&#xA0;&#x2192; This ensures that the string has a link within the specified range.</li><li><code>IsInt()</code>&#xA0;&#x2192; This decorator checks if the value is an integer.</li><li><code>Min()</code>&#xA0;and&#xA0;<code>Max()</code>&#xA0;&#x2192; This ensures that a numeric value falls between the range</li><li><code>IsDate()</code>&#xA0;&#x2192; This ensures that the value is a valid date</li><li><code>IsArray()</code>&#xA0;&#x2192; Validates that the value is an array</li><li><code>IsUrl()</code>&#xA0;&#x2192; Validate the value is a valid URL</li><li>Transform() &#x2192; Change the data into a different format</li></ul><h2 id="decorator-parameters">Decorator Parameters</h2><p>The&#xA0;<code>UserCreateDto</code>&#xA0;fields validator contains additional properties passed into it. These allow you to:</p><ul><li>Customize validation rules</li><li>Provide values</li><li>Set validation options</li><li>Provide messages when the validation fails etc.</li></ul><h1 id="validating-nested-objects">Validating Nested Objects</h1><p>Unlike normal fields validating nested objects requires a bit of extra processing, class-transformer together with class-validator allows you to validate nested objects.</p><p>We did a little bit of nested validation in&#xA0;<code>UserCreateDto</code>&#xA0;when we validated the photos field.</p><p>@IsArray()<br>@IsUrl({}, { each: true, message: &apos;Each photo must be a valid URL&apos; })<br>public readonly photos: string[];</p><p>Photos are an array of strings. To validate the nested strings, we added&#xA0;<code>ValidateNested()</code>&#xA0;and&#xA0;<code>{ each: true }</code>&#xA0;to ensure that, each link is a valid URL.</p><p>Let&#x2019;s update photos a some-what complex structure. create a new file in DTO folder and name it&#xA0;<code>user-photo.dto.ts</code></p><p>import { IsString, IsInt, Min, Max, IsUrl, Length } from &apos;class-validator&apos;;<br><br>export class UserPhotoDto {<br>  @IsString()<br>  @Length(2, 100, { message: &apos;Name must be between 2 and 100 characters&apos; })<br>  public readonly name: string;<br><br>  @IsInt()<br>  @Min(1, { message: &apos;Size must be at least 1 byte&apos; })<br>  @Max(5_000_000, { message: &apos;Size must not exceed 5MB&apos; })<br>  public readonly size: number;<br><br>  @IsUrl(<br>    { protocols: [&apos;http&apos;, &apos;https&apos;], require_protocol: true },<br>    { message: &apos;Invalid URL format&apos; },<br>  )<br>  public readonly url: string;<br>}</p><p>Now let&#x2019;s update the photos section of&#xA0;<code>UserCreateDto</code></p><p>export class UserCreateDto {<br>  // Other fields<br><br>  @IsArray()<br>  @ArrayNotEmpty({ message: &apos;Photos array should not be empty&apos; })<br>  @ValidateNested({ each: true })<br>  @Type(() =&gt; UserPhotoDto)<br>  public readonly photos: UserPhotoDto[];<br>}</p><p>The&#xA0;<code>ValidateNested()</code>&#xA0;decorator ensures that each element in the array is a valid photo object. The most important thing to be aware of when it comes to nested validation is that the nested object must be an instance of a class else&#xA0;<code>ValidateNested()</code>&#xA0;won&#x2019;t know the target class for validation. This is where class-transformer comes in.</p><h2 id="using-transform-and-type-from-class-transformer">Using Transform() and Type() from Class-transformer</h2><p><code>Class-transformer</code>&#xA0;provides us with the&#xA0;<code>@Type()</code>&#xA0;decorator. Since Typescript doesn&#x2019;t have good reflection capabilities yet, we use&#xA0;<code>@Type(() =&gt; UserPhotoDto)</code>&#xA0;to give an instance of the class.</p><p>We can also utilize the Type() decorator for basic data transformation in our DTO. The&#xA0;<code>dateOfBirth</code>&#xA0;field in&#xA0;<code>UserCreateDto</code>&#xA0;is transformed into a date object using&#xA0;<code>@Type(() =&gt; Date).</code></p><p>For complex DTO fields transformation, the&#xA0;<code>Tranform()</code>&#xA0;decorator handles this perfectly. It allows you to access both the field value and the entire object being validated. Whether you&#x2019;re converting data types, formatting strings, or applying custom logic,&#xA0;<code>@Transform()</code>&#xA0;gives you the control to return the exact version of the value that your application needs.</p><p>  @Transform(({ value, obj }) =&gt; {<br>    // perform additional transformation<br>    return value;<br>  })</p><h1 id="conditional-validation">Conditional Validation</h1><p>Most often, some fields need to be validated based on some business rules, we can use the&#xA0;<code>ValidateIf()</code>&#xA0;decorator, which allows you to apply validation to a field only if some condition is true. This is very useful if a field depends on other fields like multi-step forms.</p><p>Let&#x2019;s update the&#xA0;<code>UserPhotoDto</code>&#xA0;to include an optional&#xA0;<code>description</code>&#xA0;field, which should only be validated if it is provided. If the&#xA0;<code>description</code>&#xA0;is present, it should be a string with a length between 10 and 200 characters.</p><p>export class UserPhotoDto {<br>  // Other fields<br><br>  @ValidateIf((o) =&gt; o.description !== undefined)<br>  @IsString({ message: &apos;Description must be a string&apos; })<br>  @Length(10, 200, {<br>    message: &apos;Description must be between 10 and 200 characters&apos;,<br>  })<br>  public readonly description?: string;<br>}</p><h1 id="handling-validation-errors">Handling Validation Errors</h1><p>Before we dive into how NestJS handles validation errors, let&#x2019;s first create simple handlers in the&#xA0;<code>user.controller.ts</code>. We need a basic route to handle user creation.</p><p>import { Body, Controller, Post } from &apos;@nestjs/common&apos;;<br>import { UserCreateDto } from &apos;./dto/user-create.dto&apos;;<br><br>@Controller(&apos;users&apos;)<br>export class UsersController {<br>  @Post()<br>  createUser(@Body() userCreateDto: UserCreateDto) {<br>    // delegating the creation to a service<br>    return {<br>      message: &apos;User created successfully!&apos;,<br>      user: userCreateDto,<br>    };<br>  }<br>}</p><p>Trying this endpoint on Postman with no payload gives us a successful response.</p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:700/1*WlpYcKduxQlhsp3jEsocIw.png" class="kg-image" alt loading="lazy" width="700" height="200"></figure><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:700/1*d5_vobip1ftMXf2QmzXrzg.png" class="kg-image" alt loading="lazy" width="700" height="94"></figure><p>NestJS has a good integration with class-validator for data validation. Still, why wasn&#x2019;t our request validated? To tell NestJS that we want to validate&#xA0;<code>UserCreateDto</code>&#xA0;we have to supply a pipe to the&#xA0;<code>Body()</code>&#xA0;decorator.</p><h2 id="understanding-pipes">Understanding Pipes</h2><p>Pipes are flexible and powerful ways to transform and validate incoming data. Pipes are any class decorated with&#xA0;<code>Injectable()</code>&#xA0;and implement the&#xA0;<code>PipeTransform</code>&#xA0;interface. The usage of pipe we are interested is its ability to check that an incoming request meets a certain criteria or throw errors if otherwise.</p><p>The most common way to validate the&#xA0;<code>UserCreateDto</code>&#xA0;is to use the built-in&#xA0;<code>ValidationPipe</code>. This pipe validates rules in your DTO defined with class-validator</p><p>Now we pass a validation pipe to the&#xA0;<code>Body()</code>&#xA0;to validate the DTO</p><p>import { Body, Controller, Post, ValidationPipe } from &apos;@nestjs/common&apos;;<br>import { UserCreateDto } from &apos;./dto/user-create.dto&apos;;<br><br>@Controller(&apos;users&apos;)<br>export class UsersController {<br>  @Post()<br>  createUser(@Body(new ValidationPipe()) userCreateDto: UserCreateDto) {<br>    // delegating the creation to services<br>    return {<br>      message: &apos;User created successfully!&apos;,<br>      user: userCreateDto,<br>    };<br>  }<br>}</p><p>With this small change, we get the errors below if we try to create a user with no payload.</p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:700/1*Yth3lvUGPLy1aBGXbEpx5w.png" class="kg-image" alt loading="lazy" width="700" height="228"></figure><p>Awesome right :)</p><h2 id="setting-up-a-global-validation-pipe">Setting Up a Global Validation Pipe</h2><p>To ensure that all requests are validated across the entire application. We have to set up a global validation pipe so that we don&#x2019;t have to pass validation pipe to every&#xA0;<code>Body()</code>&#xA0;decorator.</p><p>Update&#xA0;<code>main.ts</code></p><p>import { NestFactory } from &apos;@nestjs/core&apos;;<br>import { AppModule } from &apos;./app.module&apos;;<br>import { ValidationPipe } from &apos;@nestjs/common&apos;;<br><br>async function bootstrap() {<br>  const app = await NestFactory.create(AppModule);<br>  app.useGlobalPipes(<br>    new ValidationPipe({<br>      whitelist: true,<br>      transform: true,<br>    }),<br>  );<br>  await app.listen(3000);<br>}<br><br>bootstrap();</p><p>The built-in validation pipe uses class-transformer and class-validator, we can pass validations options to be used by these underlying packages.<code>&#xA0;whitelist: true</code>&#xA0;automatically strips any properties that are not defined in the DTO<code>.transform: true</code>&#xA0;automatically transforms the payload into the appropriate types defined in your DTO.</p><p>ValidationPipe({<br>   whitelist: true,<br>   transform: true,<br>}),</p><p>With this, we can remove the pipe we passed to&#xA0;<code>createUser&#xA0;</code>endpoint and it will still be validated. Passing it to parameters helps us fine-tune the validation we need for specific endpoints.</p><p>@Post()<br>createUser(@Body() userCreateDto: UserCreateDto) {<br>  // ...<br>}</p><h2 id="formatting-validation-errors">Formatting Validation Errors</h2><p>The default validation errors format is not bad, we get to see all the errors for the validations that failed, Some frontend developers will scream at you though for mixing all the errors, I have been there&#x1F602;. Another reason to separate it is when you want to display errors under the fields that failed on the UI.</p><p>For nested objects, we also need to retrieve all the errors recursively for a smooth experience. We can achieve this by passing a custom&#xA0;<code>exceptionFactory</code>&#xA0;method to format the errors.</p><p>Update&#xA0;<code>main.ts</code></p><p>import { NestFactory } from &apos;@nestjs/core&apos;;<br>import { AppModule } from &apos;./app.module&apos;;<br>import {<br>  BadRequestException,<br>  ValidationError,<br>  ValidationPipe,<br>} from &apos;@nestjs/common&apos;;<br><br>async function bootstrap() {<br>  const app = await NestFactory.create(AppModule);<br>  app.useGlobalPipes(<br>    new ValidationPipe({<br>      transform: true,<br>      whitelist: true,<br>      exceptionFactory: (validationErrors: ValidationError[] = []) =&gt; {<br>        const getPrettyClassValidatorErrors = (<br>          validationErrors: ValidationError[],<br>          parentProperty = &apos;&apos;,<br>        ): Array&lt;{ property: string; errors: string[] }&gt; =&gt; {<br>          const errors = [];<br><br>          const getValidationErrorsRecursively = (<br>            validationErrors: ValidationError[],<br>            parentProperty = &apos;&apos;,<br>          ) =&gt; {<br>            for (const error of validationErrors) {<br>              const propertyPath = parentProperty<br>                ? `${parentProperty}.${error.property}`<br>                : error.property;<br><br>              if (error.constraints) {<br>                errors.push({<br>                  property: propertyPath,<br>                  errors: Object.values(error.constraints),<br>                });<br>              }<br><br>              if (error.children?.length) {<br>                getValidationErrorsRecursively(error.children, propertyPath);<br>              }<br>            }<br>          };<br><br>          getValidationErrorsRecursively(validationErrors, parentProperty);<br><br>          return errors;<br>        };<br><br>        const errors = getPrettyClassValidatorErrors(validationErrors);<br><br>        return new BadRequestException({<br>          message: &apos;validation error&apos;,<br>          errors: errors,<br>        });<br>      },<br>    }),<br>  );<br>  await app.listen(3000);<br>}<br><br>bootstrap();</p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:700/1*WXQdEguHnBB6WIjFm7PidQ.png" class="kg-image" alt loading="lazy" width="700" height="545"></figure><p>This looks way better. Hopefully, you don&#x2019;t go through what I went through with the front-end developers to get here &#x1F605;. Let&#x2019;s go through what is happening.</p><p>We passed an anonymous function to&#xA0;<code>exceptionFactory.</code>&#xA0;The functions accept the array of validation errors. Diving into the&#xA0;<code>validationError</code>&#xA0;interface.</p><p>export interface ValidationError {<br>    target?: Record&lt;string, any&gt;;<br>    property: string;<br>    value?: any;<br>    constraints?: {<br>        [type: string]: string;<br>    };<br>    children?: ValidationError[];<br>    contexts?: {<br>        [type: string]: any;<br>    };<br>}</p><p>For example, if we apply&#xA0;<code>IsEmail()</code>&#xA0;on a field and the provided value is not valid. A validation error is created. We also want to know the property where the error occurred. We need to keep in mind that, we can have nested objects for example the&#xA0;<code>photos</code>&#xA0;in&#xA0;<code>UserCreateDto</code>&#xA0;and therefore we can have a parent property let&#x2019;s say,&#xA0;<code>photos</code>&#xA0;where the error is with the&#xA0;<code>url</code>&#xA0;in the&#xA0;<code>UserPhotoDto.</code></p><p>We first declare an inner function, that takes the errors and sets the parent property to an empty string since it is the root field.</p><p>const getValidationErrorsRecursively = (<br>  validationErrors: ValidationError[],<br>  parentProperty = &apos;&apos;,<br>) =&gt; {<br><br>};</p><p>We then loop through the errors and get the property. For nested objects, I prefer to show the fields as&#xA0;<code>photos.0.url.&#xA0;</code>Where 0 is the index of the invalid photo in the array<code>.</code></p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:700/1*FxPw3axSWZvPUXeRK6WTgQ.png" class="kg-image" alt loading="lazy" width="700" height="399"></figure><p>The error messages are stored in the constraints field as it&#x2019;s in the&#xA0;<code>validationError</code>&#xA0;interface. We retrieve these errors and store them under a specific field.</p><p>if (error.constraints) {<br>  errors.push({<br>    property: propertyPath,<br>    errors: Object.values(error.constraints),<br>  });<br>}</p><p>For nested objects, the children property of a validation error contains an array of&#xA0;<code>validationError</code>&#xA0;for the nested objects. We can easily get the errors by recursively calling our function and passing the parent property.</p><p>if (error.children?.length) {<br>  getValidationErrorsRecursively(error.children, propertyPath);<br>}</p><h1 id="creating-custom-validators">Creating Custom Validators</h1><p>While Class-validator provides a comprehensive set of<a href="https://github.com/typestack/class-validator?tab=readme-ov-file&amp;ref=blog.avarile.com#validation-decorators" rel="noopener ugc nofollow"><u>&#xA0;</u>built-in validators</a>, there are times when your requirements exceed the standard validation rules or the standard validation doesn&#x2019;t fit what you want to do. Custom validators are useful when you need to enforce rules that aren&#x2019;t covered by the standard validators. Examples:</p><ul><li>We can create a custom validator to enforce a specific rule on what a valid password should be.</li><li>We can create another to ensure that the username is unique.</li></ul><p>To create a custom validator, we have to define a new class that implements the&#xA0;<code>ValidatorConstraintInterface</code>&#xA0;from&#xA0;<code>class-validator</code>. This requires us to implement two methods:</p><ul><li><code>validate</code>&#xA0;&#x2192; Contains your validation logic and must return a&#xA0;<code>boolean</code></li><li><code>defaultMessage</code>&#xA0;&#x2192; Optional default message to return when the validation fails.</li></ul><h2 id="custom-password-validator">Custom Password Validator</h2><p>Create a new folder in&#xA0;<code>users</code>&#xA0;module named&#xA0;<code>validators</code>. Create two files,&#xA0;<code>is-valid-password.validator.ts</code>&#xA0;and&#xA0;<code>is-username-unique.validator.ts</code>. It should look like this.</p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:631/1*KI527qFA3Wli-ycCTenaEg.png" class="kg-image" alt loading="lazy" width="631" height="195"></figure><p>A valid password in our use case is very simple. it should contains</p><ul><li>At least one uppercase letter.</li><li>At least one lowercase letter.</li><li>At least one symbol.</li><li>At least one number.</li><li>Password length should be more than 5 characters and less than 20 characters.</li></ul><p>Update&#xA0;<code>is-valid-password.validator.ts</code></p><p>import {<br>  ValidatorConstraint,<br>  ValidatorConstraintInterface,<br>  ValidationArguments,<br>} from &apos;class-validator&apos;;<br><br>@ValidatorConstraint({ name: &apos;IsStrongPassword&apos;, async: false })<br>export class IsValidPasswordConstraint implements ValidatorConstraintInterface {<br>  validate(password: string, args: ValidationArguments) {<br>    return (<br>      typeof password === &apos;string&apos; &amp;&amp;<br>      password.length &gt; 5 &amp;&amp;<br>      password.length &lt;= 20 &amp;&amp;<br>      /[A-Z]/.test(password) &amp;&amp;<br>      /[a-z]/.test(password) &amp;&amp;<br>      /[0&#x2013;9]/.test(password) &amp;&amp;<br>      /[!@#$%^&amp;*(),.?&quot;:{}|&lt;&gt;]/.test(password)<br>    );<br>  }<br><br>  defaultMessage(args: ValidationArguments) {<br>    return &apos;Password must be between 6 and 20 characters long and include at least one uppercase letter, one lowercase letter, one number, and one special character&apos;;<br>  }<br>}</p><p><code>IsValidPasswordContraint</code>&#xA0;is a custom validator because it is decorated with&#xA0;<code>ValidatorConstraint()</code>, we provide our custom validation rules in the validate method. If the validate function returns false, the error message in the&#xA0;<code>defaultMessage</code>&#xA0;will be returned. Providing these methods implements the&#xA0;<code>ValidatorContraintInterface</code>. To use&#xA0;<code>isValidPasswordContraint</code>, update the password field in&#xA0;<code>UserCreateDto</code>. For&#xA0;<code>ValidatorConstraint({ name: &#x2018;IsStrongPassword&#x2019;, async: false })</code>, we provided the constraint name that will be used to retrieve the error and also, since all actions in the validate are synchronous, we set&#xA0;<code>async</code>&#xA0;to&#xA0;<code>false</code>.</p><p>import { Validate } from &apos;class-validator&apos;;<br><br>export class UserCreateDto {<br>  // other fields<br><br>  @Validate(IsValidPasswordConstraint)<br>  public readonly password: string;<br>}</p><p>Now, if we try again with an invalid password, we get this result indicating our custom validator is working.</p><figure class="kg-card kg-image-card"><img src="https://miro.medium.com/v2/resize:fit:600/1*jdq3U9jgO9cgNoOYJ6EgYw.png" class="kg-image" alt loading="lazy" width="600" height="114"></figure><p>We can go further and create a decorator for the validator so that we can decorate the password field without using the&#xA0;<code>Validate</code>.</p><p>Update&#xA0;<code>is-valid-password.validator.ts</code></p><p>import {<br>  ValidatorConstraint,<br>  ValidatorConstraintInterface,<br>  ValidationArguments,<br>  registerDecorator,<br>  ValidatorOptions,<br>} from &apos;class-validator&apos;;<br><br>@ValidatorConstraint({ name: &apos;IsStrongPassword&apos;, async: false })<br>class IsValidPasswordConstraint implements ValidatorConstraintInterface {<br>  // removing the implementation so that we focus on IsPasswordValid function<br>}<br><br>export function IsValidPassword(validationOptions?: ValidatorOptions) {<br>  return function (object: NonNullable&lt;unknown&gt;, propertyName: string) {<br>    registerDecorator({<br>      target: object.constructor,<br>      propertyName: propertyName,<br>      options: validationOptions,<br>      constraints: [],<br>      validator: IsValidPasswordConstraint,<br>    });<br>  };<br>}</p><p>Creating custom decorators makes working with validators a breeze, NestJs gives us&#xA0;<code>registerDecorator</code>&#xA0;to create our own. we provide it with the validator which is the&#xA0;<code>IsValidPasswordContraint</code>&#xA0;we created. We can use it like this</p><p>export class UserCreateDto {<br>  // other fields  <br><br>  @IsValidPassword()<br>  public readonly password: string;<br>}</p><h2 id="asynchronous-custom-validator-with-custom-validation-options">Asynchronous Custom Validator With Custom Validation Options</h2><p>It is common to encounter scenarios where you need to validate against external systems. Let&#x2019;s assume that the username in&#xA0;<code>UserCreateDto</code>&#xA0;is unique across the various servers.</p><p>Update&#xA0;<code>is-unique-username.validator.ts</code></p><p>import {<br>  ValidatorConstraint,<br>  ValidatorConstraintInterface,<br>  ValidationArguments,<br>  registerDecorator,<br>  ValidationOptions,<br>} from &apos;class-validator&apos;;<br><br>interface IsUsernameUniqueOptions {<br>  server: string;<br>  message?: string;<br>}<br><br>@ValidatorConstraint({ name: &apos;IsUsernameUnique&apos;, async: true })<br>export class IsUsernameUniqueConstraint<br>  implements ValidatorConstraintInterface<br>{<br>  async validate(username: string, args: ValidationArguments) {<br>    const options = args.constraints[0] as IsUsernameUniqueOptions;<br>    const server = options.server;<br><br>    // server check, let assume username exist<br>    return !(await this.checkUsernameOnServer(username, server));<br>  }<br><br>  defaultMessage(args: ValidationArguments) {<br>    const options = args?.constraints[0] as IsUsernameUniqueOptions;<br>    return options?.message || &apos;Username is already taken&apos;;<br>  }<br><br>  async checkUsernameOnServer(username: string, server: string) {<br>    return true;<br>  }<br>}<br><br>export function IsUsernameUnique(<br>  options: IsUsernameUniqueOptions,<br>  validationOptions?: ValidationOptions,<br>) {<br>  return function (object: object, propertyName: string) {<br>    registerDecorator({<br>      target: object.constructor,<br>      propertyName: propertyName,<br>      options: validationOptions,<br>      constraints: [options],<br>      validator: IsUsernameUniqueConstraint,<br>    });<br>  };<br>}</p><p>Usage</p><p>export class UserCreateDto {<br>  @IsString()<br>  @Length(2, 30, { message: &apos;Name must be between 2 and 30 characters&apos; })<br>  @Transform(({ value }) =&gt; value.trim())<br>  @IsUsernameUnique({ server: &apos;east-1&apos;, message: &apos;Name already exists&apos; })<br>  public readonly name: string;<br><br>  // other fields<br>}</p><p>We created a simple interface to show the possible options we can pass to the decorator. These options are constraints that will be used by&#xA0;<code>IsUsernameUniqueConstraint</code>, we can get them through the validation arguments .&#xA0;<code>const options = args.constraints[0] as IsUsernameUniqueOptions;</code></p><p>Logging options give us&#xA0;<code>{ server: &#x2018;east-1&#x2019;, message: &#x2018;Name already exists&#x2019; }</code>, We then called the required service and passed the server name and username to validate the uniqueness of the name.</p><p>Also,&#xA0;<code>async</code>&#xA0;is set to&#xA0;<code>true</code>&#xA0;to allow asynchronous operations inside the validate function;&#xA0;<code>ValidatorConstraint({ name: &#x2018;IsUsernameUnique&#x2019;, async: true })</code>.</p><h1 id="common-pitfalls-and-best-practices">Common Pitfalls and Best Practices</h1><p>It is necessary to be aware of common pitfalls to ensure robust and maintainable code.</p><ul><li>Avoid direct use of entities. One common mistake is using entities directly. Entities are typically used for database interactions and may contain fields or relationships that shouldn&#x2019;t be exposed or validated on incoming requests.</li><li>Test Custom Validators Extensively. Validation logic is a critical part of your application&#x2019;s security and data integrity. Ensure they are well-tested.</li><li>Be Explicit with Error Messages. Provide error messages that are informative and user-friendly. It should communicate what the user should do to correct it.</li><li>Leverage Built-in and Custom Validators Together. Our&#xA0;<code>IsUniqueUsername</code>&#xA0;validator still uses&#xA0;<code>IsString()</code>&#xA0;on the name field. We don&#x2019;t have to reinvent everything if it is already available.</li></ul><h1 id="conclusion">Conclusion</h1><p>There is so much to add like validation groups, using service containers, etc, but this article is getting way longer than I anticipated &#x1F605;. As you continue developing with NestJS, I encourage you to explore more complex use cases and scenarios and share your experiences to keep the learning journey going.</p><p>Data validation is crucial in ensuring data integrity within any application and the principles covered here will serve as a strong foundation for further growth and mastery in building secure and efficient applications.</p><p>This is my very first article, and I&#x2019;m eager to hear your thoughts! &#x1F60A; Please feel free to leave any feedback in the comments.</p><p>If you&#x2019;d like to connect and stay updated on future content, you can find me on&#xA0;<a href="http://www.linkedin.com/in/ebenezer-ahurein?ref=blog.avarile.com" rel="noopener ugc nofollow">LinkedIn</a></p>]]></content:encoded></item><item><title><![CDATA[All useful design related websites]]></title><description><![CDATA[<p>readme generator: <a href="https://readme.so/editor?ref=blog.avarile.com">https://readme.so/editor</a></p><p>favicon generator: <a href="https://www.favicon-generator.org/?ref=blog.avarile.com">https://www.favicon-generator.org/</a></p><p>ascii banner generator: <a href="https://manytools.org/hacker-tools/ascii-banner/?ref=blog.avarile.com">https://manytools.org/hacker-tools/ascii-banner/</a></p>]]></description><link>https://blog.avarile.com/all-useful-design-related-websites/</link><guid isPermaLink="false">6805f606ba644e00011619ce</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Mon, 21 Apr 2025 07:49:19 GMT</pubDate><content:encoded><![CDATA[<p>readme generator: <a href="https://readme.so/editor?ref=blog.avarile.com">https://readme.so/editor</a></p><p>favicon generator: <a href="https://www.favicon-generator.org/?ref=blog.avarile.com">https://www.favicon-generator.org/</a></p><p>ascii banner generator: <a href="https://manytools.org/hacker-tools/ascii-banner/?ref=blog.avarile.com">https://manytools.org/hacker-tools/ascii-banner/</a></p>]]></content:encoded></item><item><title><![CDATA[Another API resource page]]></title><description><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://publicapis.dev/?ref=blog.avarile.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">A Collaborative List Of 1400+ Public APIs For Developers</div><div class="kg-bookmark-description">A collection of public APIs for developers, categorized and crowdsourced. Animals, books, cryptocurrencies, development, music, weather and much more.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://publicapis.dev/favicon-pa/apple-touch-icon.png" alt><span class="kg-bookmark-author">Public APIs</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://res.cloudinary.com/dev-resources/image/upload/q_auto,w_1200/v1655460684/media/thumbnail-pa_xxz0uy.png" alt></div></a></figure>]]></description><link>https://blog.avarile.com/another-api-resource-page/</link><guid isPermaLink="false">65d14bc3ea4e4f0001a25d39</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Sun, 18 Feb 2024 00:14:01 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://publicapis.dev/?ref=blog.avarile.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">A Collaborative List Of 1400+ Public APIs For Developers</div><div class="kg-bookmark-description">A collection of public APIs for developers, categorized and crowdsourced. Animals, books, cryptocurrencies, development, music, weather and much more.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://publicapis.dev/favicon-pa/apple-touch-icon.png" alt><span class="kg-bookmark-author">Public APIs</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://res.cloudinary.com/dev-resources/image/upload/q_auto,w_1200/v1655460684/media/thumbnail-pa_xxz0uy.png" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Public APIs]]></title><description><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/public-apis/public-apis?ref=blog.avarile.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - public-apis/public-apis: A collective list of free APIs</div><div class="kg-bookmark-description">A collective list of free APIs. Contribute to public-apis/public-apis development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">public-apis</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://repository-images.githubusercontent.com/54346799/e5ee272c-dfe1-40e5-b66b-b0a36e815254" alt></div></a></figure><p>Introduction:<br>In the dynamic realm of technology, Application Programming Interfaces (APIs) play a pivotal role in connecting various software systems, enabling</p>]]></description><link>https://blog.avarile.com/untitled/</link><guid isPermaLink="false">65d14aa6ea4e4f0001a25d2a</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Sun, 18 Feb 2024 00:10:54 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/public-apis/public-apis?ref=blog.avarile.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - public-apis/public-apis: A collective list of free APIs</div><div class="kg-bookmark-description">A collective list of free APIs. Contribute to public-apis/public-apis development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">public-apis</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://repository-images.githubusercontent.com/54346799/e5ee272c-dfe1-40e5-b66b-b0a36e815254" alt></div></a></figure><p>Introduction:<br>In the dynamic realm of technology, Application Programming Interfaces (APIs) play a pivotal role in connecting various software systems, enabling them to communicate and share data seamlessly. While there are countless APIs available, the focus of this blog is on the fascinating world of free open source APIs &#x2013; the digital building blocks that empower developers to create innovative applications without breaking the bank.</p><p>What are Free Open Source APIs?<br>Free open source APIs are software interfaces that are not only accessible without cost but also come with the added benefit of being open source. This means that the source code is available for anyone to view, modify, and distribute. These APIs adhere to the principles of collaboration and transparency, fostering a community-driven approach to development.</p><p>Advantages of Free Open Source APIs:</p><ol><li><strong>Cost-Efficiency:</strong><ul><li>One of the primary advantages of using free open source APIs is the elimination of licensing fees. Developers can leverage these APIs without worrying about financial constraints, making them an attractive choice for individuals, startups, and even larger organizations looking to reduce expenses.</li></ul></li><li><strong>Customization and Flexibility:</strong><ul><li>With access to the source code, developers can customize and tailor the functionality of the API to suit their specific needs. This flexibility empowers developers to create unique solutions that align perfectly with their project requirements.</li></ul></li><li><strong>Community Support:</strong><ul><li>The open source community is known for its collaborative spirit. Free open source APIs often have an active community of developers who contribute to ongoing improvements, troubleshoot issues, and share knowledge. This collective effort results in robust and reliable APIs.</li></ul></li><li><strong>Security and Trust:</strong><ul><li>Open source APIs are subject to peer review, which enhances their security. The transparency of the source code allows developers to scrutinize the implementation for vulnerabilities, contributing to a more secure overall ecosystem. Trust is built through transparency and collaboration.</li></ul></li></ol><p>Popular Free Open Source APIs:</p><ol><li><strong>OpenWeatherMap API:</strong><ul><li>Access real-time weather data for any location on Earth. This API is widely used in applications ranging from mobile weather apps to smart home systems.</li></ul></li><li><strong>OpenStreetMap API:</strong><ul><li>Harness the power of crowd-sourced mapping data with OpenStreetMap API. Developers can integrate maps, geocoding, and routing features into their applications.</li></ul></li><li><strong>GitHub REST API:</strong><ul><li>GitHub&apos;s API allows developers to interact with repositories, issues, and other GitHub features programmatically. This is invaluable for automating workflows and integrating GitHub functionalities into custom tools.</li></ul></li><li><strong>REST Countries API:</strong><ul><li>Retrieve information about countries, including details such as currency, population, and time zones. This API is a valuable resource for applications requiring country-specific data.</li></ul></li></ol><p>Conclusion:<br>Free open source APIs are the unsung heroes of the digital age, democratizing access to powerful tools and fostering a collaborative environment for innovation. As developers continue to explore and contribute to these open source projects, the possibilities for creating impactful and cost-effective applications are truly boundless. Embrace the world of free open source APIs, and unlock the potential for transformative and inclusive technological solutions.</p>]]></content:encoded></item><item><title><![CDATA[A Fresh new Start]]></title><description><![CDATA[<p>&#x8FC8;&#x51FA;&#x4E86;&#x575A;&#x5B9E;&#x7684;&#x7B2C;&#x4E00;&#x6B65;...</p>]]></description><link>https://blog.avarile.com/a-fresh-new-start/</link><guid isPermaLink="false">65d0ab7119383d000160c223</guid><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Sat, 17 Feb 2024 12:50:44 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1682686578615-39549501dd08?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wxfDF8YWxsfDF8fHx8fHwyfHwxNzA4MTczMTUwfA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1682686578615-39549501dd08?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wxfDF8YWxsfDF8fHx8fHwyfHwxNzA4MTczMTUwfA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="A Fresh new Start"><p>&#x8FC8;&#x51FA;&#x4E86;&#x575A;&#x5B9E;&#x7684;&#x7B2C;&#x4E00;&#x6B65;...</p>]]></content:encoded></item><item><title><![CDATA[Coming soon]]></title><description><![CDATA[<p>This is Avarile&apos;s AI Hub, a brand new site by Avarile Wang that&apos;s just getting started. Things will be up and running here shortly, but you can <a href="#/portal/">subscribe</a> in the meantime if you&apos;d like to stay up to date and receive emails when new</p>]]></description><link>https://blog.avarile.com/coming-soon/</link><guid isPermaLink="false">65d0929f19383d000160c017</guid><category><![CDATA[News]]></category><dc:creator><![CDATA[Avarile Wang]]></dc:creator><pubDate>Sat, 17 Feb 2024 11:03:59 GMT</pubDate><media:content url="https://static.ghost.org/v4.0.0/images/feature-image.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://static.ghost.org/v4.0.0/images/feature-image.jpg" alt="Coming soon"><p>This is Avarile&apos;s AI Hub, a brand new site by Avarile Wang that&apos;s just getting started. Things will be up and running here shortly, but you can <a href="#/portal/">subscribe</a> in the meantime if you&apos;d like to stay up to date and receive emails when new content is published!</p>]]></content:encoded></item></channel></rss>