<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Wassim Chegham</title>
    <description>The latest articles on DEV Community by Wassim Chegham (@wassimchegham).</description>
    <link>https://dev.to/wassimchegham</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F13081%2F0a029e3e-206b-41b5-83b3-52e39a29c4cb.jpg</url>
      <title>DEV Community: Wassim Chegham</title>
      <link>https://dev.to/wassimchegham</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wassimchegham"/>
    <language>en</language>
    <item>
      <title>Prompt Stuffing Is Killing Your Agent</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Mon, 30 Mar 2026 15:49:49 +0000</pubDate>
      <link>https://dev.to/wassimchegham/agentic-rag-done-right-4846</link>
      <guid>https://dev.to/wassimchegham/agentic-rag-done-right-4846</guid>
      <description>&lt;p&gt;Classic RAG is like packing your entier wardrobe for a weekend trip. Sure, you'll have options, but good luck finding what you need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/wassimchegham/why-your-ai-agent-demo-falls-apart-in-production-1320"&gt;In Part 1&lt;/a&gt;, we talked about why agents fall apart in production: compounding errors, the reliability tax, the gap between demo magic and real-world chaos. Now let's zoom into one of the biggest culprits — how most agents handle retrieval.&lt;/p&gt;

&lt;p&gt;Because classic RAG has a mantra: &lt;strong&gt;"We always retrieve context."&lt;/strong&gt; And that's exactly where the problems start.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Retrieve Everything, Hope for the Best
&lt;/h2&gt;

&lt;p&gt;Let's go back to our running example: a travel-planning agent. A user asks for a 4-day trip with hiking, a modest budget, and one fancy dinner. Reasonable request. Here's what classic RAG does with it:&lt;/p&gt;

&lt;p&gt;It grabs &lt;em&gt;everything&lt;/em&gt;. Weather data. Hotel options. Flight details. Restaurant suggestions. Trail maps. Local events. Currency exchange rates. It crams all of that into a single prompt and says, "Hey model, figure it out."&lt;/p&gt;

&lt;p&gt;This is fragile for reasons that should be obvous, but let's spell them out anyway:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model has to reason across too many dimensions at once.&lt;/strong&gt; Flights, budget constraints, hiking trail difficulty, restaurant dress codes, weather windows, all competing for attention in one context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints get missed.&lt;/strong&gt; When you stuff a 6,000-token context blob into a prompt, the model has to juggle everything simultaneously. Your budget limit? Buried somewhere between the hotel listings and the weather forecast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It breaks as complexity grows.&lt;/strong&gt; A simple "book me a flight" query works fine. A multi-day, multi-constraint trip plan? The prompt becomes a minefield.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the uncomfortable truth that a lot of RAG tutorials gloss over:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;More context ≠ better answers.&lt;/strong&gt; It means higher cost, slower responses, and more room for the model to get confused.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You're paying more tokens to get worse results. That's not a tradeoff — that's a bug in your architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBMUlxuICAgIHN1YmdyYXBoIGNsYXNzaWNbXCIgQ2xhc3NpYyBSQUdcIl1cbiAgICAgICAgZGlyZWN0aW9uIFRCXG4gICAgICAgIEExW1VzZXIgYXNrcyBmb3IgdHJpcCBwbGFuXSAtLT4gQTJbUmV0cmlldmUgQUxMIGNvbnRleHRdXG4gICAgICAgIEEyIC0tPiBBM1tcIkZsaWdodHMgKyBIb3RlbHMgKyBXZWF0aGVyPGJyLz4rIFJlc3RhdXJhbnRzICsgVHJhaWxzXCJdXG4gICAgICAgIEEzIC0tPiBBNFtTdHVmZiBpbnRvIG9uZSBnaWFudCBwcm9tcHRdXG4gICAgICAgIEE0IC0tPiBBNVtcIkhvcGUgdGhlIG1vZGVsPGJyLz5maWd1cmVzIGl0IG91dCBcIl1cbiAgICBlbmRcblxuICAgIHN1YmdyYXBoIGFnZW50aWNbXCIgQWdlbnRpYyBSQUdcIl1cbiAgICAgICAgZGlyZWN0aW9uIFRCXG4gICAgICAgIEIxW1VzZXIgYXNrcyBmb3IgdHJpcCBwbGFuXSAtLT4gQjJbQWdlbnQgcmVhc29ucyBhYm91dDxici8-d2hhdCBpdCBuZWVkcyBmaXJzdF1cbiAgICAgICAgQjIgLS0-IEIzW1JldHJpZXZlIGRlc3RpbmF0aW9uIGluZm9dXG4gICAgICAgIEIzIC0tPiBCNFtWYWxpZGF0ZSBjb25zdHJhaW50c11cbiAgICAgICAgQjQgLS0-IEI1W1JldHJpZXZlIGZsaWdodHNdXG4gICAgICAgIEI1IC0tPiBCNltWYWxpZGF0ZSBidWRnZXRdXG4gICAgICAgIEI2IC0tPiBCN1tSZXRyaWV2ZSBob3RlbHNdXG4gICAgICAgIEI3IC0tPiBCOFtWYWxpZGF0ZSBhdmFpbGFiaWxpdHldXG4gICAgICAgIEI4IC0tPiBCOVtQbGFuIGFjdGl2aXRpZXMgKyByZXN0YXVyYW50c11cbiAgICAgICAgQjkgLS0-IEIxMFtDb21waWxlIGZpbmFsIGl0aW5lcmFyeV1cbiAgICBlbmQiLCAibWVybWFpZCI6IHsidGhlbWUiOiAiZGVmYXVsdCJ9fQ%3D%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBMUlxuICAgIHN1YmdyYXBoIGNsYXNzaWNbXCIgQ2xhc3NpYyBSQUdcIl1cbiAgICAgICAgZGlyZWN0aW9uIFRCXG4gICAgICAgIEExW1VzZXIgYXNrcyBmb3IgdHJpcCBwbGFuXSAtLT4gQTJbUmV0cmlldmUgQUxMIGNvbnRleHRdXG4gICAgICAgIEEyIC0tPiBBM1tcIkZsaWdodHMgKyBIb3RlbHMgKyBXZWF0aGVyPGJyLz4rIFJlc3RhdXJhbnRzICsgVHJhaWxzXCJdXG4gICAgICAgIEEzIC0tPiBBNFtTdHVmZiBpbnRvIG9uZSBnaWFudCBwcm9tcHRdXG4gICAgICAgIEE0IC0tPiBBNVtcIkhvcGUgdGhlIG1vZGVsPGJyLz5maWd1cmVzIGl0IG91dCBcIl1cbiAgICBlbmRcblxuICAgIHN1YmdyYXBoIGFnZW50aWNbXCIgQWdlbnRpYyBSQUdcIl1cbiAgICAgICAgZGlyZWN0aW9uIFRCXG4gICAgICAgIEIxW1VzZXIgYXNrcyBmb3IgdHJpcCBwbGFuXSAtLT4gQjJbQWdlbnQgcmVhc29ucyBhYm91dDxici8-d2hhdCBpdCBuZWVkcyBmaXJzdF1cbiAgICAgICAgQjIgLS0-IEIzW1JldHJpZXZlIGRlc3RpbmF0aW9uIGluZm9dXG4gICAgICAgIEIzIC0tPiBCNFtWYWxpZGF0ZSBjb25zdHJhaW50c11cbiAgICAgICAgQjQgLS0-IEI1W1JldHJpZXZlIGZsaWdodHNdXG4gICAgICAgIEI1IC0tPiBCNltWYWxpZGF0ZSBidWRnZXRdXG4gICAgICAgIEI2IC0tPiBCN1tSZXRyaWV2ZSBob3RlbHNdXG4gICAgICAgIEI3IC0tPiBCOFtWYWxpZGF0ZSBhdmFpbGFiaWxpdHldXG4gICAgICAgIEI4IC0tPiBCOVtQbGFuIGFjdGl2aXRpZXMgKyByZXN0YXVyYW50c11cbiAgICAgICAgQjkgLS0-IEIxMFtDb21waWxlIGZpbmFsIGl0aW5lcmFyeV1cbiAgICBlbmQiLCAibWVybWFpZCI6IHsidGhlbWUiOiAiZGVmYXVsdCJ9fQ%3D%3D" alt="Classic RAG vs Agentic RAG comparison" width="342" height="2073"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at the left side. That's a prayer, not a pipeline. Now look at the right side. That's engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Agentic RAG or Conditional Retrieval
&lt;/h2&gt;

&lt;p&gt;Agentic RAG flips the model. Instead of "always retrieve," it uses &lt;strong&gt;conditional retrieval&lt;/strong&gt;. The agent fetches information only when it actually needs it, validates what it got, and only then moves on.&lt;/p&gt;

&lt;p&gt;The key insight is simple: &lt;strong&gt;retrieval should be a decision, not a reflex.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what that looks like for our travel agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user asks for a 4-day hiking trip on a budget with one fancy dinner.&lt;/li&gt;
&lt;li&gt;The agent doesn't immediately fire off six API calls. It &lt;em&gt;thinks&lt;/em&gt; first: "What do I need to know before I can even start planning?"&lt;/li&gt;
&lt;li&gt;It retrieves destination info: where can you hike for 4 days that fits the budget?&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;validates&lt;/strong&gt; that against the constraints. Are there actually trails there? Is it the right season?&lt;/li&gt;
&lt;li&gt;Only then does it retrieve flight options. And it checks: does this fit the budget?&lt;/li&gt;
&lt;li&gt;Then hotels. Then activities. Each step, validated before moving on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the "conditional retrieval + validation loop" pattern, and it removes a &lt;strong&gt;huge&lt;/strong&gt; class of production bugs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBURFxuICAgIFN0YXJ0KFtVc2VyIFJlcXVlc3RdKSAtLT4gUmVhc29uW0FnZW50IHJlYXNvbnM6PGJyLz5XaGF0IGRvIEkgbmVlZD9dXG4gICAgUmVhc29uIC0tPiBEZWNpc2lvbntEbyBJIG5lZWQgdG88YnIvPnJldHJpZXZlIHNvbWV0aGluZz99XG5cbiAgICBEZWNpc2lvbiAtLSBcIk5vOiBhbHJlYWR5IGhhdmU8YnIvPmVub3VnaCBjb250ZXh0XCIgLS0-IEFjdFtUYWtlIGFjdGlvbiBvcjxici8-cmVzcG9uZCBkaXJlY3RseV1cbiAgICBEZWNpc2lvbiAtLSBcIlllc1wiIC0tPiBXaGF0W0RldGVybWluZSB3aGF0PGJyLz50byByZXRyaWV2ZV1cblxuICAgIFdoYXQgLS0-IFJldHJpZXZlW1JldHJpZXZlIHNwZWNpZmljPGJyLz5kYXRhIHNvdXJjZV1cbiAgICBSZXRyaWV2ZSAtLT4gVmFsaWRhdGV7VmFsaWRhdGUgYWdhaW5zdDxici8-Y29uc3RyYWludHN9XG5cbiAgICBWYWxpZGF0ZSAtLSBcIlZhbGlkIFwiIC0tPiBFbm91Z2h7SGF2ZSBldmVyeXRoaW5nPGJyLz5JIG5lZWQ_fVxuICAgIFZhbGlkYXRlIC0tIFwiSW52YWxpZCBcIiAtLT4gQWRqdXN0W0FkanVzdCBxdWVyeTxici8-b3IgcGFyYW1ldGVyc11cbiAgICBBZGp1c3QgLS0-IFJldHJpZXZlXG5cbiAgICBFbm91Z2ggLS0gXCJOb1wiIC0tPiBSZWFzb25cbiAgICBFbm91Z2ggLS0gXCJZZXNcIiAtLT4gQWN0XG5cbiAgICBBY3QgLS0-IERvbmUoW0RlbGl2ZXIgUmVzdWx0XSkiLCAibWVybWFpZCI6IHsidGhlbWUiOiAiZGVmYXVsdCJ9fQ%3D%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBURFxuICAgIFN0YXJ0KFtVc2VyIFJlcXVlc3RdKSAtLT4gUmVhc29uW0FnZW50IHJlYXNvbnM6PGJyLz5XaGF0IGRvIEkgbmVlZD9dXG4gICAgUmVhc29uIC0tPiBEZWNpc2lvbntEbyBJIG5lZWQgdG88YnIvPnJldHJpZXZlIHNvbWV0aGluZz99XG5cbiAgICBEZWNpc2lvbiAtLSBcIk5vOiBhbHJlYWR5IGhhdmU8YnIvPmVub3VnaCBjb250ZXh0XCIgLS0-IEFjdFtUYWtlIGFjdGlvbiBvcjxici8-cmVzcG9uZCBkaXJlY3RseV1cbiAgICBEZWNpc2lvbiAtLSBcIlllc1wiIC0tPiBXaGF0W0RldGVybWluZSB3aGF0PGJyLz50byByZXRyaWV2ZV1cblxuICAgIFdoYXQgLS0-IFJldHJpZXZlW1JldHJpZXZlIHNwZWNpZmljPGJyLz5kYXRhIHNvdXJjZV1cbiAgICBSZXRyaWV2ZSAtLT4gVmFsaWRhdGV7VmFsaWRhdGUgYWdhaW5zdDxici8-Y29uc3RyYWludHN9XG5cbiAgICBWYWxpZGF0ZSAtLSBcIlZhbGlkIFwiIC0tPiBFbm91Z2h7SGF2ZSBldmVyeXRoaW5nPGJyLz5JIG5lZWQ_fVxuICAgIFZhbGlkYXRlIC0tIFwiSW52YWxpZCBcIiAtLT4gQWRqdXN0W0FkanVzdCBxdWVyeTxici8-b3IgcGFyYW1ldGVyc11cbiAgICBBZGp1c3QgLS0-IFJldHJpZXZlXG5cbiAgICBFbm91Z2ggLS0gXCJOb1wiIC0tPiBSZWFzb25cbiAgICBFbm91Z2ggLS0gXCJZZXNcIiAtLT4gQWN0XG5cbiAgICBBY3QgLS0-IERvbmUoW0RlbGl2ZXIgUmVzdWx0XSkiLCAibWVybWFpZCI6IHsidGhlbWUiOiAiZGVmYXVsdCJ9fQ%3D%3D" alt="Conditional retrieval and validation loop" width="596" height="1553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the loops. The agent isn't just a straight pipeline — it pauses, checks constraints, and only then decides what to do next. Classic RAG has no loops. It's a one-shot gamble. Agentic RAG is iterative and self-correcting.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Validation Loop in Practice
&lt;/h3&gt;

&lt;p&gt;Let's make this concrete. Say the agent is looking for hotels for our hiking trip:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBURFxuICAgIFJbUmV0cmlldmUgaG90ZWwgb3B0aW9uczxici8-Zm9yIGRlc3RpbmF0aW9uXSAtLT4gQzF7V2l0aGluIGJ1ZGdldD88YnIvPlx1MjI2NCAkMTUwL25pZ2h0fVxuXG4gICAgQzEgLS0gXCJZZXMgXCIgLS0-IEMye0F2YWlsYWJsZSBmb3I8YnIvPmFsbCA0IG5pZ2h0cz99XG4gICAgQzEgLS0gXCJObyBcIiAtLT4gQURKMVtBZGp1c3Q6IHdpZGVuIHNlYXJjaCByYWRpdXM8YnIvPm9yIGxvd2VyIHN0YXIgcmF0aW5nXVxuICAgIEFESjEgLS0-IFJcblxuICAgIEMyIC0tIFwiWWVzIFwiIC0tPiBDM3tOZWFyIGhpa2luZyB0cmFpbHM8YnIvPm9yIHRyYW5zcG9ydD99XG4gICAgQzIgLS0gXCJObyBcIiAtLT4gQURKMltBZGp1c3Q6IHNoaWZ0IGRhdGVzPGJyLz5vciB0cnkgbmVhcmJ5IGFyZWFdXG4gICAgQURKMiAtLT4gUlxuXG4gICAgQzMgLS0gXCJZZXMgXCIgLS0-IFBBU1NbIEhvdGVsIHZhbGlkYXRlZDxici8-UHJvY2VlZCB0byBuZXh0IHN0ZXBdXG4gICAgQzMgLS0gXCJObyBcIiAtLT4gQURKM1tBZGp1c3Q6IHByaW9yaXRpemU8YnIvPmxvY2F0aW9uIG92ZXIgcHJpY2VdXG4gICAgQURKMyAtLT4gUiIsICJtZXJtYWlkIjogeyJ0aGVtZSI6ICJkZWZhdWx0In19" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBURFxuICAgIFJbUmV0cmlldmUgaG90ZWwgb3B0aW9uczxici8-Zm9yIGRlc3RpbmF0aW9uXSAtLT4gQzF7V2l0aGluIGJ1ZGdldD88YnIvPlx1MjI2NCAkMTUwL25pZ2h0fVxuXG4gICAgQzEgLS0gXCJZZXMgXCIgLS0-IEMye0F2YWlsYWJsZSBmb3I8YnIvPmFsbCA0IG5pZ2h0cz99XG4gICAgQzEgLS0gXCJObyBcIiAtLT4gQURKMVtBZGp1c3Q6IHdpZGVuIHNlYXJjaCByYWRpdXM8YnIvPm9yIGxvd2VyIHN0YXIgcmF0aW5nXVxuICAgIEFESjEgLS0-IFJcblxuICAgIEMyIC0tIFwiWWVzIFwiIC0tPiBDM3tOZWFyIGhpa2luZyB0cmFpbHM8YnIvPm9yIHRyYW5zcG9ydD99XG4gICAgQzIgLS0gXCJObyBcIiAtLT4gQURKMltBZGp1c3Q6IHNoaWZ0IGRhdGVzPGJyLz5vciB0cnkgbmVhcmJ5IGFyZWFdXG4gICAgQURKMiAtLT4gUlxuXG4gICAgQzMgLS0gXCJZZXMgXCIgLS0-IFBBU1NbIEhvdGVsIHZhbGlkYXRlZDxici8-UHJvY2VlZCB0byBuZXh0IHN0ZXBdXG4gICAgQzMgLS0gXCJObyBcIiAtLT4gQURKM1tBZGp1c3Q6IHByaW9yaXRpemU8YnIvPmxvY2F0aW9uIG92ZXIgcHJpY2VdXG4gICAgQURKMyAtLT4gUiIsICJtZXJtYWlkIjogeyJ0aGVtZSI6ICJkZWZhdWx0In19" alt="Hotel validation loop in practice" width="740" height="992"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each retrieval gets validated against specific constraints — budget, availability, location — before the agent moves on. If validation fails, the agent adjusts and re-retrieves. No silent failures. No hallucinated hotel that doesn't actually exist at that price.&lt;/p&gt;

&lt;p&gt;Compare this to classic RAG, where the model gets a list of 20 hotels in one context dump and picks one that &lt;em&gt;looks&lt;/em&gt; right. Maybe it's in budget. Maybe it's not. You won't know until the user tries to book it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost Case for Conditional Retrieval
&lt;/h2&gt;

&lt;p&gt;Here's the part that makes your finance team happy: Agentic RAG is &lt;strong&gt;cheaper&lt;/strong&gt; to run.&lt;/p&gt;

&lt;p&gt;This seems counterintuitive. You're doing more steps — reason, retrieve, validate, repeat. But here's why it's actually cheaper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fewer tokens per request.&lt;/strong&gt; You retrieve only the data you need for the current step, not the entire knowledge base dump. A focused hotel query is 200 tokens of context. The "everything at once" approach can easily be 4,000+.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer tool calls overall.&lt;/strong&gt; Conditional retrieval means you skip irrelevant sources. If the user's destination is already decided, you don't waste a call retrieving "top destinations for hiking."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer retries.&lt;/strong&gt; When the model gets confused by too much context, it gives bad answers. Bad answers trigger retries, clarifications, follow-up calls. Clean context → right answer the first time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's the piece that most tutorials miss: &lt;strong&gt;budgets are part of agent state.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're running agents in production, you need to track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token usage per step and per session&lt;/li&gt;
&lt;li&gt;Number of tool calls&lt;/li&gt;
&lt;li&gt;Retry counts&lt;/li&gt;
&lt;li&gt;Total execution time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your supervisor loop (the thing orchestrating the agent's steps) should enforce limits. If the token budget is hit, the agent should stop, summarize what it has so far, or ask the user for confirmation before continuing.&lt;/p&gt;

&lt;p&gt;Think about it this way: &lt;strong&gt;we don't keep searching hotels forever just to find a $2 cheaper option.&lt;/strong&gt; At some point, the cost of searching exceeds the savings. A well-designed agent knows when to stop.&lt;/p&gt;

&lt;p&gt;This is where the "agentic" part really matters. A classic RAG pipeline has no concept of cost awareness, it retrieves, it stuffs, it's done. An agentic system can reason about whether the next retrieval is worth the cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters in Production
&lt;/h2&gt;

&lt;p&gt;In a demo, classic RAG works fine. The inputs are controlled. The context is small. The constraints are simple. You show it on stage, everyone claps, you ship it.&lt;/p&gt;

&lt;p&gt;Then production happens.&lt;/p&gt;

&lt;p&gt;Real users have complex, multi-constraint requests. The context grows. The prompt gets bloated. The model starts missing things. You add more retrieval to "fix" it, which makes the prompt bigger, which makes the model miss more things. It's a death spiral.&lt;/p&gt;

&lt;p&gt;Agentic RAG breaks this cycle because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Each step is scoped.&lt;/strong&gt; The model reasons about one thing at a time with only the context it needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation catches errors early.&lt;/strong&gt; A constraint violation at step 3 gets caught at step 3, not discovered when the user sees the final output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent is cost-aware.&lt;/strong&gt; It doesn't burn through your API budget retrieving data it doesn't need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It scales with complexity.&lt;/strong&gt; Adding a new constraint (e.g., "must be wheelchair accessible") means adding a validation check, not restructuring the entire prompt.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;If you're building agents that use retrieval (and most agents do) here's your checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Make retrieval conditional, not automatic.&lt;/strong&gt; The agent should decide whether to retrieve, not just retrieve by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate after every retrieval step.&lt;/strong&gt; Check the results against your constraints before moving on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope your context.&lt;/strong&gt; Each step should get only the data it needs — not the full knowledge base.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track your costs as state.&lt;/strong&gt; Token usage, tool calls, retries, and execution time should be first-class values in your agent's state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce limits in your supervisor loop.&lt;/strong&gt; Set budgets and let the agent know when to stop searching and start deciding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design for re-retrieval.&lt;/strong&gt; When validation fails, the agent should be able to adjust parameters and try again, not crash or hallucinate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a deeper dive into advanced Agentic RAG patterns, check out &lt;a href="https://developer.microsoft.com/reactor/events/26775/" rel="noopener noreferrer"&gt;Pamela Fox's session on the topic&lt;/a&gt; — it's an excellent companion to what we've covered here.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Are you using classic RAG or agentic RAG in your projects? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>agents</category>
      <category>llm</category>
    </item>
    <item>
      <title>Why Your AI Agent Demo Falls Apart in Production</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Fri, 20 Mar 2026 15:49:47 +0000</pubDate>
      <link>https://dev.to/wassimchegham/why-your-ai-agent-demo-falls-apart-in-production-1320</link>
      <guid>https://dev.to/wassimchegham/why-your-ai-agent-demo-falls-apart-in-production-1320</guid>
      <description>&lt;p&gt;Your agent demo crushed it on stage. The audience clapped. Your PM high-fived you. The travel-planning agent nailed it — a 4-day hiking trip, budget-friendly, one fancy dinner on night three. Beautiful.&lt;/p&gt;

&lt;p&gt;Then you deployed it and… it fell apart.&lt;/p&gt;

&lt;p&gt;Not dramatically. Not all at once. It just started doing &lt;em&gt;weird&lt;/em&gt; things. Booking a hotel in Paris, then recommending a restaurant in London. Picking a "budget" flight that cost $1,200. Suggesting a hiking trail that's been closed since 2019. Death by a thousand paper cuts.&lt;/p&gt;

&lt;p&gt;If this sounds familiar, you're not alone. And the problem isn't your model, your prompt, or your vibes. It's math.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Step Agents Are Distributed Systems (Whether You Like It or Not)
&lt;/h2&gt;

&lt;p&gt;Here's the thing nobody tells you when you're building that first agent prototype: a multi-step AI agent is a distributed system. Every tool call is a network request that can fail, time out, or return garbage. Every reasoning step is a non-deterministic decision that might go sideways.&lt;/p&gt;

&lt;p&gt;Your travel agent doesn't just "plan a trip." It orchestrates a chain of operations: search flights, check hotel availability, look up hiking trails, find restaurants, cross-reference budgets, verify dates. Each step depends on the last. Each step can break.&lt;/p&gt;

&lt;p&gt;We've been building distributed systems for decades. We know they're hard. But somehow, when we slap "AI" on it, we forget everything we learned and expect magic.&lt;/p&gt;

&lt;p&gt;Let's stop doing that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 Failure Modes of Multi-Step Agents
&lt;/h2&gt;

&lt;p&gt;I've seen agents fail in production in roughly five ways. Every. Single. Time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBURFxuICAgIEFbXCJcdWQ4M2VcdWRkMTYgTXVsdGktU3RlcCBBZ2VudFwiXSAtLT4gQltcIlx1Mjc0YyBXcm9uZyBUb29sIFNlbGVjdGlvblwiXVxuICAgIEEgLS0-IENbXCJcdTIzZjFcdWZlMGYgQVBJIFRpbWVvdXRzXCJdXG4gICAgQSAtLT4gRFtcIlx1MjZhMFx1ZmUwZiBQYXJ0aWFsIEZhaWx1cmVzXCJdXG4gICAgQSAtLT4gRVtcIlx1ZDgzZFx1ZGQwMCBJbmNvbnNpc3RlbnQgU3RhdGVcIl1cbiAgICBBIC0tPiBGW1wiXHVkODNkXHVkY2E1IENvbXBvdW5kaW5nIEZhaWx1cmVzXCJdXG5cbiAgICBCIC0tPiBCMVtcIkFnZW50IHBpY2tzIGhvdGVsIGJvb2tpbmc8YnIvPnRvb2wgdG8gZmluZCBoaWtpbmcgdHJhaWxzXCJdXG4gICAgQyAtLT4gQzFbXCJGbGlnaHQgQVBJIGhhbmdzIGZvciAzMHMsPGJyLz5hZ2VudCBoYWxsdWNpbmF0ZXMgcmVzdWx0c1wiXVxuICAgIEQgLS0-IEQxW1wiRmxpZ2h0IEFQSSByZXR1cm5zIDIgb2YgNTxici8-cmVzdWx0cywgYWdlbnQgcGlja3MgZnJvbTxici8-aW5jb21wbGV0ZSBzZXRcIl1cbiAgICBFIC0tPiBFMVtcIlBpY2tzIFBhcmlzIGZvciBmbGlnaHRzLDxici8-dGhlbiBzdWdnZXN0cyBhIExvbmRvbjxici8-cmVzdGF1cmFudFwiXVxuICAgIEYgLS0-IEYxW1wiV3JvbmcgZGF0ZSBpbiBzdGVwIDI8YnIvPmNhc2NhZGVzIGludG8gYnJva2VuPGJyLz5pdGluZXJhcnkgYnkgc3RlcCA3XCJdIiwgIm1lcm1haWQiOiB7InRoZW1lIjogImRlZmF1bHQifX0%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBURFxuICAgIEFbXCJcdWQ4M2VcdWRkMTYgTXVsdGktU3RlcCBBZ2VudFwiXSAtLT4gQltcIlx1Mjc0YyBXcm9uZyBUb29sIFNlbGVjdGlvblwiXVxuICAgIEEgLS0-IENbXCJcdTIzZjFcdWZlMGYgQVBJIFRpbWVvdXRzXCJdXG4gICAgQSAtLT4gRFtcIlx1MjZhMFx1ZmUwZiBQYXJ0aWFsIEZhaWx1cmVzXCJdXG4gICAgQSAtLT4gRVtcIlx1ZDgzZFx1ZGQwMCBJbmNvbnNpc3RlbnQgU3RhdGVcIl1cbiAgICBBIC0tPiBGW1wiXHVkODNkXHVkY2E1IENvbXBvdW5kaW5nIEZhaWx1cmVzXCJdXG5cbiAgICBCIC0tPiBCMVtcIkFnZW50IHBpY2tzIGhvdGVsIGJvb2tpbmc8YnIvPnRvb2wgdG8gZmluZCBoaWtpbmcgdHJhaWxzXCJdXG4gICAgQyAtLT4gQzFbXCJGbGlnaHQgQVBJIGhhbmdzIGZvciAzMHMsPGJyLz5hZ2VudCBoYWxsdWNpbmF0ZXMgcmVzdWx0c1wiXVxuICAgIEQgLS0-IEQxW1wiRmxpZ2h0IEFQSSByZXR1cm5zIDIgb2YgNTxici8-cmVzdWx0cywgYWdlbnQgcGlja3MgZnJvbTxici8-aW5jb21wbGV0ZSBzZXRcIl1cbiAgICBFIC0tPiBFMVtcIlBpY2tzIFBhcmlzIGZvciBmbGlnaHRzLDxici8-dGhlbiBzdWdnZXN0cyBhIExvbmRvbjxici8-cmVzdGF1cmFudFwiXVxuICAgIEYgLS0-IEYxW1wiV3JvbmcgZGF0ZSBpbiBzdGVwIDI8YnIvPmNhc2NhZGVzIGludG8gYnJva2VuPGJyLz5pdGluZXJhcnkgYnkgc3RlcCA3XCJdIiwgIm1lcm1haWQiOiB7InRoZW1lIjogImRlZmF1bHQifX0%3D" alt="The 5 failure modes of multi-step AI agents" width="1399" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Wrong Tool Selection
&lt;/h3&gt;

&lt;p&gt;The agent has six tools available and picks the wrong one. You ask for hiking trails near Chamonix and it calls the hotel booking API. Why? Because the model decided "outdoor activities" was close enough to "hotel amenities." This isn't a bug you can reproduce consistently — it happens 1 in 20 times, which is exactly often enough to ruin your weekend.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. API Timeouts
&lt;/h3&gt;

&lt;p&gt;External APIs are flaky. The flight search takes 30 seconds instead of 3. The agent doesn't wait — it either times out and hallucinates a result, or it retries in a loop until your user gives up. Welcome to the real world, where third-party APIs don't care about your agent's plans.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Partial Failures
&lt;/h3&gt;

&lt;p&gt;This one's sneaky. The tool &lt;em&gt;responds&lt;/em&gt;, but with incomplete data. The flight API returns 2 results instead of 15 because of a pagination bug. The agent doesn't know it's working with a partial dataset — it just picks the "best" option from a bad menu. Your user gets a suboptimal flight, and nobody understands why.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Inconsistent State
&lt;/h3&gt;

&lt;p&gt;Over a long conversation or a multi-step plan, the agent loses track. It picks Paris as the destination in step 1, finds flights to CDG in step 2, then recommends a restaurant in London in step 5. The context window is long, but the agent's attention isn't perfect. Earlier decisions get fuzzy, and the plan stops being coherent.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Compounding Failures
&lt;/h3&gt;

&lt;p&gt;This is the killer. A small mistake early on — say, the agent misreads the budget as $5,000 instead of $500 — doesn't just affect one step. It cascades. The hotel is too expensive. The restaurant is too fancy. The hiking gear rental gets skipped because the budget's already blown. By step 7, the entire itinerary is garbage, and the root cause is buried six steps back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reliability Tax: When "Almost Perfect" Isn't Good Enough
&lt;/h2&gt;

&lt;p&gt;Let's talk numbers, because this is where intuition fails us.&lt;/p&gt;

&lt;p&gt;Say your agent is 95% accurate at each individual step. That sounds great, right? You'd ship that. Your PM would celebrate that.&lt;/p&gt;

&lt;p&gt;Now do the math for a 10-step task:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;0.95¹⁰ ≈ 0.5987&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your "95% accurate" agent succeeds less than 60% of the time on a 10-step plan. That's a coin flip. For a travel itinerary.&lt;/p&gt;

&lt;p&gt;Here's what that looks like as your agent takes on more complex tasks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Steps&lt;/th&gt;
&lt;th&gt;Per-Step Accuracy&lt;/th&gt;
&lt;th&gt;System Success Rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;77.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;59.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;46.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;35.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;95.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;90.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;81.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read that bottom row again. Even at &lt;strong&gt;99% per-step accuracy&lt;/strong&gt; — which is incredibly hard to achieve — a 20-step agent fails nearly 1 in 5 times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Almost perfect at the step level turns into mostly broken at the system level.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the reliability tax. You pay it whether you know about it or not. And the instinct — the thing everyone does first — is to blame the model. "We need GPT-5." Or to blame the prompt. "Let me add 47 more lines to the system prompt."&lt;/p&gt;

&lt;p&gt;But the real issue isn't the model or the prompt. It's system complexity and basic probability. You can't prompt-engineer your way out of compound probability.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Stop Treating Agents Like Magic
&lt;/h2&gt;

&lt;p&gt;The solution isn't a better model. It's a better architecture. Stop treating your agent as a magic black box and start treating it as what it actually is: a &lt;strong&gt;non-deterministic software component&lt;/strong&gt; that needs the same engineering discipline as any other distributed system.&lt;/p&gt;

&lt;p&gt;Two mindset shifts make the biggest difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mindset Shift 1: Selective Autonomy
&lt;/h3&gt;

&lt;p&gt;The instinct with agents is to go full autopilot. "Let the AI handle everything!" That's like removing the pilot from a plane because autopilot exists.&lt;/p&gt;

&lt;p&gt;Autopilot is incredible — for cruising at 35,000 feet. But you want a human pilot for takeoff, landing, and when the engine catches fire. Same with agents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't let the agent do everything autonomously.&lt;/strong&gt; Insert human approval steps at high-stakes decision points. Before the agent books a $400 flight? Human confirms. Before it commits to a restaurant reservation? Human confirms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBMUlxuICAgIFMxW1wiU2VhcmNoPGJyLz5GbGlnaHRzXCJdIC0tPiBTMltcIlNlbGVjdDxici8-RmxpZ2h0XCJdXG4gICAgUzIgLS0-IEgxe3tcIlx1MjcwYiBIdW1hbjxici8-QXBwcm92YWxcIn19XG4gICAgSDEgLS0-fEFwcHJvdmVkfCBTM1tcIlNlYXJjaDxici8-SG90ZWxzXCJdXG4gICAgUzMgLS0-IFM0W1wiU2VsZWN0PGJyLz5Ib3RlbFwiXVxuICAgIFM0IC0tPiBIMnt7XCJcdTI3MGIgSHVtYW48YnIvPkFwcHJvdmFsXCJ9fVxuICAgIEgyIC0tPnxBcHByb3ZlZHwgUzVbXCJQbGFuPGJyLz5BY3Rpdml0aWVzXCJdXG4gICAgUzUgLS0-IFM2W1wiQm9vazxici8-RGlubmVyXCJdXG4gICAgUzYgLS0-IEgze3tcIlx1MjcwYiBIdW1hbjxici8-QXBwcm92YWxcIn19XG4gICAgSDMgLS0-fEFwcHJvdmVkfCBTN1tcIkZpbmFsPGJyLz5JdGluZXJhcnlcIl1cblxuICAgIHN0eWxlIEgxIGZpbGw6I2Y1YzU0MixzdHJva2U6I2Q0YTAxNyxjb2xvcjojMDAwXG4gICAgc3R5bGUgSDIgZmlsbDojZjVjNTQyLHN0cm9rZTojZDRhMDE3LGNvbG9yOiMwMDBcbiAgICBzdHlsZSBIMyBmaWxsOiNmNWM1NDIsc3Ryb2tlOiNkNGEwMTcsY29sb3I6IzAwMCIsICJtZXJtYWlkIjogeyJ0aGVtZSI6ICJkZWZhdWx0In19" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjogImZsb3djaGFydCBMUlxuICAgIFMxW1wiU2VhcmNoPGJyLz5GbGlnaHRzXCJdIC0tPiBTMltcIlNlbGVjdDxici8-RmxpZ2h0XCJdXG4gICAgUzIgLS0-IEgxe3tcIlx1MjcwYiBIdW1hbjxici8-QXBwcm92YWxcIn19XG4gICAgSDEgLS0-fEFwcHJvdmVkfCBTM1tcIlNlYXJjaDxici8-SG90ZWxzXCJdXG4gICAgUzMgLS0-IFM0W1wiU2VsZWN0PGJyLz5Ib3RlbFwiXVxuICAgIFM0IC0tPiBIMnt7XCJcdTI3MGIgSHVtYW48YnIvPkFwcHJvdmFsXCJ9fVxuICAgIEgyIC0tPnxBcHByb3ZlZHwgUzVbXCJQbGFuPGJyLz5BY3Rpdml0aWVzXCJdXG4gICAgUzUgLS0-IFM2W1wiQm9vazxici8-RGlubmVyXCJdXG4gICAgUzYgLS0-IEgze3tcIlx1MjcwYiBIdW1hbjxici8-QXBwcm92YWxcIn19XG4gICAgSDMgLS0-fEFwcHJvdmVkfCBTN1tcIkZpbmFsPGJyLz5JdGluZXJhcnlcIl1cblxuICAgIHN0eWxlIEgxIGZpbGw6I2Y1YzU0MixzdHJva2U6I2Q0YTAxNyxjb2xvcjojMDAwXG4gICAgc3R5bGUgSDIgZmlsbDojZjVjNTQyLHN0cm9rZTojZDRhMDE3LGNvbG9yOiMwMDBcbiAgICBzdHlsZSBIMyBmaWxsOiNmNWM1NDIsc3Ryb2tlOiNkNGEwMTcsY29sb3I6IzAwMCIsICJtZXJtYWlkIjogeyJ0aGVtZSI6ICJkZWZhdWx0In19" alt="Selective autonomy workflow with human approval checkpoints" width="1847" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the beautiful part: &lt;strong&gt;each human checkpoint resets the error probability.&lt;/strong&gt; Instead of one 10-step chain with a 60% success rate, you get three 3-step chains with a human verification between them. Each chain has ~85% accuracy, and the human catches the failures in between. Your effective reliability goes way up — not because the model got smarter, but because you designed the system better.&lt;/p&gt;

&lt;p&gt;This is selective autonomy. Let the agent handle what it's good at (searching, comparing, summarizing) and keep humans in the loop for what matters (confirming, approving, deciding).&lt;/p&gt;

&lt;h3&gt;
  
  
  Mindset Shift 2: Trace-Level Observability
&lt;/h3&gt;

&lt;p&gt;When your agent breaks in production, your logs say something helpful like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR: Agent failed to complete task
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks. Very useful.&lt;/p&gt;

&lt;p&gt;Traditional logging tells you &lt;em&gt;something bad happened&lt;/em&gt;. But with a multi-step agent, you need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; happened — which tool was called, what arguments were passed, what came back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where&lt;/strong&gt; time went — did step 3 take 200ms or 20 seconds?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt; it failed — was it the model's reasoning, the tool's response, or the orchestration logic?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;traces&lt;/strong&gt; come in. Not logs. Traces.&lt;/p&gt;

&lt;p&gt;A trace captures the full execution path of your agent: every reasoning step, every tool call, every input and output. It's the difference between "the patient is sick" and a full medical chart with vitals, lab results, and imaging.&lt;/p&gt;

&lt;p&gt;Build trace-level observability from day one. Instrument every tool call. Capture the agent's chain-of-thought at each decision point. When (not if) something breaks in production, you'll know exactly where to look.&lt;/p&gt;

&lt;p&gt;Here's what you want to capture in a trace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent reasoning&lt;/strong&gt; — the model's chain-of-thought before each action&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool selection&lt;/strong&gt; — which tool was chosen and why&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool input/output&lt;/strong&gt; — the exact request and response&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency&lt;/strong&gt; — how long each step took&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token usage&lt;/strong&gt; — how much context was consumed at each step&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outcome&lt;/strong&gt; — success, partial failure, or error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this, you're debugging a distributed system with &lt;code&gt;console.log&lt;/code&gt;. Good luck.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gap Between Demo and Production
&lt;/h2&gt;

&lt;p&gt;The gap between a demo that works and a product that works isn't more features. It's not a bigger model. It's not a fancier prompt.&lt;/p&gt;

&lt;p&gt;It's &lt;strong&gt;discipline and structure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's acknowledging that your agent is a distributed system subject to compound probability, and engineering accordingly. It's inserting human checkpoints where they matter. It's building observability that tells you the full story, not just the punchline.&lt;/p&gt;

&lt;p&gt;The travel agent that worked on stage can work in production. But only if you stop treating it like magic and start treating it like software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;Here's what you should do this week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Map your agent's failure modes.&lt;/strong&gt; Walk through each step and ask: "What happens when this tool fails? Returns partial data? Times out?" If you can't answer, you have a problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calculate your reliability tax.&lt;/strong&gt; Count your agent's steps. Do the math. If you're at 10+ steps with no human checkpoints, your success rate is probably lower than you think.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add human-in-the-loop checkpoints&lt;/strong&gt; at high-stakes decision points. Start with the most expensive or irreversible actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instrument traces, not just logs.&lt;/strong&gt; Capture the full execution path — reasoning, tool calls, latency, outputs. Make it queryable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop blaming the model.&lt;/strong&gt; The model is one component. The system is the product. Engineer the system.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://dev.to/wassimchegham/agentic-rag-done-right-4846"&gt;In the next post&lt;/a&gt;, we'll tackle one of the biggest culprits behind agent failures: retrieval. Specifically, why classic RAG makes everything worse — and how Agentic RAG fixes it.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you experienced the reliability tax with your agents? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>production</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Using LlamaIndex.TS to Orchestrate MCP Servers</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Mon, 07 Jul 2025 15:49:59 +0000</pubDate>
      <link>https://dev.to/azure/using-llamaindexts-to-orchestrate-mcp-servers-413k</link>
      <guid>https://dev.to/azure/using-llamaindexts-to-orchestrate-mcp-servers-413k</guid>
      <description>&lt;p&gt;In this post, we’ll demonstrate how to orchestrate Model Context Protocol (MCP) servers using &lt;a href="https://ts.llamaindex.ai/" rel="noopener noreferrer"&gt;llamaindex.TS&lt;/a&gt; in a real-world TypeScript application. We’ll use the &lt;a href="https://aka.ms/azure-ai-travel-agents" rel="noopener noreferrer"&gt;Azure AI Travel Agents&lt;/a&gt; project as our base, focusing on best practices for secure, scalable, and maintainable orchestration. Feel free to star the repo to get notified with the latest changes.&lt;/p&gt;

&lt;p&gt;If you are interested in an overview of the Azure AI Travel Agents project, please read &lt;a href="https://techcommunity.microsoft.com/blog/AzureDevCommunityBlog/introducing-azure-ai-travel-agents-a-flagship-mcp-powered-sample-for-ai-travel-s/4416683" rel="noopener noreferrer"&gt;our announcement blog&lt;/a&gt;!&lt;/p&gt;




&lt;h2&gt;
  
  
  Why llamaindex.TS and MCP?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;llamaindex.TS&lt;/strong&gt; provides a modular, composable framework for building LLM-powered applications in TypeScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; enables tool interoperability and streaming, making it ideal for orchestrating multiple AI services.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;The Llamaindex.TS orchestrator lives in &lt;a href="https://github.com/Azure-Samples/azure-ai-travel-agents/tree/main/src/api/src/orchestrator/llamaindex/" rel="noopener noreferrer"&gt;&lt;code&gt;src/api/src/orchestrator/llamaindex&lt;/code&gt;&lt;/a&gt;, with provider modules for different LLM backends and MCP clients. We currently support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure OpenAI&lt;/li&gt;
&lt;li&gt;Docker Models&lt;/li&gt;
&lt;li&gt;Azure AI Foundry Local&lt;/li&gt;
&lt;li&gt;Github Model&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to explore the code base and suggest more providers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up the MCP Client with Streamable HTTP
&lt;/h2&gt;

&lt;p&gt;To interact with MCP servers, without using Llamaindex.TS, we can write a custom implementation using the &lt;code&gt;StreamableHTTPClientTransport&lt;/code&gt; for efficient, authenticated, and streaming communication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// filepath: src/api/src/mcp/mcp-http-client.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StreamableHTTPClientTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/streamableHttp.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MCPClient&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;EventEmitter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StreamableHTTPClientTransport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serverName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamableHTTPClientTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serverName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;listTools&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listTools&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toolArgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toolArgs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closeGracefully&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Always pass the &lt;code&gt;Authorization&lt;/code&gt; header for secure access, as shown above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling manually an MCP Tool from the Orchestrator
&lt;/h2&gt;

&lt;p&gt;Suppose you want to get destination recommendations from the MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MCPClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../mcp/mcp-http-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DESTINATION_SERVER_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MCP_DESTINATION_RECOMMENDATION_URL&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MCP_DESTINATION_RECOMMENDATION_ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MCPClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;destination-recommendation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DESTINATION_SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listTools&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Available tools:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getDestinationsByPreferences&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CULTURAL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MODERATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;season&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUMMER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;familyFriendly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Recommended destinations:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Always close the MCP client gracefully to release resources.&lt;/p&gt;




&lt;h2&gt;
  
  
  Orchestrating LLMs and MCP Tools with Llamaindex.TS
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;mcp&lt;/code&gt; client from &lt;code&gt;@llamaindex/tools&lt;/code&gt; makes it easy to connect to MCP servers and retrieve tool definitions dynamically. Below is a sample from the project’s orchestrator setup, showing how to use &lt;code&gt;mcp&lt;/code&gt; to fetch tools and create agents for each MCP server.&lt;/p&gt;

&lt;p&gt;Here is an example of what an &lt;code&gt;mcpServerConfig&lt;/code&gt; object might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mcpServerConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5007&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// MCP server endpoint&lt;/span&gt;
  &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MCP_ECHO_PING_ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Secure token from env&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;echo-ping&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Logical name for the server&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then use this config with the &lt;code&gt;mcp&lt;/code&gt; client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mcp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@llamaindex/tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;multiAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ToolCallLLM&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;llamaindex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...existing code...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mcpServerConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mcpToolsConfig&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;echo-ping&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;mcp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mcpServerConfig&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;echoAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EchoAgent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Echo back the received input. Do not respond with anything else. Always call the tools.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;agentsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;echoAgent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;handoffTargets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;echoAgent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;toolsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ...other code...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;travelAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TravelAgent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Acts as a triage agent to determine the best course of action for the user's query. If you cannot handle the query, please pass it to the next agent. If you can handle the query, please do so.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;toolsList&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;canHandoffTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handoffTargets&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAgents&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;agentsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;travelAgent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create the multi-agent workflow&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;multiAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agentsList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rootAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;travelAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can repeat this pattern to compose a multi-agent workflow where each agent is powered by tools discovered at runtime from the MCP server. See project for &lt;a href="https://github.com/Azure-Samples/azure-ai-travel-agents/blob/main/src/api/src/orchestrator/llamaindex/index.ts" rel="noopener noreferrer"&gt;a full example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can then use this LLM instance to orchestrate calls to MCP tools, such as itinerary planning or destination recommendation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always use access tokens and secure headers.&lt;/li&gt;
&lt;li&gt;Never hardcode secrets; use environment variables and secret managers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Join the Community:
&lt;/h2&gt;

&lt;p&gt;We encourage you to join our Azure AI Foundry Developer Community​ to share your experiences, ask questions, and get support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/NcwHpz6bRW" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; for real-time discussions and support.&lt;/li&gt;
&lt;li&gt;Visit our &lt;a href="//aka.ms/foundry/forum"&gt;Azure AI Foundry Developer Forum&lt;/a&gt; to ask questions and share your knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By combining llamaindex.TS with MCP’s Streamable HTTP transport, you can orchestrate powerful, secure, and scalable AI workflows in TypeScript. The Azure AI Travel Agents project provides a robust template for building your own orchestrator.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ts.llamaindex.ai/" rel="noopener noreferrer"&gt;llamaindex.TS Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http" rel="noopener noreferrer"&gt;MCP Streamable HTTP Spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aka.ms/azure-ai-travel-agents" rel="noopener noreferrer"&gt;Azure AI Travel Agents Sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mcp</category>
      <category>programming</category>
      <category>cloud</category>
      <category>javascript</category>
    </item>
    <item>
      <title>DeepSeek Extension for GitHub Copilot in VS Code 🚀</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Thu, 13 Feb 2025 11:36:49 +0000</pubDate>
      <link>https://dev.to/wassimchegham/deepseek-extension-for-github-copilot-in-vs-code-2c03</link>
      <guid>https://dev.to/wassimchegham/deepseek-extension-for-github-copilot-in-vs-code-2c03</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr: Run DeepSeek models in your GitHub Copilot Chat 🚀&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;DeepSeek has been getting a lot of buzz lately, and with a little setup, you can start using it today in GitHub Copilot within VS Code. In this post, I’ll walk you through how to install and run a VS Code extension I built, so you can take advantage of DeepSeek right on your machine. With this extension, you can use &lt;strong&gt;&lt;code&gt;@deepseek&lt;/code&gt;&lt;/strong&gt; to explore the deepseek-coder model. It’s powered by Ollama, enabling seamless, fully offline interactions with DeepSeek models—giving you a local coding assistant that prioritizes privacy and performance.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In a future post I'll walk you through the extension code and explain how to call models hosted locally using Ollama. Feel free to subscribe to get notified.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features and Benefits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Open-Source and Extendable
&lt;/h3&gt;

&lt;p&gt;As &lt;a href="https://github.com/manekinekko/vscode-deepseek" rel="noopener noreferrer"&gt;an open-source project&lt;/a&gt;, the DeepSeek for GitHub Copilot extension is fully customizable. Advanced users can modify and extend its functionality, build from source, tweak configurations, and even integrate additional AI capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local AI Processing
&lt;/h3&gt;

&lt;p&gt;With the DeepSeek for GitHub Copilot extension, all interactions are processed locally on your machine, ensuring complete data privacy and eliminating latency issues. This makes it an ideal solution for developers working on sensitive projects or in restricted environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seamless Integration with GitHub Copilot Chat
&lt;/h2&gt;

&lt;p&gt;The extension integrates natively with GitHub Copilot Chat, allowing you to invoke DeepSeek models effortlessly. If you're already familiar with GitHub Copilot, you'll find the workflow intuitive and easy to use. You can simply type &lt;strong&gt;&lt;code&gt;@deepseek&lt;/code&gt;&lt;/strong&gt; followed by your question to get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Powered by Ollama
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;, a lightweight AI model runtime, powers the execution of DeepSeek models. It simplifies model management by handling downloads and execution, so you can focus on coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizable Model Selection
&lt;/h2&gt;

&lt;p&gt;You can configure the extension to use different DeepSeek models through a simple setting adjustment. This flexibility allows you to choose the right model size and capability for your hardware. Please note that running bigger models might not work on your local system. You can take advantage of Azure's infrastructure to run bigger models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing and Running Ollama
&lt;/h3&gt;

&lt;p&gt;DeepSeek for GitHub Copilot requires &lt;strong&gt;Ollama&lt;/strong&gt; to function properly. Ollama is an AI model runtime that allows you to run and manage large language models efficiently on your local machine.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Ollama&lt;/strong&gt;: Download the installer, install, and start Ollama from the &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install from Visual Studio Code Marketplace&lt;/strong&gt;: The simplest way to get started is by installing the extension directly from &lt;a href="https://marketplace.visualstudio.com/items?itemName=wassimdev.wassimdev-vscode-deepseek" rel="noopener noreferrer"&gt;the Visual Studio Code Marketplace&lt;/a&gt;.

&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;Visual Studio Code&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to the Extensions panel (Ctrl + Shift + X).&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;DeepSeek for GitHub Copilot&lt;/strong&gt; and click &lt;strong&gt;Install&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the Extension&lt;/strong&gt;: Once installed, using the extension is straightforward:

&lt;ul&gt;
&lt;li&gt;Open the &lt;strong&gt;GitHub Copilot Chat&lt;/strong&gt; panel.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;@deepseek&lt;/code&gt; followed by your prompt to interact with the model.&lt;/li&gt;
&lt;li&gt;Note: On the first run, the extension will automatically &lt;strong&gt;download&lt;/strong&gt; the DeepSeek model. This may take a few minutes, depending on your internet connection.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjq5tzssl35z4y48sycd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjq5tzssl35z4y48sycd.png" alt="DeepSeek Extension for GitHub Copilot in VS Code" width="800" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration and Customization
&lt;/h2&gt;

&lt;p&gt;DeepSeek for GitHub Copilot allows users to configure the AI model through Visual Studio Code settings.&lt;/p&gt;

&lt;p&gt;To change the DeepSeek model, update the settings.json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"deepseek.model.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deepseek-coder:1.3b"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A list of available models can be found on the &lt;a href="https://ollama.com/search?q=deepseek" rel="noopener noreferrer"&gt;Ollama website&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and Workarounds
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Current Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The extension does not have access to your files in this version, meaning it cannot provide context-aware completions. This is due to the fact that DeepSeek models don't support Function Calling.&lt;/li&gt;
&lt;li&gt;Limited to local machine performance—larger models may require more RAM and CPU power.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Workarounds
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To provide context for completions, manually copy-paste the relevant code into the chat.&lt;/li&gt;
&lt;li&gt;Optimize performance by selecting smaller DeepSeek models (such as deepseek-coder:1.3b) if you experience lag.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  System Requirements
&lt;/h3&gt;

&lt;p&gt;To run DeepSeek for GitHub Copilot Chat, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio Code (latest version recommended)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; app installed and running (Download from ollama.com)&lt;/li&gt;
&lt;li&gt;Sufficient system resources

&lt;ul&gt;
&lt;li&gt;Minimum: 8GB RAM, multi-core CPU&lt;/li&gt;
&lt;li&gt;Recommended: 16GB RAM, GPU acceleration (if available)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The DeepSeek for &lt;a href="https://marketplace.visualstudio.com/items?itemName=wassimdev.wassimdev-vscode-deepseek" rel="noopener noreferrer"&gt;GitHub Copilot Chat extension&lt;/a&gt; provides an excellent way for delivering privacy, low-latency responses, and offline capabilities.&lt;/p&gt;

&lt;p&gt;🔗 Get Started Today: Install the DeepSeek for GitHub Copilot Chat extension and supercharge your GitHub Copilot Chat experience with AI—entirely offline! 🚀&lt;/p&gt;

&lt;p&gt;■ Wassim Chegham (&lt;a href="https://wassim.dev" rel="noopener noreferrer"&gt;https://wassim.dev&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>javascript</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building a RAG app with LlamaIndex.ts and Azure OpenAI: Getting started!</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Tue, 10 Sep 2024 09:22:33 +0000</pubDate>
      <link>https://dev.to/azure/building-a-rag-app-with-llamaindexts-and-azure-openai-getting-started-3pgb</link>
      <guid>https://dev.to/azure/building-a-rag-app-with-llamaindexts-and-azure-openai-getting-started-3pgb</guid>
      <description>&lt;p&gt;As AI continues to shape the way we work and interact with technology, many businesses are looking for ways to leverage their own data within intelligent applications. If you've used tools like ChatGPT or Azure OpenAI, you're already familiar with how generative AI can improve processes and enhance user experiences. However, for truly customized and relevant responses, your applications need to incorporate your proprietary data. &lt;/p&gt;

&lt;p&gt;This is where Retrieval-Augmented Generation (RAG) comes in, providing a structured approach to integrating data retrieval with AI-powered responses. With frameworks like &lt;a href="https://www.llamaindex.ai" rel="noopener noreferrer"&gt;LlamaIndex&lt;/a&gt;, you can easily build this capability into your solutions, unlocking the full potential of your business data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqi9jgbxzdswvj2spa9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqi9jgbxzdswvj2spa9c.png" alt="Building a RAG app with LlamaIndex.ts and Azure OpenAI: Getting started!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Want to quickly run and explore the app? Click here. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is RAG - Retrieval-Augmented Generation?
&lt;/h2&gt;

&lt;p&gt;Retrieval-Augmented Generation (RAG) is a neural network framework that enhances AI text generation by including a retrieval component to access relevant information and integrate your own data. It consists of two main parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retriever&lt;/strong&gt;: A dense retriever model (e.g., based on BERT) that searches a large corpus of documents to find relevant passages or information related to a given query.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generator&lt;/strong&gt;: A sequence-to-sequence model (e.g., based on BART or T5) that takes the query and the retrieved text as input and generates a coherent, contextually enriched response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The retriever finds relevant documents, and the generator uses them to create more accurate and informative responses. This combination allows the RAG model to leverage external knowledge effectively, improving the quality and relevance of the generated text.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does LlamaIndex implement RAG?
&lt;/h2&gt;

&lt;p&gt;To implement a RAG system using LlamaIndex, follow these general steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Ingestion:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Load your documents into LlamaIndex.ts using a document loader such as &lt;code&gt;SimpleDirectoryReader&lt;/code&gt;, which helps in importing data from various sources like PDFs, APIs, or SQL databases.&lt;/li&gt;
&lt;li&gt;Break down large documents into smaller, manageable chunks using the &lt;code&gt;SentenceSplitter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Index Creation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a vector index of these document chunks using &lt;code&gt;VectorStoreIndex&lt;/code&gt;, allowing efficient similarity searches based on embeddings.&lt;/li&gt;
&lt;li&gt;Optionally, for complex datasets, use recursive retrieval techniques to manage hierarchically structured data and retrieve relevant sections based on user queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Query Engine Setup:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Convert the vector index into a query engine using &lt;code&gt;asQueryEngine&lt;/code&gt; with parameters such as &lt;code&gt;similarityTopK&lt;/code&gt; to define how many top documents should be retrieved.&lt;/li&gt;
&lt;li&gt;For more advanced setups, create a multi-agent system where each agent is responsible for specific documents, and a top-level agent coordinates the overall retrieval process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Retrieval and Generation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Implement the RAG pipeline by defining an objective function that retrieves relevant document chunks based on user queries.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;RetrieverQueryEngine&lt;/code&gt; to perform the actual retrieval and query processing, with optional post-processing steps like re-ranking the retrieved documents using tools such as &lt;code&gt;CohereRerank&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a practical example, we have provided a sample application to demonstrate a complete RAG implementation using Azure OpenAI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical RAG Sample Application
&lt;/h2&gt;

&lt;p&gt;We'll now focus on building a RAG application using LlamaIndex.ts (the TypeScipt implementation of LlamaIndex) and Azure OpenAI, and deploy on it as a serverless Web Apps on &lt;a href="https://azure.microsoft.com/products/container-apps" rel="noopener noreferrer"&gt;Azure Container Apps&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements to Run the Sample
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Azure Developer CLI (azd)&lt;/strong&gt;: A command-line tool to easily deploy your entire app, including backend, frontend, and databases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure Account&lt;/strong&gt;: You'll need an Azure account to deploy the application. Get a free Azure account with some credits to get started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will find the getting started project on GitHub. We recommend you to &lt;a href="https://github.com/Azure-Samples/llama-index-javascript/fork" rel="noopener noreferrer"&gt;fork&lt;/a&gt; this template so you can freely edit it when needed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/codespaces/new?hide_repo_select=true&amp;amp;ref=main&amp;amp;repo=811754358&amp;amp;machine=standardLinux32gb&amp;amp;devcontainer_path=.devcontainer%2Fdevcontainer.json&amp;amp;location=WestUs2" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/codespaces/badge.svg" alt="Open in GitHub Codespaces"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  High-Level Architecture
&lt;/h2&gt;

&lt;p&gt;The getting started project application is built based on the following architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Azure OpenAI&lt;/strong&gt;: The AI provider that processes the user's queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LlamaIndex.ts&lt;/strong&gt;: The framework that helps ingest, transform, and vectorize content (PDFs) and create a search index.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure Container Apps&lt;/strong&gt;: The container environment where the serverless application is hosted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure Managed Identity&lt;/strong&gt;: Ensures top-notch security and eliminates the need for handling credentials and API keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj394w08lnx8d8eieahg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj394w08lnx8d8eieahg8.png" alt="architecture-diagram-llama-index-javascript"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more details on what resources are deployed, check the &lt;code&gt;infra&lt;/code&gt; folder available in all our &lt;a href="https://github.com/Azure-Samples/" rel="noopener noreferrer"&gt;samples&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example User Workflows
&lt;/h3&gt;

&lt;p&gt;The sample application contains logic for two workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Ingestion&lt;/strong&gt;: Data is fetched, vectorized, and search indexes are created. If you want to add more files like PDFs or Word files, this is where you should add them.&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npm run generate
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serving Prompt Requests&lt;/strong&gt;: The app receives user prompts, sends them to Azure OpenAI, and augments these prompts using the vector index as a retriever.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Running the Sample
&lt;/h2&gt;

&lt;p&gt;Before running the sample, ensure you have provisioned the necessary Azure resources.&lt;/p&gt;

&lt;p&gt;To run the GitHub template in GitHub Codespace, simply click &lt;br&gt;
&lt;a href="https://github.com/codespaces/new?hide_repo_select=true&amp;amp;ref=main&amp;amp;repo=811754358&amp;amp;machine=standardLinux32gb&amp;amp;devcontainer_path=.devcontainer%2Fdevcontainer.json&amp;amp;location=WestUs2" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/codespaces/badge.svg" alt="Open in GitHub Codespaces"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your Codespaces instance, sign into your Azure account, from your terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;azd auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Provision, package, and deploy the sample application to Azure using a single command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;azd up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To run and try the application locally, install the npm dependencies and run the app:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The app will run on port 3000 in your Codespaces instance or at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; in your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This guide demonstrated how to build a serverless RAG (Retrieval-Augmented Generation) application using LlamaIndex.ts and Azure OpenAI, deployed on Microsoft Azure. By following this guide, you can leverage Azure's infrastructure and LlamaIndex's capabilities to create powerful AI applications that provide contextually enriched responses based on your data.&lt;/p&gt;

&lt;p&gt;We’re excited to see what you build with this getting started application. Feel free to &lt;a href="https://github.com/Azure-Samples/llama-index-javascript/fork" rel="noopener noreferrer"&gt;fork&lt;/a&gt; it and like the GitHub repository to receive the latest updates and features.&lt;/p&gt;

</description>
      <category>rag</category>
      <category>openai</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Azure Static Web Apps CLI is now GA 🚀</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Wed, 25 May 2022 19:28:10 +0000</pubDate>
      <link>https://dev.to/wassimchegham/azure-static-web-apps-cli-is-now-ga-3d7e</link>
      <guid>https://dev.to/wassimchegham/azure-static-web-apps-cli-is-now-ga-3d7e</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F254zd16j6g1jc32fh9bq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F254zd16j6g1jc32fh9bq.png" alt="Azure Static Web Apps CLI is now GA" width="641" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Azure Static Web Apps?
&lt;/h2&gt;

&lt;p&gt;Azure Static Web Apps is a service that's perfect for your full stack as well as static application projects. Yes, you heard that correctly. Regardless if you are dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A static resume site with vanilla HTML, CSS and JavaScript&lt;/li&gt;
&lt;li&gt;SPA application with Angular, React, Vue, etc.&lt;/li&gt;
&lt;li&gt;Static site generators like Gatsby, Next, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Azure Static Web Apps is there for you and enables you to deploy your files to Azure. In order words, Azure Static Web Apps if the perfect choice if you are looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FREE Web hosting for static content like HTML, CSS, JavaScript, and images.&lt;/li&gt;
&lt;li&gt;Integrated API support provided by Azure Functions with the option to link an existing Azure Functions app using a standard account.&lt;/li&gt;
&lt;li&gt;First-class GitHub and Azure DevOps integration where repository changes trigger builds and deployments.&lt;/li&gt;
&lt;li&gt;Globally distributed static content, putting content closer to your users.&lt;/li&gt;
&lt;li&gt;Free SSL certificates, which are automatically renewed.&lt;/li&gt;
&lt;li&gt;Custom domains to provide branded customizations to your app.&lt;/li&gt;
&lt;li&gt;Seamless security model with a reverse-proxy when calling APIs, which requires no CORS configuration.&lt;/li&gt;
&lt;li&gt;Authentication provider integrations with Azure Active Directory, GitHub, and Twitter.&lt;/li&gt;
&lt;li&gt;Customizable authorization role definition and assignments.&lt;/li&gt;
&lt;li&gt;Back-end routing rules enabling full control over the content and routes you serve.&lt;/li&gt;
&lt;li&gt;Generated staging versions powered by pull requests enabling preview versions of your site before publishing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Azure Static Web Apps CLI?
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xSrSifDQzR0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;It's the CLI companion for Azure Static Web Apps that you use from your local dev machine. The SWA CLI offers tons of features, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work on your JAMstack app locally&lt;/li&gt;
&lt;li&gt;Built-in framework detection&lt;/li&gt;
&lt;li&gt;Serverless support&lt;/li&gt;
&lt;li&gt;Authentication &amp;amp; Authorization&lt;/li&gt;
&lt;li&gt;Login to Azure&lt;/li&gt;
&lt;li&gt;Deploy &amp;amp; Ship from the CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check it the documentation &lt;a href="https://aka.ms/swa-cli-ga"&gt;website&lt;/a&gt; 👍&lt;br&gt;
Have fun!&lt;/p&gt;




&lt;p&gt;Feel free to reach out on Twitter at &lt;a href="https://twitter.com/manekinekko"&gt;@manekinekko&lt;/a&gt; if you want to get started with Azure Static Web Apps. You can also follow my work at &lt;a href="https://wassim.dev"&gt;wassim.dev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>devops</category>
      <category>javascript</category>
      <category>azure</category>
    </item>
    <item>
      <title>Understanding Git Internals</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Sun, 20 Feb 2022 21:58:01 +0000</pubDate>
      <link>https://dev.to/wassimchegham/behind-the-git-sha-dow-1pib</link>
      <guid>https://dev.to/wassimchegham/behind-the-git-sha-dow-1pib</guid>
      <description>&lt;p&gt;Let's explore some common Git commands, and dive into Git internals to understand what happens when you run Git commands.&lt;/p&gt;

&lt;p&gt;But first, let's talk about Git itself.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Git?
&lt;/h1&gt;

&lt;p&gt;Put simply, Git is an open source distributed version control system. It was designed by Linus Torvalds, creator of the Linux kernel, to manage the source code of the kernel. Git was designed from the start to be as fast and efficient as possible.&lt;/p&gt;

&lt;h1&gt;
  
  
  Git's Principles
&lt;/h1&gt;

&lt;p&gt;In other version control systems such as CVS, Subversion, and ClearCase, the server is centralized — there's a clear separation between the server and clients.&lt;/p&gt;

&lt;p&gt;When developers work on projects that use these systems, they first send a &lt;em&gt;checkout&lt;/em&gt; request to the server, then retrieve a &lt;em&gt;snapshot&lt;/em&gt; of the current version — usually the most recent one. Everyone has to go through the central server in order to work on the same project, sending &lt;em&gt;commits&lt;/em&gt; or creating branches.&lt;/p&gt;

&lt;p&gt;With Git, things are different. When we want to work on a project that uses Git, we clone it locally, on to our machine. In other words, Git copies all project files to our local drive, then we can work on the project. All operations run locally on our machine. We don't even need a network connection, except to synchronize with other team members, when &lt;em&gt;pushing&lt;/em&gt; our changes or &lt;em&gt;pulling&lt;/em&gt; new changes.&lt;/p&gt;

&lt;p&gt;That's what makes Git so quick.&lt;/p&gt;

&lt;p&gt;With Git, we can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;commit&lt;/em&gt; changes.&lt;/li&gt;
&lt;li&gt;change and create branches.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;merge&lt;/em&gt; or &lt;em&gt;rebase&lt;/em&gt; branches.&lt;/li&gt;
&lt;li&gt;retrieve a &lt;em&gt;diff&lt;/em&gt; or apply a &lt;em&gt;patch&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;recover different versions of the same file.&lt;/li&gt;
&lt;li&gt;access the change history of any file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we can do most of this without even being connected to the Internet. Amazing, right?&lt;/p&gt;

&lt;p&gt;Let's talk about some of the very basic Git commands when it comes to staging and committing changes to Git.&lt;/p&gt;

&lt;h2&gt;
  
  
  A brief intro to Git basic commands
&lt;/h2&gt;

&lt;p&gt;When we access a folder that contains the source code of an application we are working on, but doesn't use Git, and run &lt;code&gt;git status&lt;/code&gt;. Git will respond that the current directory is not a Git repository:&lt;/p&gt;

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

&lt;p&gt;That's because we haven't initialized Git in this project. We need to first run &lt;code&gt;git init&lt;/code&gt; in the root directory in order to initialize a new Git repository.&lt;/p&gt;

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

&lt;p&gt;As we can see from the screenshot, we created an empty Git repository, and we are currently on its default branch — usually called &lt;em&gt;main&lt;/em&gt;.&lt;br&gt;
We can also notice that Git creates a &lt;em&gt;.git/&lt;/em&gt; folder at the root of the project. This hidden directory is Git's internal database. If you wish to make a backup of your project's Git history, simply make a copy of this directory.&lt;/p&gt;

&lt;p&gt;Let's run &lt;code&gt;git status&lt;/code&gt; again to see what's the status of our new project:&lt;/p&gt;

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

&lt;p&gt;Git tells us that we haven't added anything to our commit. What Git means here is that we haven't revisioned any content yet. In Git, we can do this in 2 steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mark the change to be committed using &lt;code&gt;git add&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;commit the change to Git using &lt;code&gt;git commit&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's add the content of the current root directory with the &lt;code&gt;git add .&lt;/code&gt; command:&lt;/p&gt;

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

&lt;p&gt;The next step is to commit these files using the command &lt;code&gt;git commit -m "my first commit"&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejmsnji0zvb65wk9j5qx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejmsnji0zvb65wk9j5qx.png" alt="git commit -m "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's change the title of our app in &lt;code&gt;src/index.html&lt;/code&gt; and then run the command &lt;code&gt;git diff&lt;/code&gt;:&lt;/p&gt;

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

&lt;p&gt;Git shows what changes are waiting to be committed. We can view those changes using the &lt;code&gt;git status&lt;/code&gt;. Once we are sure about our changes, we can commit them using the commands &lt;code&gt;git add .&lt;/code&gt; followed by &lt;code&gt;git commit -m "add thundr emoji"&lt;/code&gt;. Or, we can combine these two commands into one using &lt;code&gt;git commit -am "add thundr emoji"&lt;/code&gt; (note the &lt;code&gt;-am&lt;/code&gt; options):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j2fea73gx2vvvswjgvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j2fea73gx2vvvswjgvt.png" alt="git commit -am "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was a brief intro to some of the basic Git commands. &lt;/p&gt;

&lt;p&gt;You can learn more about Git in &lt;a href="https://docs.microsoft.com/learn/paths/intro-to-vc-git/?WT.mc_id=javascript-58593-wachegha" rel="noopener noreferrer"&gt;this Git tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's look at how Git does all this.&lt;/p&gt;
&lt;h1&gt;
  
  
  Git Objects
&lt;/h1&gt;

&lt;p&gt;When we create a local repository with &lt;code&gt;git init&lt;/code&gt; (or &lt;code&gt;git clone&lt;/code&gt;), Git initializes its database, and saves it in a hidden directory called &lt;code&gt;.git/&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72k5mmno9m7523g2aisd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72k5mmno9m7523g2aisd.png" alt="tree .git -L 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we examine this folder, we'll find several subfolders and files. The most interesting ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HEAD&lt;/code&gt;: this file contains the path to the reference of the current branch.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config&lt;/code&gt;: the repository configuration file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;objects/&lt;/code&gt;: this is the directory that contains all files in our repository, their content is encoded and compressed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;refs/heads/&lt;/code&gt;: this directory contains one file per branch. Each file is named after a branch, and its content is the &lt;em&gt;SHA-1&lt;/em&gt; of the last commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we create or edit files and run &lt;code&gt;git add .&lt;/code&gt;, Git adds a &lt;em&gt;snapshot&lt;/em&gt; of the files to its database. It retrieves the current content of the edited files, then computes a hash using a &lt;a href="https://en.wikipedia.org/wiki/SHA-1" rel="noopener noreferrer"&gt;SHA-1 algorithm&lt;/a&gt;, and creates an entry in its database for this specific change. The key of this entry is the SHA-1 hash, and its value is the raw contents of the file. &lt;strong&gt;Yes, the whole content!&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

.git/objects/
➜ tree &lt;span class="nt"&gt;-L&lt;/span&gt; 2
&lt;span class="nb"&gt;.&lt;/span&gt;
├── 61
│   └── cef767aa6b95d09a46848c9305d51a7d2ffbdf
├── c4
│   └── 581986199f973ea6b006a7a754486db97104c5
├── ...
├── f5
│   ├── 31992d6edce8355d131c31723398305ee08364
│   └── 6ff47022c7a46eac3aee615d6d9150338524dc
└── ...


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

&lt;/div&gt;
&lt;p&gt;Git uses a technique called &lt;a href="https://en.wikipedia.org/wiki/Content-addressable_storage" rel="noopener noreferrer"&gt;Content Addressable Storage&lt;/a&gt; to store the content of files, as objects, inside the &lt;code&gt;.git/objects/&lt;/code&gt;folder. Basically, Git uses the first 2 characters of the object's name as a subfolder name, i.e. &lt;code&gt;objects/xx/&lt;/code&gt;, add the remaining 38 characters are used as the file name, i.e. &lt;code&gt;objects/xx/yy&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that when referring or inspecting the content of these files and folders, we can simply use the first 8 bits of the SHA-1 hash. Those are enough!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Tree objects
&lt;/h2&gt;

&lt;p&gt;Git uses a simplified UNIX-filesystem-like format to store tree its content. Content is stored as tree and blob objects. Trees objects is similar to UNIX directory entries and blob objects are more or less inodes or file contents. A single tree object contains one or more entries, each of which is the SHA-1 hash of a blob or subtree with its associated mode, type, and filename.&lt;/p&gt;

&lt;p&gt;We can inspect the current branch in Git using &lt;code&gt;git ls-tree&lt;/code&gt; and print a list of its latest stored objects. A branch's name is considered to be a top-level tree:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

@manekinekko/thundr
➜ git ls-tree main
100644 blob 4f9ac26980c156a3d525267010d5f78144b43519    .browserslistrc
100644 blob 0711527ef9d5c117396e6c03290a76658e6384ed    .gitignore
040000 tree 572a53f73bb332280d19f2f7cb0bcac8b32faab5    .vscode
100644 blob 7c582e3fcc8e8d02e8e018eb43959020c2aef847    README.md
100644 blob a1486ac82746b7019361a1758f00dc6fd7a29efd    angular.json
100644 blob c6f92b3680a069987a4c1236ec12c7b377eda1ea    package.json
040000 tree 61cef767aa6b95d09a46848c9305d51a7d2ffbdf    src
100644 blob 82d91dc4a4de57f380b66c59cdd16ff6cd5798e4    tsconfig.app.json
100644 blob f531992d6edce8355d131c31723398305ee08364    tsconfig.json


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

&lt;/div&gt;
&lt;p&gt;Notice that the &lt;code&gt;src&lt;/code&gt; subdirectory is a tree that points to another tree: &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

040000 tree 61cef767aa6b95d09a46848c9305d51a7d2ffbdf    src


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

&lt;/div&gt;
&lt;p&gt;We can inspect the &lt;code&gt;src&lt;/code&gt; tree using its SHA-1 hash:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

@manekinekko/thundr
➜ git ls-tree 61cef767aa6b95d09a46848c9305d51a7d2ffbdf
040000 tree dbfd18df3078aaf0f03edff8c237e4248a84759c    app
040000 tree d564d0bc3dd917926892c55e3706cc116d5b165e    assets
040000 tree 5825478d74b5576b0f8330bdf5179b3ec6503fb8    environments
100644 blob 997406ad22c29aae95893fb3d666c30258a09537    favicon.ico
100644 blob c4581986199f973ea6b006a7a754486db97104c5    index.html
100644 blob c7b673cf44b388e9989fe908b78d7d73cd2e1409    main.ts
100644 blob 429bb9ef2d3400363c014fa434775b0f482f6bea    polyfills.ts
100644 blob 90d4ee0072ce3fc41812f8af910219f9eea3c3de    styles.css


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

&lt;/div&gt;
&lt;p&gt;Tree objects list one or multiple blobs and sub-trees, with their mode/permissions, the type, the SHA-1 hash, and the file/folder name.&lt;/p&gt;

&lt;p&gt;Looking at the &lt;code&gt;index.html&lt;/code&gt; entry, we notice that the content is stored are a blob:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

100644 blob c4581986199f973ea6b006a7a754486db97104c5    index.html


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Blob objects
&lt;/h2&gt;

&lt;p&gt;For blobs, we can read their content using the &lt;code&gt;git-cat&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

@manekinekko/thundr 
➜ git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; c4581986199f973ea6b006a7a754486db97104c5
&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;doctype html&amp;gt;
&amp;lt;html &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt;&lt;span class="nb"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;meta &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"utf-8"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;title&amp;gt;Thundr&amp;lt;/title&amp;gt;
  &amp;lt;base &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;meta &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"viewport"&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;&lt;span class="nb"&gt;link &lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"icon"&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"image/x-icon"&lt;/span&gt; &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"favicon.ico"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;app-root&amp;gt;&amp;lt;/app-root&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;
&lt;p&gt;Let's update the content of the &lt;code&gt;src/index.html&lt;/code&gt; file, and run again a &lt;code&gt;git add .&lt;/code&gt;. Git performs the same process as before. It creates a new entry in its database, and because the file content changed, the SHA-1 hash has also changed. When we do a &lt;code&gt;git commit&lt;/code&gt;, Git recreates a new tree structure with a new SHA-1 hash:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

@manekinekko/thundr
➜ git ls-tree main
...
040000 tree 2d56d5d1aa7fc5f2b4133f5c19088625a2a508db    src

@manekinekko/thundr
➜ git ls-tree 2d56d5d1aa7fc5f2b4133f5c19088625a2a508db
...
100644 blob 83a8d59dbac0603a0b108fadb20af24cb575ecca    index.html


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that both SHA-1 hashes of &lt;code&gt;src&lt;/code&gt; tree and &lt;code&gt;index.html&lt;/code&gt; blob have changed because Git created a new tree structure that stores the new file content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can inspect again the content of the new stored blob and see the change we made (we added a thunder ⚡️ emoji in the title):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

@manekinekko/thundr
git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; 83a8d59dbac0603a0b108fadb20af24cb575ecca
&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;doctype html&amp;gt;
&amp;lt;html &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt;&lt;span class="nb"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;meta &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"utf-8"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;title&amp;gt;Thundr ⚡️&amp;lt;/title&amp;gt;
  &amp;lt;base &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;meta &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"viewport"&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;&lt;span class="nb"&gt;link &lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"icon"&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"image/x-icon"&lt;/span&gt; &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"favicon.ico"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;app-root&amp;gt;&amp;lt;/app-root&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;
&lt;p&gt;Next, let's rename that file to, e.g., &lt;code&gt;src/index-2.html&lt;/code&gt;, and then commit that changes again. Interestingly, Git does not create a new entry in the database for this file because the content — and hence the SHA-1 hash — have not changed. However, the SHA-1 of the &lt;code&gt;src&lt;/code&gt; tree is now different because Git created a new tree structure:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

@manekinekko/thundr
➜ git ls-tree main | &lt;span class="nb"&gt;grep &lt;/span&gt;src
040000 tree c561e2cc7ad896d6880f47df384b19ddb0c602e6    src

@manekinekko/thundr
➜ git ls-tree c561e2cc | &lt;span class="nb"&gt;grep &lt;/span&gt;index-2.html
100644 blob 83a8d59dbac0603a0b108fadb20af24cb575ecca    index-2.html


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

&lt;/div&gt;
&lt;p&gt;As you can see, the SHA-1 hashes of both file names &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;index-2.html&lt;/code&gt; are the same, and that's because their content is identical!&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

100644 blob 83a8d59dbac0603a0b108fadb20af24cb575ecca    index.html
100644 blob 83a8d59dbac0603a0b108fadb20af24cb575ecca    index-2.html


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

&lt;/div&gt;
&lt;p&gt;In order to track who saved the snapshots and where they are saved (which exact tree), Git stores this information in Commit objects.&lt;/p&gt;
&lt;h2&gt;
  
  
  Commit objects
&lt;/h2&gt;

&lt;p&gt;A commit object keeps track of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the hash of the top-level tree where the file snapshot is located&lt;/li&gt;
&lt;li&gt;the hash of the parent commit (if any).&lt;/li&gt;
&lt;li&gt;the author/committer's name extracted from the &lt;code&gt;user.name&lt;/code&gt; and &lt;code&gt;user.email&lt;/code&gt; configuration settings.&lt;/li&gt;
&lt;li&gt;the timestamp of the commit.&lt;/li&gt;
&lt;li&gt;the GPG signature of the commit (if any).&lt;/li&gt;
&lt;li&gt;a blank line.&lt;/li&gt;
&lt;li&gt;the commit message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git stores commit object as blobs. We can inspect the content of a commit object using the &lt;code&gt;git cat-file&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@manekinekko/thundr
➜ git cat-file -p cc5e291471deb4f264cbad64d8a6570ca1487e83
tree 9ac02461fe7c94c834d28efa54952e8953002ef0
author Wassim Chegham &amp;lt;github@wassim.dev&amp;gt; 1645222639 +0100
committer Wassim Chegham &amp;lt;github@wassim.dev&amp;gt; 1645222639 +0100
gpgsig -----BEGIN PGP SIGNATURE-----

 iQIzBAA...
 -----END PGP SIGNATURE-----

my first commit


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

&lt;/div&gt;
&lt;p&gt;Here's what's actually happening in Git's internal database:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Note that in this diagram, we are using the first 8 bits of the SHA-1 hashes to identify Tree, Blob and Commit objects. Those are enough!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you may have guessed, Git does not really care about file names. It cares more about their content. Even if we copy a file, Git will not create a new entry in its database. It's just a matter of content and SHA-1 hashes.&lt;/p&gt;

&lt;p&gt;And if you're wondering what does Git do when we run a &lt;code&gt;git push&lt;/code&gt;? Git computes the delta between the two files, compresses that diff, and sends it to the server. Yes, Git does not send the whole file's content.&lt;/p&gt;

&lt;h1&gt;
  
  
  Voilà!
&lt;/h1&gt;

&lt;p&gt;That was it! Now we know what Git does behind the shadow when we create, edit, commit, and push files.&lt;/p&gt;

&lt;p&gt;Follow me on Twitter at &lt;a href="https://twitter.com/@manekinekko" rel="noopener noreferrer"&gt;@manekinekko&lt;/a&gt; for more content!&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>50+ FREE content for every developer!</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Wed, 18 Aug 2021 13:59:41 +0000</pubDate>
      <link>https://dev.to/wassimchegham/50-free-content-for-every-developer-40f1</link>
      <guid>https://dev.to/wassimchegham/50-free-content-for-every-developer-40f1</guid>
      <description>&lt;p&gt;Here is a list of 50+ FREE resources for developers. It includes free learning content for:&lt;/p&gt;

&lt;p&gt;✅ Git &amp;amp; GitHub&lt;br&gt;
✅ Programming&lt;br&gt;
✅ Python&lt;br&gt;
✅ Go&lt;br&gt;
✅ Rust&lt;br&gt;
✅ JavaScript &amp;amp; Typescript&lt;br&gt;
✅ Node.js&lt;br&gt;
✅ AI/ML&lt;br&gt;
✅ Docker &amp;amp; Kubernetes (k8s)&lt;br&gt;
✅ Blockchain &amp;amp; Ethereum&lt;br&gt;
✅ Quantum computing&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/introduction-to-github/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to GitHub&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn to use key GitHub features, including issues, notifications, branches, commits, and pull requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/paths/intro-to-vc-git/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to version control with Git&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Git is the leading version control tool, and it's essential for developers. Learn how to use Git to track your own changes and collaborate with others. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/contribute-open-source/?WT.mc_id=javascript-36613-wachegha"&gt;Contribute to an open-source project on GitHub&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to use GitHub to find open-source projects and tasks to contribute to. Discover how to create pull requests and communicate with project maintainers effectively to get your changes accepted... &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/introduction-to-github-visual-studio-code/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to GitHub in Visual Studio Code&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn to use the GitHub integration in Visual Studio Code, including authentication, publishing repos, and viewing your repo timeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/create-custom-github-actions/?WT.mc_id=javascript-36613-wachegha"&gt;Create and publish custom GitHub actions&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to write your own GitHub actions and create custom workflows. Learn best practices for documenting your action, and how to publish your action to the GitHub Marketplace. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/create-host-web-sites-github-pages/?WT.mc_id=javascript-36613-wachegha"&gt;Create and host web sites by using GitHub Pages&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to host your personal, organization, and project sites for free with GitHub Pages.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/implement-code-workflow/?WT.mc_id=javascript-36613-wachegha"&gt;Implement a code workflow in your build pipeline by using Git and GitHub&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to collaborate with others and merge only the highest quality code. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/web-development-101-introduction-programming/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to programming&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about programming languages and the tools that developers use to create software. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=javascript-36613-wachegha"&gt;Web Development for Beginners&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn the basics of web development, including programming languages and tools, and web accessibility. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=javascript-36613-wachegha"&gt;Build a simple website using HTML, CSS, and JavaScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get started with web development by learning how to use HTML, CSS, and JavaScript to build a website and to use developer tools in the browser to check your work. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/web-development-101-variables/?WT.mc_id=javascript-36613-wachegha"&gt;JavaScript variables and data types&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about the types of variables and their data types, along with how you can use them in JavaScript programming. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/web-development-101-arrays/?WT.mc_id=javascript-36613-wachegha"&gt;JavaScript arrays and loops&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about the structural format and uses of arrays in JavaScript, and how loops can assist you with repetitive tasks involving the data within arrays. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/web-development-101-functions/?WT.mc_id=javascript-36613-wachegha"&gt;Create modular code by using functions in JavaScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Functions are the building blocks for any application you'll create. You can create named, reusable sections of code with functions to help make it more readable and maintainable. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/web-development-101-accessibility/?WT.mc_id=javascript-36613-wachegha"&gt;Learn the basics of web accessibility&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are various tools and reports at your disposal that can highlight issues that need to be addressed. There are also standards like ARIA tags that will make your app usable by all. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/publish-app-service-static-web-app-api/?WT.mc_id=javascript-36613-wachegha"&gt;Publish an Angular, React, Svelte, or Vue JavaScript app to the cloud&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Automatically deploy and update a static web application from a GitHub repository. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/publish-static-web-app-api-preview-url/?WT.mc_id=javascript-36613-wachegha"&gt;Publish a serverless API with your JAMStack app&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Publish an Angular, React, Svelte, or Vue JavaScript app and API with Azure Static Web Apps and Azure Functions. Deploy your code from GitHub to a staging site using preview URLs. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/publish-static-web-app-authentication/?WT.mc_id=javascript-36613-wachegha"&gt;Authenticate users in your JAMStack app&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Use Azure Static Web Apps and Azure Functions to authenticate users. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/vue-get-started/?WT.mc_id=javascript-36613-wachegha"&gt;Get started with Vue&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Vue.js is a progressive web framework that allows developers to get up and running quickly, with just the addition of a script tag. You can use it to create large scalable applications. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/develop-web-apps-with-vs-code/?WT.mc_id=javascript-36613-wachegha"&gt;Develop web applications with Visual Studio Code&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to develop apps with Visual Studio Code, and use its features to create and test a very simple web application. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/build-mixed-reality-with-babylonjs/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to WebXR with Babylon.js&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this learning module, we'll introduce you to the core concepts of building Mixed Reality experiences with Babylon.js. We'll create a simple WebXR app that can be run cross-platform. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/paths/build-javascript-applications-nodejs/?WT.mc_id=javascript-36613-wachegha"&gt;Build JavaScript applications with Node.js&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Node.js provides a large set of built-in APIs that help you build various types of applications, command-line apps, web apps, and more... &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=javascript-36613-wachegha"&gt;Create a new Node.js project and work with dependencies&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Use dependencies from the npm registry to develop Node.js applications faster. Learn how to manage dependencies for your project. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/build-web-api-nodejs-express/?WT.mc_id=javascript-36613-wachegha"&gt;Build a web API with Node.js and Express&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Use Express for Node.js to build RESTful APIs. Create and configure middleware to add things like logging and authentication/authorization. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=javascript-36613-wachegha"&gt;Explore the art world by using RESTful APIs&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about how to build a basic API, how to query APIs, and authentication strategies in Python and JavaScript while discovering unique art by using museum APIs. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/typescript-generics/?WT.mc_id=javascript-36613-wachegha"&gt;Define generics in TypeScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Generics are code templates that you can define and reuse throughout your codebase. They provide a way to tell functions, classes, or interfaces what type you want to use when you call it. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/typescript-namespaces-organize-code/?WT.mc_id=javascript-36613-wachegha"&gt;Organize code using TypeScript namespaces&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;TypeScript provides two ways to organize code - namespaces and modules. This module explains how to organize TypeScript code using namespaces. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/typescript-declare-variable-types/?WT.mc_id=javascript-36613-wachegha"&gt;Declare variable types in TypeScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get an introduction to the types of space exploration problems that Python and data science can influence. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/introduction-python-nasa/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to Python for space exploration&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get an introduction to the types of space exploration problems that Python and data science can influence. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/python-install-vscode/?WT.mc_id=javascript-36613-wachegha"&gt;Set up your Python beginner development environment with Visual Studio Code&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get started with learning Python by installing and configuring the tools you'll need to build real applications. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/basic-python-nasa/?WT.mc_id=javascript-36613-wachegha"&gt;Write basic Python in Notebooks&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn the basics of Python using interactive Notebooks. Learn about some basic concepts of the Python programming language, using NASA as context to apply them. Actual engineers at NASA use these ideas everyday when working on projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/secret-message/?WT.mc_id=javascript-36613-wachegha"&gt;Crack the code and reveal a secret with Python and Visual Studio Code&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get a glimpse into the popular Python programming language with this introductory lesson that requires no coding experience. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/go-control-flow/?WT.mc_id=javascript-36613-wachegha"&gt;Use control flows in Go&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to write programs in the Go way by using fundamental control flows like &lt;code&gt;if/else&lt;/code&gt;, &lt;code&gt;switches&lt;/code&gt;, and &lt;code&gt;for&lt;/code&gt; as well as another set of keywords.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/go-write-test-program/?WT.mc_id=javascript-36613-wachegha"&gt;Write and test a program in Go&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn step by step how to write a Go program, how to structure the files, how to compile the files, how to run the program, and how to test the program.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/go-data-types/?WT.mc_id=javascript-36613-wachegha"&gt;Use data types and structs, arrays, slices, and maps in Go&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about structs, arrays, slices, and maps. Understand the difference between them and when to use one type over the other. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/go-errors-logs/?WT.mc_id=javascript-36613-wachegha"&gt;Implement error handling and logging in Go&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Understand how to handle errors and log helpful information in your Go programs. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/rust-introduction/?WT.mc_id=javascript-36613-wachegha"&gt;What is Rust&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A quick introduction to Rust language features and how Rust compares with other programming languages. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/paths/rust-first-steps/?WT.mc_id=javascript-36613-wachegha"&gt;Take your first steps with Rust&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Interested in learning a new programming language that's growing in use and popularity? Start here! Lay the foundation of knowledge you need to build fast and effective programs in Rust. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/rust-understand-common-concepts/?WT.mc_id=javascript-36613-wachegha"&gt;Understand common concepts in Rust&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn the basics of Rust. Explore variables, data types, structs, enums, functions, indexing, hash maps, and flow control. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/rust-set-up-environment/?WT.mc_id=javascript-36613-wachegha"&gt;Set up the Rust development environment&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to set up the Rust development environment, write a program, and use the Cargo build system. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/intro-to-docker-containers/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to Docker containers&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Describes the benefits of using Docker containers as a containerization platform. Discuss the infrastructure provided by the Docker platform. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/use-docker-container-dev-env-vs-code/?WT.mc_id=javascript-36613-wachegha"&gt;Use a Docker container as a development environment with Visual Studio Code&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Describes the benefits of using Docker containers as a containerization platform. Discuss the infrastructure provided by the Docker platform. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/intro-to-azure-kubernetes-service/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to Azure Kubernetes Service&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Determine the types of business problems that can be solved using Kubernetes. Describe the benefits of container orchestration with features like deployment management, automatic updates, and self-healing. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/get-started-ai-fundamentals/?WT.mc_id=javascript-36613-wachegha"&gt;Get started with AI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With AI, we can build solutions that seemed like science fiction a short time ago; enabling incredible advances in health care, financial management, environmental protection, and other areas to make a better world for everyone. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/machine-learning-model-nasa/?WT.mc_id=javascript-36613-wachegha"&gt;Build a machine learning model&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this free course, you focus on a local analysis of your data by using scikit-learn, and use a decision tree classifier to gain knowledge from raw weather and rocket launch data.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/intro-machine-learning-pytorch/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to PyTorch&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn how to build machine learning models with PyTorch. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/paths/pytorch-fundamentals/?WT.mc_id=javascript-36613-wachegha"&gt;PyTorch Fundamentals&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn the fundamentals of deep learning with PyTorch! This beginner-friendly free course will introduce key concepts to building machine learning models in multiple domains include speech, vision, and natural language processing. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/intro-computer-vision-pytorch/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to Computer Vision with PyTorch&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get an introduction to Computer Vision using one of the most popular deep learning frameworks, PyTorch! Learn about image classification tasks and convolutional neural networks. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/blockchain-ethereum-networks/?WT.mc_id=javascript-36613-wachegha"&gt;Connect and deploy to Ethereum networks&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about and use Ethereum networks for development, testing, and production. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/intro-to-blockchain/?WT.mc_id=javascript-36613-wachegha"&gt;Introduction to blockchain&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Discover how blockchain protocols enable trust. Learn to assess scenarios for when to use blockchain and decide if it's right for your solution. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/paths/quantum-computing-fundamentals/?WT.mc_id=javascript-36613-wachegha"&gt;Quantum computing foundations&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;7+ hours of FREE content about fundamental concepts of quantum computing.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/qsharp-create-first-quantum-development-kit/?WT.mc_id=javascript-36613-wachegha"&gt;Create your first Q# program by using the Quantum Development Kit&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get started with Q# programming by building a quantum random number generator.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/learn/modules/run-algorithms-quantum-hardware-azure-quantum/?WT.mc_id=javascript-36613-wachegha"&gt;Run algorithms on quantum hardware by using Azure Quantum&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Get started with quantum computing on Azure Quantum and learn how to create and run Q# quantum programs on quantum computers in the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Have fun!
&lt;/h2&gt;

&lt;p&gt;Feel free to reach out on Twitter at &lt;a href="https://twitter.com/manekinekko"&gt;@manekinekko&lt;/a&gt;. You can also follow my work at &lt;a href="https://wassim.dev"&gt;wassim.dev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>azure</category>
    </item>
    <item>
      <title>10 Things To Know About Azure Static Web Apps 🎉</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Mon, 05 Jul 2021 13:35:13 +0000</pubDate>
      <link>https://dev.to/azure/10-things-to-know-about-azure-static-web-apps-3n4i</link>
      <guid>https://dev.to/azure/10-things-to-know-about-azure-static-web-apps-3n4i</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/?WT.mc_id=javascript-23540-wachegha"&gt;Azure Static Web Apps&lt;/a&gt; allows any developer to build modern web &lt;br&gt;
applications that are automatically published from changes made in the git repository, and much more...&lt;/p&gt;

&lt;p&gt;Here are 10 things to know to get started with Azure Static Web Apps!&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/overview?WT.mc_id=javascript-23540-wachegha"&gt;What's Azure Static Web Apps?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940310672695296-939" src="https://platform.twitter.com/embed/Tweet.html?id=1377940310672695296"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940310672695296-939');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940310672695296&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/front-end-frameworks?WT.mc_id=javascript-23540-wachegha"&gt;What contents can be deployed to Azure Static Web Apps?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940315856908288-993" src="https://platform.twitter.com/embed/Tweet.html?id=1377940315856908288"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940315856908288-993');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940315856908288&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/add-api?WT.mc_id=javascript-23540-wachegha&amp;amp;tabs=vanilla-javascript"&gt;Does Azure Static Web Apps support serverless APIs?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940320701284353-534" src="https://platform.twitter.com/embed/Tweet.html?id=1377940320701284353"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940320701284353-534');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940320701284353&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/github-actions-workflow?WT.mc_id=javascript-23540-wachegha"&gt;How does Azure Static Web Apps work?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940326783025154-521" src="https://platform.twitter.com/embed/Tweet.html?id=1377940326783025154"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940326783025154-521');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940326783025154&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/getting-started?tabs=vanilla-javascript&amp;amp;WT.mc_id=javascript-23540-wachegha"&gt;What devtools does Azure Static Web Apps support?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940332554375170-384" src="https://platform.twitter.com/embed/Tweet.html?id=1377940332554375170"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940332554375170-384');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940332554375170&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/custom-domain?WT.mc_id=javascript-23540-wachegha&amp;amp;tabs=azure-dns"&gt;How about custom domain names?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940337000386563-171" src="https://platform.twitter.com/embed/Tweet.html?id=1377940337000386563"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940337000386563-171');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940337000386563&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/configuration?WT.mc_id=javascript-23540-wachegha"&gt;How to configure an Azure Static Web Apps app?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940343178559489-133" src="https://platform.twitter.com/embed/Tweet.html?id=1377940343178559489"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940343178559489-133');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940343178559489&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/local-development?WT.mc_id=javascript-23540-wachegha"&gt;What about local dev?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940351168708608-280" src="https://platform.twitter.com/embed/Tweet.html?id=1377940351168708608"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940351168708608-280');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940351168708608&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/review-publish-pull-requests?WT.mc_id=javascript-23540-wachegha"&gt;Does Azure Static Web Apps support PR changes preview?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940357112070151-773" src="https://platform.twitter.com/embed/Tweet.html?id=1377940357112070151"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940357112070151-773');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940357112070151&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-authorization?tabs=javascript&amp;amp;WT.mc_id=javascript-23540-wachegha"&gt;How to secure apps with Azure Static Web Apps?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940363546071044-194" src="https://platform.twitter.com/embed/Tweet.html?id=1377940363546071044"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940363546071044-194');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940363546071044&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/?WT.mc_id=javascript-23540-wachegha"&gt;Azure Static Web Apps documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/free/?WT.mc_id=javascript-23540-wachegha"&gt;Get started with 12 months of free services&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deploy your favorite framework
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/deploy-nextjs?WT.mc_id=javascript-23540-wachegha"&gt;Deploy static-rendered Next.js websites on Azure Static Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/deploy-nuxtjs?WT.mc_id=javascript-23540-wachegha"&gt;Deploy server-rendered Nuxt.js websites on Azure Static Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/publish-app-service-static-web-app-api/?WT.mc_id=javascript-23540-wachegha"&gt;Publish an Angular, React, Svelte, or Vue JavaScript app with Azure Static Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/create-deploy-static-webapp-gatsby-app-service/?WT.mc_id=javascript-23540-wachegha"&gt;Create and publish a static web app with Gatsby and Azure Static Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/publish-app-service-static-web-app-api-dotnet/?WT.mc_id=javascript-23540-wachegha"&gt;Publish a Blazor WebAssembly app and .NET API with Azure Static Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Have fun!
&lt;/h2&gt;

&lt;p&gt;Feel free to reach out on Twitter at &lt;a href="https://twitter.com/manekinekko"&gt;@manekinekko&lt;/a&gt; if you want to get started with Azure Static Web Apps. You can also follow my work at &lt;a href="https://wassim.dev"&gt;wassim.dev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>staticwebapps</category>
    </item>
    <item>
      <title>The Subtle Art of Being A Developer Advocate | What is a Developer Advocate?</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Wed, 21 Apr 2021 10:32:00 +0000</pubDate>
      <link>https://dev.to/wassimchegham/the-subtle-art-of-being-a-developer-advocate-gdg</link>
      <guid>https://dev.to/wassimchegham/the-subtle-art-of-being-a-developer-advocate-gdg</guid>
      <description>&lt;p&gt;A few years ago I wrote this article called "&lt;a href="https://www.freecodecamp.org/news/what-the-heck-is-a-developer-advocate-87ab4faccfc4/" rel="noopener noreferrer"&gt;What the heck is a developer advocate?&lt;/a&gt;" which tried to help people in the tech industry understand what this role entails. Yet, I still get tons of questions on Twitter about this role.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/wassimchegham" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F13081%2F0a029e3e-206b-41b5-83b3-52e39a29c4cb.jpg" alt="wassimchegham"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/wassimchegham/what-the-heck-is-a-developer-advocate-4l2a" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;What the heck is a Developer Advocate?&lt;/h2&gt;
      &lt;h3&gt;Wassim Chegham ・ Jun 1 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devrel&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#discuss&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#writing&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h5&gt;
  
  
  This article is also available in other languages
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;🇯🇵 &lt;a href="https://qiita.com/kamimi01/items/17fe79dc5522648e2a1d" rel="noopener noreferrer"&gt;Japanese&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, I am going to try to demystify the role of a Developer Advocate by giving, this time, concrete examples of tasks and activities I do on my day-to-day job working as a Senior Developer Advocate at Microsoft, and as someone who's been doing developer advocacy since 2015.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h5&gt;
  
  
  Disclaimer:
&lt;/h5&gt;

&lt;p&gt;Views expressed in this post are my own and do not represent my employer nor my colleagues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's first shed some light on the difference between a Developer Advocate and a Technology Evangelist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Advocate and Technology Evangelist
&lt;/h2&gt;

&lt;p&gt;There is a certain confusion between Developer Advocacy and Technology Evangelism. Let's look at both terms' definitions.&lt;/p&gt;

&lt;p&gt;According to Wikipedia, the term "tech evangelist" was invented by Apple as part of their initiative to persuade developers to create apps for Macintosh. The verb "persuade" is very important because it implies that an Evangelist would try to convince developers to adopt a certain technology without necessarily listening, or caring about their needs or opinion.&lt;/p&gt;

&lt;p&gt;This is exactly the opposite of what Advocacy is all about!&lt;/p&gt;

&lt;p&gt;"Advocacy" is an old concept that comes from the Medieval Latin word "advocare" which means "to add a voice". The term "advocate" comes from Old French word "avocat" which means "a lawyer". So, an Advocate literarily means someone who "pleads a case or a cause", who "argues that something needs to be changed or improved".&lt;/p&gt;

&lt;p&gt;Applied to the tech industry, these two terms may seem quite similar but the subtle difference lies in the fact that a Tech. Evangelist role is done one-way only (outbound), and a Developer Advocate role is considered two-way (outbound and inbound). In other words, a Tech Evangelist would typically be interested in convincing developers that certain technology is what they need. A Developer Advocate would typically be interested in listening to developers' needs and providing them with the most adequate help. A Developer Advocate also collects developers' feedback and advocates for them internally.&lt;/p&gt;

&lt;p&gt;This is why the two titles should be used wisely.&lt;/p&gt;

&lt;p&gt;However, I want to take a step back to highlight that beyond the theoretical definition, it turns out that in practice there are always some exceptions to what the job titles may entail. I know some of my friends whose job title was Tech Evangelist, but the work they did was more of a Developer Advocate (and vice-versa). What really matters is not the job title but rather what you do to help developers be successful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gu61d6gy428zj4y83zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gu61d6gy428zj4y83zz.png" alt="Alt Text" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Advocates and Marketers
&lt;/h2&gt;

&lt;p&gt;Whenever you ask a Developer Advocate to define their role, each one of them will give you a different answer, which is confusing. That's common. But, have you ever wondered why? The main reason for this is that many companies tend to hire Developer Advocates to do different kinds of tasks, from sales to communication and, most commonly, Marketing. Why Marketing? Because companies usually spend between 5 to 12% of their revenue on Marketing, and when they need to reach to more developers, they usually would hire someone as a "Developer Advocate" (or any other variation of this title) who reports to marketing (or business unit) and is driven by marketing and sales KPIs (Key Performance Indicators). Most importantly, in this situation, this role is usually led outside of the product engineering team, which might be problematic (more on this below).&lt;/p&gt;

&lt;p&gt;Don't get me wrong, there is nothing bad with companies using marketing and sales to reach out to developers, but doing this under the Developer Advocacy titles umbrella isn't doing anyone a favor. Either way, this usually turns out to be a bad move because not all developers are great at marketing (or sales) and end up not performing well. Developers have excellent ingenuity and creativity but some of us may lack basic business marketing skills. Why do you think most successful startups are founded by at least 2 people? If I were good at Marketing or Sales I would have done a better job promoting my own open-source projects, yet you've never heard about &lt;a href="https://xlayers.dev" rel="noopener noreferrer"&gt;xlayers.dev&lt;/a&gt;. Do you?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft79tsnseb70spzk8y936.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft79tsnseb70spzk8y936.png" alt="Alt Text" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When reaching to developers, Marketing teams should collaborate with Developer Advocates to help them tailor the message for developers. Why? Because Developer Advocates are, before anything else, developers themselves and speak the same language as other developers.&lt;/p&gt;

&lt;p&gt;In many other cases, companies simply ignore the true meaning behind Advocacy and end up making their own definition, based on their business needs. That's why almost no Developer Advocate understands what their role is or should be. I hope this article would help somehow!&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Advocates and Developer Relations
&lt;/h2&gt;

&lt;p&gt;Put simply, Developer Relations is the umbrella term for the teams including Developer Advocates, Community Managers, and any team whose responsibility is to create and foster communities of developers. Some larger companies, as we do at Microsoft, also include teams responsible for documentation, events, and social media.&lt;/p&gt;

&lt;p&gt;So, a Developer Advocacy team is a tiny subset of Developer Relations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5d20yko6tc28sy7s0or4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5d20yko6tc28sy7s0or4.png" alt="Alt Text" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's my role at Microsoft?
&lt;/h2&gt;

&lt;p&gt;As Developer Advocates, we may not agree on what we do or should be doing, but we all agree on one common definition:&lt;/p&gt;

&lt;p&gt;"Our role is to act as the bridge between internal engineering teams and our developer community. We also advocate for developers internally".&lt;/p&gt;

&lt;p&gt;Before I describe the work I do at Microsoft, let me give you some context: I was hired because of my JavaScript skills and my close relationship with the JavaScript developer community. I currently work as part of the JavaScript advocacy team. Our team belongs to the Developer Relation organization which is part of the Azure Engineering department at Microsoft.&lt;/p&gt;

&lt;p&gt;My day-to-day job is to advocate for JavaScript developers internally at Microsoft, act as their voice during product team meetings or internal studies. Externally, I support and gather JavaScript developers' feedback so we can improve our products and services. Basically, I help JavaScript developers be successful using Microsoft Clouds, services, and open-source developer tools.&lt;/p&gt;

&lt;p&gt;You've probably seen that Microsoft is raising the bar for its products and to achieve this, the company is investing in Developers and open-source. That's why our &lt;strong&gt;Developer Relations team's mission is to empower developers to achieve more&lt;/strong&gt;. Our larger Developer Advocacy team (or Cloud Developer Advocacy, as we refer to it internally because we are also helping DevOps teams) is composed of multiple sub-teams focusing on different developer communities such as Rust, Java, Python...etc, but also audiences like students, academia, and startups.&lt;/p&gt;

&lt;p&gt;The mission of the Cloud Developer Advocacy team is to win the hearts and minds of Developers through authenticity, community, and technical engagement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftebfywwy2jxt22tdi1yd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftebfywwy2jxt22tdi1yd.png" alt="Alt Text" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What my typical day looks like as a Developer Advocate?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The tasks I am going to disclose below are the activities "I" regularly do. My team members may or may not do the "exact" same activities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Creating content
&lt;/h3&gt;

&lt;p&gt;I participate in writing technical documentation and content in different formats used by engineers worldwide. This can be as simple as updating existing documentation or creating full documentation like the &lt;a href="https://docs.microsoft.com/azure/static-web-apps/?WT.mc_id=javascript-0000-wachegha" rel="noopener noreferrer"&gt;Azure Static Web Apps documentation&lt;/a&gt; that my team and I collaborated on with the Microsoft documentation team.&lt;/p&gt;

&lt;p&gt;Other content also includes creating and hosting workshops for developers, coding challenges as well as snackable content that I regularly publish on Twitter.&lt;/p&gt;

&lt;p&gt;Here are a couple of recent examples:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1377940304712585217-576" src="https://platform.twitter.com/embed/Tweet.html?id=1377940304712585217"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1377940304712585217-576');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1377940304712585217&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;And this one:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1281704000572858375-695" src="https://platform.twitter.com/embed/Tweet.html?id=1281704000572858375"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1281704000572858375-695');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1281704000572858375&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  Public speaking
&lt;/h3&gt;

&lt;p&gt;Probably one of the highly visible activities that most Developer Advocates are notorious for is public events. That's also part of my work, giving technical talks, and keynotes at international conferences and events. Basically going where the developers are. This also includes live streamings, podcasts, and similar types of mediums.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building tools in the open
&lt;/h3&gt;

&lt;p&gt;Besides the work I do for my company, I am also an active member of the open-source community, and most of the work I do for my employer is done in the Open as well. This means that my job is also to help developers be successful using the tools that help them use and integrate Azure with their products and applications. My recent tools include &lt;a href="https://www.hexa.run" rel="noopener noreferrer"&gt;https://www.hexa.run&lt;/a&gt;, the &lt;a href="https://github.com/nestjs/azure-database" rel="noopener noreferrer"&gt;Nest.JS libraries for Azure CosmosDB&lt;/a&gt;, and &lt;a href="https://github.com/nestjs/azure-storage" rel="noopener noreferrer"&gt;Azure Storage&lt;/a&gt;. You can check my other open-source work at &lt;a href="https://wassim.dev" rel="noopener noreferrer"&gt;wassim.dev&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Product feedback
&lt;/h3&gt;

&lt;p&gt;Continuously improving the products and services that developers use is one of our team's core missions. I spend the majority of my time interacting with developers and engineers through social media, or at online or onsite events. I get tons of requests from developers who are asking questions, reporting issues, or asking for feature requests. I always try to help them first, if I am familiar with the product. For major issues or popular feature requests, I create a work item on our internal dashboard and collaborate closely with the product team to improve the experience based on the feedback gathered from the community. &lt;/p&gt;

&lt;p&gt;This is really where, as a Developer Advocate, I can advocate for JavaScript developers and act as their voice internally. A recent example of this is with the Azure Static Web Apps product where I spent the last year and a half contributing to the product and helping the engineering team designing part of the service, providing critical feedback, trying early access features, and implementing the CLI developer tool. &lt;/p&gt;

&lt;h3&gt;
  
  
  Shipping products
&lt;/h3&gt;

&lt;p&gt;One other aspect of being a Developer Advocate that many people probably ignore is that as Developer Advocates, some of us also contribute to creating and shipping products, either for internal or external use, or both. For the last 6 months, I had the opportunity to create, lead and ship the &lt;a href="https://github.com/Azure/static-web-apps-cli" rel="noopener noreferrer"&gt;official Azure Static Web Apps CLI&lt;/a&gt; to allow developers to run and debug their apps locally. &lt;/p&gt;

&lt;p&gt;I think that's something that every Developer Advocate should be doing because it's essential to understand how a product or a service is designed, implemented, know its strengths and weaknesses. That a knowledge that we will have to have if we need to better help developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Being the Customer Zero
&lt;/h3&gt;

&lt;p&gt;A good amount of my time is spent improving Azure products and services, and working with Azure engineering teams across the company to try out new features, provide feedback about JavaScript developers' expectations. The products I've worked on during the last 2 years were: Azure Functions,  Azure Storage, Azure Cosmos DB, Azure IoT, Azure Static Web Apps, GitHub Codespaces, and npm. Acting as "customer zero" is a really great way to have a tremendous impact on a product before it gets released. One example of this is Azure Static Web Apps: my team and I are working closely with the engineering team to help provide the best developer experience for the Web developers community who will be using this service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constantly learning
&lt;/h3&gt;

&lt;p&gt;Since JavaScript is widely used in many different areas, the technical stacks that I usually focus on include Node.js, TypeScript, Serverless, IoT architectures, databases, and hosting. I also must be honest, I've also been fascinated by the Rust programming language and I am planning to start learning it in the near future! Luckily my colleagues on the Rust Developer Advocacy team have built this &lt;a href="https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/?WT.mc_id=javascript-00000-wachegha" rel="noopener noreferrer"&gt;5 hours free guide about Rust for beginners&lt;/a&gt;. It looks like a good start for me! &lt;/p&gt;

&lt;h3&gt;
  
  
  Creating and improving official docs
&lt;/h3&gt;

&lt;p&gt;As a Developer Advocate, I also spend some time creating comprehensive technical guides for many Microsoft Clouds services. One of the latest guides that my team and I worked on for 4 months is &lt;a href="https://docs.microsoft.com/en-us/learn/paths/build-javascript-applications-nodejs/" rel="noopener noreferrer"&gt;the Node.js Learn Path&lt;/a&gt;. The good thing about our official documentation is that is open and anyone can help improve it. We also regularly participate in this and send Pull Requests to improve and update the docs at &lt;a href="http://docs.microsoft.com/?WT.mc_id=javascript-0000-wachegha" rel="noopener noreferrer"&gt;http://docs.microsoft.com&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helping others grow
&lt;/h3&gt;

&lt;p&gt;Another aspect of my job – well it's not part of my job description per se – but it's really important to me: that's helping people around me grow and be successful. As someone from a minority group, who's succeeded in the tech industry, I genuinely care about diversity and inclusion. So helping others grow professionally and personally is part of who I am. &lt;/p&gt;

&lt;p&gt;I do internal mentoring through an official mentorship program at Microsoft. Externally, I am mentoring people from the community who are new to programming and want to switch careers, and also people who want to start contributing to open-source. I obviously can't disclose all the details but I basically help and advise my mentees about programming, tech, and career growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Business and OKRs
&lt;/h3&gt;

&lt;p&gt;Let me just be clear, every company's goal is to do business. Your company isn't simply paying you to work on open-source, or travel to events. It's investing money in you and is expecting an ROI (Return on investment). But we all know that the ROI of a community and relationship building is not that easy to measure or quantify. &lt;/p&gt;

&lt;p&gt;We are continuously reviewing and updating our team's OKRs (Objectives &amp;amp; Key Results), strategy, and planning to align with the company's broader strategy while giving everyone on the team the freedom to connect with developers in authentic ways, have meaningful conversations, help them solve their problems, and being their advocate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Engineers' main responsibilities are to own, design, implement, and ship products, and for those who want to share their experience with the developer community, they are able to do it. Developer Advocates are not different than engineers except that their responsibilities are not working full time on products but help the engineering teams reach out and listen to developers' needs in order to create the best experience for everyone.&lt;/p&gt;

&lt;h1&gt;
  
  
  Developer Advocates are engineers who love to learn in the open.
&lt;/h1&gt;

&lt;p&gt;That’s my story. If you like or agree with what you've just read, our team is hiring. Check out our page &lt;a href="https://aka.ms/awesomejobs" rel="noopener noreferrer"&gt;https://aka.ms/awesomejobs&lt;/a&gt; ❤️&lt;/p&gt;




&lt;h4&gt;
  
  
  Bonus: The Developer Advocate Iceberg
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbwn6178yb7do2e8bhk8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbwn6178yb7do2e8bhk8.jpg" alt="Alt Text" width="800" height="915"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Feel free to reach out on Twitter at &lt;a href="https://twitter.com/manekinekko" rel="noopener noreferrer"&gt;@manekinekko&lt;/a&gt; if you are still curious about Developer Advocacy. You can also follow my work at &lt;a href="https://wassim.dev" rel="noopener noreferrer"&gt;wassim.dev&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Assets used in this blog are licensed under the Adobe Standard License.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>career</category>
      <category>writing</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Introducing: Open Web Docs!</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Fri, 29 Jan 2021 21:06:49 +0000</pubDate>
      <link>https://dev.to/wassimchegham/introducing-open-web-docs-4g1m</link>
      <guid>https://dev.to/wassimchegham/introducing-open-web-docs-4g1m</guid>
      <description>&lt;p&gt;Open Web Docs is a new collective project between &lt;a href="https://web.dev/open-web-docs/"&gt;Google&lt;/a&gt;, &lt;a href="https://blogs.windows.com/msedgedev/2021/01/25/welcome-open-web-docs/"&gt;Microsoft&lt;/a&gt;, Mozilla, &lt;a href="https://press.coil.com/press-news/coil-is-proud-to-support-open-web-docs"&gt;Coil&lt;/a&gt;, &lt;a href="https://www.w3.org/blog/2021/01/welcome-to-open-web-docs/"&gt;W3C&lt;/a&gt;, Samsung, and &lt;a href="https://www.igalia.com/2021/01/25/Open-Web-Docs.html"&gt;Igalia&lt;/a&gt;, to support the creation and maintenance of strategic web platform documentation. &lt;/p&gt;

&lt;p&gt;Open Web Docs is dedicated to supporting browser-agnostic, community-driven, and high-quality web developer documentation. &lt;strong&gt;This new initiative is not a new documentation site, instead, Open Web Docs is committed to improving existing platforms through many different community contributions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1353748877111918593-977" src="https://platform.twitter.com/embed/Tweet.html?id=1353748877111918593"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1353748877111918593-977');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1353748877111918593&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Open Web Docs collaborators are supported by sponsors like Coil, Google and Microsoft, Igalia, and many other donors on Open Collective.&lt;/p&gt;

&lt;p&gt;Open Web Docs long term roadmap will be published soon. However, the   &lt;a href="https://github.com/openwebdocs/project/blob/main/2021-goals.md"&gt;initial goals&lt;/a&gt; are focused on supporting MDN's recent &lt;a href="https://hacks.mozilla.org/2020/12/welcome-yari-mdn-web-docs-has-a-new-platform/"&gt;infrastructure transition&lt;/a&gt; and contributing to core web technology documentation, browser compatibility data, and JavaScript documentation on MDN Web Docs. &lt;/p&gt;

&lt;p&gt;You can learn more or join the adventure at the &lt;a href="https://opencollective.com/open-web-docs"&gt;Open Web Docs collective&lt;/a&gt; page, on &lt;a href="https://github.com/openwebdocs"&gt;GitHub&lt;/a&gt;, or by following &lt;a href="https://twitter.com/OpenWebDocs"&gt;@OpenWebDocs&lt;/a&gt; for more exciting updates.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Build a DIY teleprompter for under $20 in less than 20min</title>
      <dc:creator>Wassim Chegham</dc:creator>
      <pubDate>Tue, 27 Oct 2020 15:16:11 +0000</pubDate>
      <link>https://dev.to/wassimchegham/build-a-diy-teleprompter-for-under-20-in-less-than-20min-5h01</link>
      <guid>https://dev.to/wassimchegham/build-a-diy-teleprompter-for-under-20-in-less-than-20min-5h01</guid>
      <description>&lt;p&gt;I am not really good at memorising scripts while recording videos of me talking to a camera. I usually spend hours recording multiple shots just to get 2 min of a video done right!&lt;/p&gt;

&lt;p&gt;I tweeted about this recently:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1318153290249625602-184" src="https://platform.twitter.com/embed/Tweet.html?id=1318153290249625602"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1318153290249625602-184');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1318153290249625602&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;After publishing this tweet, my friend &lt;a href="https://twitter.com/alexismp" rel="noopener noreferrer"&gt;Alexis&lt;/a&gt; responded:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1318154652572147714-656" src="https://platform.twitter.com/embed/Tweet.html?id=1318154652572147714"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1318154652572147714-656');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1318154652572147714&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;He actually knows me well, because that what exactly I had in mind. I like to build stuff! So let's build a cheap teleprompter, for under $20, in 20 minutes or less.&lt;/p&gt;

&lt;p&gt;By the way, here is the final result (in a video):&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1319251368666947585-885" src="https://platform.twitter.com/embed/Tweet.html?id=1319251368666947585"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1319251368666947585-885');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1319251368666947585&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  What's a teleprompter?
&lt;/h3&gt;

&lt;p&gt;According to Wikipedia: "A teleprompter, also known as an autocue, is a display device that prompts the person speaking with an electronic visual text of a speech or script."&lt;/p&gt;

&lt;p&gt;Because a picture is worth a thousand words, I made a simple drawing explaining how a teleprompter works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkn3uy2hn3bdvg70i16f6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkn3uy2hn3bdvg70i16f6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Components you will need
&lt;/h3&gt;

&lt;h4&gt;
  
  
  x2 wooden pictures frames with clear glass
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvu47q516tb402wfd9mt4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvu47q516tb402wfd9mt4.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From your local hardware store, buy 2 wooden picture frames. Make sure the frames are in wood and the glazing is a clear glass (not plastic). The backing board should be a solid wood (but this is not mandatory). Also, the picture frames should be large enough to hold your monitor/tablet/phone or any device that you will use as a display. Mines were large enough to hold an iPad Pro. But you can choose any other format.&lt;/p&gt;

&lt;h4&gt;
  
  
  x3 pairs of solid brass butt hinges
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fis4j9obxqy5skcxyvcgt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fis4j9obxqy5skcxyvcgt.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will also need 2 or 3 pairs of solid brass butt hinges that we will use to hold the 2 frames together. My frames are 24x30 cm (9x11"), so I used 3 pairs of 25mm hinges.&lt;/p&gt;

&lt;p&gt;Make sure the screws that come with the hinges are not too long so they don't pass all the way through the frames!&lt;/p&gt;

&lt;h4&gt;
  
  
  A dark piece of sheet
&lt;/h4&gt;

&lt;p&gt;We will need a dark piece of sheet to protect the teleprompter glass against any reflections coming from our light sources.&lt;/p&gt;

&lt;h4&gt;
  
  
  The rest...
&lt;/h4&gt;

&lt;p&gt;Next, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A piece of small wood or a wooden stick.&lt;/li&gt;
&lt;li&gt;A black aerosol spray paint can.&lt;/li&gt;
&lt;li&gt;Your usual camera setup.&lt;/li&gt;
&lt;li&gt;A device with a screen. This could be a tablet, a phone or an external monitor connected to a computer.&lt;/li&gt;
&lt;li&gt;A teleprompter app (with "mirror" support).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How-to...
&lt;/h2&gt;

&lt;p&gt;1- Carefully disassemble the picture frames. Keep only 1 glazing panel and 1 baking board (and the 2 frames, obviously!). You can get rid of all the other components or use then as spare parts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnp6u1bq13mwluzngsanp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnp6u1bq13mwluzngsanp.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2- After you removed the glass panel, put it in a secure place, we will use it later. Now, hold the 2 frames together "like a closed book" and place the hinges on one of the sides. Make sure to place frame A on top of frame B, with both frames facing down (see figure):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr9y3v78fjcnviah322e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr9y3v78fjcnviah322e3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHY?&lt;/strong&gt; Inside the frame B, we will place our screen/tablet which will sit on the baking board. Frame A will be placed on top of frame B, with the glass facing down, and tilted at 45 degrees, like an open book.&lt;/p&gt;

&lt;p&gt;3- Once you marked where the hinges are going to be placed, drill very tiny holes that will hold the screws. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjgu7l98443hyejpw817l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjgu7l98443hyejpw817l.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4- Then, tightly screw all 3 hinges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxjx74tb8n8jfkrmz0gb1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxjx74tb8n8jfkrmz0gb1.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5- If some of the components are in white or any other clear color, paint them all in black so that all components (except the glass) are dark. This would help absorbe any lighting coming from our light sources.&lt;/p&gt;

&lt;p&gt;Note: I painted both back panels just to in case I needed a spare one!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9bygy3x0vhi3olqfix8d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9bygy3x0vhi3olqfix8d.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6- Once all components are painted and dried, place the glazing panel back on frame A, and the back panel on frame B.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk3oq44ap72fzfdnlflq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk3oq44ap72fzfdnlflq0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7- We are almost done. Using a small stick of wood (or any other item that you have on hand). Frame A should be tilted at 45 degrees, but feel free to adjust to your convenience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7el60rytvtj0s0q5ajk1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7el60rytvtj0s0q5ajk1.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8- If you have any light sources placed behind the camera, you would see reflections on the glazing panel on frame A.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpfbpd1dr7cjkbtuc3fdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpfbpd1dr7cjkbtuc3fdn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;9- To avoid this, place a dark piece of sheet between the camera and the back of frame A.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy6v3guofrpki67zwqc47.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy6v3guofrpki67zwqc47.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;10- Lastly, place your screen/tablet/monitor inside frame B with the screen facing up, and bump up the brightness. Open your teleprompter app and adjust the text size. Make also sure to turn on the "mirror" mode, or you can practice reading reverse text (😂)!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you can skip steps 2-4 if you can buy an already hinged picture frame with glass front!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Congratulations!
&lt;/h3&gt;

&lt;p&gt;You just built your DIY teleprompter! Congratulations!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fscfikl13jii5j56zectj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fscfikl13jii5j56zectj.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please share your creations and show us how is your teleprompter look like.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me at &lt;a href="https://twitter.com" rel="noopener noreferrer"&gt;@manekinekko&lt;/a&gt; for more hacks and DIY tutorials.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>todayilearned</category>
    </item>
  </channel>
</rss>
