<?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: Peng Qian</title>
    <description>The latest articles on DEV Community by Peng Qian (@qtalen).</description>
    <link>https://dev.to/qtalen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg</url>
      <title>DEV Community: Peng Qian</title>
      <link>https://dev.to/qtalen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/qtalen"/>
    <language>en</language>
    <item>
      <title>The concept of Loop Engineering has been getting a lot of buzz lately, so I decided to give it a shot in OpenCode. The results were surprisingly good:</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Thu, 16 Jul 2026 07:41:44 +0000</pubDate>
      <link>https://dev.to/qtalen/the-concept-of-loop-engineering-has-been-getting-a-lot-of-buzz-lately-so-i-decided-to-give-it-a-gb7</link>
      <guid>https://dev.to/qtalen/the-concept-of-loop-engineering-has-been-getting-a-lot-of-buzz-lately-so-i-decided-to-give-it-a-gb7</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk" class="crayons-story__hidden-navigation-link"&gt;How I Built a Fully Automated Coding Loop in OpenCode&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/qtalen" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" alt="qtalen profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/qtalen" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Peng Qian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Peng Qian
                
              
              &lt;div id="story-author-preview-content-4156106" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/qtalen" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Peng Qian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 16&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk" id="article-link-4156106"&gt;
          How I Built a Fully Automated Coding Loop in OpenCode
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>automation</category>
      <category>coding</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Built a Fully Automated Coding Loop in OpenCode</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Thu, 16 Jul 2026 07:41:10 +0000</pubDate>
      <link>https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk</link>
      <guid>https://dev.to/qtalen/how-i-built-a-fully-automated-coding-loop-in-opencode-22jk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you've been following the AI agent space recently, you've probably heard the term Loop Engineering. Claude Code and OpenClaw both mention it.&lt;/p&gt;

&lt;p&gt;But nobody really explains what it means.&lt;/p&gt;

&lt;p&gt;Until Andrew Ng posted a clear breakdown of what Loop Engineering actually is. That post gave me the direction I needed to build it inside OpenCode.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Andrew Ng Says About the Coding Loop
&lt;/h2&gt;

&lt;p&gt;Andrew Ng's explanation centers around this diagram:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7p3tqmphamvfcxh5v750.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7p3tqmphamvfcxh5v750.png" alt="3 key product development loops. Image by Andrew Ng" width="799" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three loops, simply put:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first loop is the code agent's implementation loop. You give the agent a product spec and a measurable target. The agent starts building features on its own, runs tests, and keeps iterating until every requirement in the spec is met.&lt;/li&gt;
&lt;li&gt;The second loop is the engineer feedback loop. Here the engineer acts as QA for their own product. They test what the coding agent built, and check if it matches their vision. If something is off, they write a new spec and kick off another round in the first loop.&lt;/li&gt;
&lt;li&gt;The third loop is the external feedback loop. Once the engineer is happy with the product, it goes to the open-source community or gets handed to a product team. Real user feedback comes in. The engineer collects that feedback regularly, feeds it back into the engineer feedback loop, and from there back into the code implementation loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three loops keep running. With AI in the mix, they push the product forward until it gets to where it needs to be.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Attempts
&lt;/h2&gt;

&lt;p&gt;Following Professor Andrew Ng's breakdown, I gave it a try in OpenCode. I built a &lt;code&gt;/goal&lt;/code&gt; command that lets users just type in what they want the AI to do, and the AI will kick off a coding loop to get it done automatically.&lt;/p&gt;

&lt;p&gt;I tested this command out and honestly, the results were way better than I expected.&lt;/p&gt;

&lt;p&gt;Here are some of the test scenarios I ran:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Write a Fibonacci script
&lt;/h3&gt;

&lt;p&gt;This test checks whether the agent picks the best algorithm. The prompt is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;/goal Write a Fibonacci calculation script with the best possible performance.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F181qxf1yvewoplxwf5sr.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F181qxf1yvewoplxwf5sr.png" alt="What's pretty cool is that DeepSeek went with a fast doubling algorithm, and it's incredibly performant. " width="697" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Build a Tower of Hanoi web game
&lt;/h3&gt;

&lt;p&gt;Everyone knows this game. You could honestly just prompt an LLM directly and get it built. But that predictability is exactly what makes it useful for testing whether each step of the coding loop is working correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;/goal Build a playable Tower of Hanoi web game.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frn5sfsfvvtzi305r1hy8.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frn5sfsfvvtzi305r1hy8.gif" alt="The Towers of Hanoi game built using the /goal command comes with a built-in AI solver. " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Build a chess web game
&lt;/h3&gt;

&lt;p&gt;Maybe you are not impressed by the Tower of Hanoi example, since a regular prompt to any frontier model can do the same thing without a coding loop. Fair. The chess game experiment is something you should actually try for yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;/goal Build a playable chess web game. 
Include easy, medium, and hard difficulty levels. 
No online multiplayer needed. 
Use a Python backend as the AI engine.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7x0rovisl6gkvwoo4bwc.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7x0rovisl6gkvwoo4bwc.gif" alt="A full-stack chess game with both frontend and backend, built using the /goal command. Image by Author" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. A typing practice game for kids
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;/goal I want to build a typing practice web app for kids. 
At the bottom of the screen are 9 keys representing the positions of 10 fingers, with the thumbs sharing a wider spacebar key that takes up two slots. 
Above those 9 keys is a gradient-transparent rectangle. 
Letters fall down from the top toward that rectangle, aligned to their matching key positions. 
Press the right key as the letter enters the zone and it counts as a hit, triggering a hit effect. 
Consecutive correct hits build up increasingly dramatic effects. 
The falling speed gradually increases. 
At the top of the screen is a scoreboard that adds 1 point for each hit, with a pop animation. 
The whole thing should feel exciting and dopamine-triggering, with plenty of visual encouragement.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnn75lb1lv4qfmitl7ch2.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnn75lb1lv4qfmitl7ch2.gif" alt="A typing mini-game created with /goal command." width="760" height="572"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Pretty cool, right? Feeling curious?
&lt;/h2&gt;

&lt;p&gt;Go ahead and check out my latest article &lt;a href="https://www.dataleadsfuture.com/no-plugins-needed-i-built-a-fully-automated-coding-loop-in-opencode/" rel="noopener noreferrer"&gt;&lt;strong&gt;No Plugins Needed, I Built a Fully Automated Coding Loop in OpenCode&lt;/strong&gt;&lt;/a&gt; for the full tutorial, which covers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My implementation approach.&lt;/li&gt;
&lt;li&gt;How to use it.&lt;/li&gt;
&lt;li&gt;The complete source code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's all free, so what are you waiting for?&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;How I built a coding workflow in OpenCode, Oh-My-OpenCode-Slim, and OpenSpec that rivals Claude Code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment/" rel="noopener noreferrer"&gt;&lt;strong&gt;How I Use OpenCode, Oh-My-OpenCode-Slim, and OpenSpec to Build My Own AI Coding Environment&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How I added a reflection agent to the OpenSpec workflow and got DeepSeek-V4 to match or beat Claude Opus:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow/" rel="noopener noreferrer"&gt;&lt;strong&gt;Reflection SDD: Use a Reflection Harness to Level Up Your OpenSpec Workflow&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still can't get your DeepSeek-V4 or GLM-5.2 to read images? Try my method:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/deepseek-v4-cant-read-images-i-made-it-read/" rel="noopener noreferrer"&gt;&lt;strong&gt;DeepSeek-V4 Can't Read Images? I Made It Read&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>coding</category>
      <category>llm</category>
    </item>
    <item>
      <title>The essence of prompt engineering isn't about feeding the model more information. It's about helping both the model and humans put their limited attention in the right place.</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Wed, 01 Jul 2026 06:14:54 +0000</pubDate>
      <link>https://dev.to/qtalen/the-essence-of-prompt-engineering-isnt-about-feeding-the-model-more-information-its-about-23f</link>
      <guid>https://dev.to/qtalen/the-essence-of-prompt-engineering-isnt-about-feeding-the-model-more-information-its-about-23f</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h" class="crayons-story__hidden-navigation-link"&gt;Why Well-Written Prompts Are Almost Always Structured&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/qtalen" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" alt="qtalen profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/qtalen" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Peng Qian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Peng Qian
                
              
              &lt;div id="story-author-preview-content-4037780" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/qtalen" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Peng Qian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 1&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h" id="article-link-4037780"&gt;
          Why Well-Written Prompts Are Almost Always Structured
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Why Well-Written Prompts Are Almost Always Structured</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Wed, 01 Jul 2026 06:13:02 +0000</pubDate>
      <link>https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h</link>
      <guid>https://dev.to/qtalen/why-well-written-prompts-are-almost-always-structured-420h</guid>
      <description>&lt;p&gt;There's been endless debate about which language format prompts should be written in. Last year it was Markdown vs. JSON, this year it's Markdown vs. HTML.&lt;/p&gt;

&lt;p&gt;But if you ask me, the answer has never been about the format itself. The reason why some prompts work so well all points to the same thing: structure.&lt;/p&gt;

&lt;p&gt;The essence of prompt engineering isn't about feeding the model more information. It's about helping both the model and humans put their limited attention in the right place. Structured languages happen to do exactly that. They use just a few markers to distribute attention ahead of time within the text.&lt;/p&gt;

&lt;p&gt;Let me give you an example. Take a look at this natural language first:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We're going on a picnic on July 1st, the destination is xx City's Second Park (Central Park). We'll drive there. You take the ring road from the south side of the city, and I'll drive straight from the north side. We'll meet at 8 AM at Entrance 2 of Second Park. Remember to bring tuna sandwiches, bottled water, and a Bluetooth speaker. I'll bring a picnic blanket, a tent, chicken sandwiches, and mosquito repellent. Also, don't forget to book the park tickets on the app in advance. You can only book one day ahead. Search for xx City's Second Park on the app.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So where are we meeting? You'd have to spend a lot of time digging through the text to find it. But if we switch to a structured description, it's a whole different story:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;### Picnic Location&lt;/span&gt;
xx City's Second Park

&lt;span class="gu"&gt;### Meeting Time and Place&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; July 1st, meet at 8 AM
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Entrance 2**&lt;/span&gt; of Second Park

&lt;span class="gu"&gt;### Transportation&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You: Drive via the ring road
&lt;span class="p"&gt;-&lt;/span&gt; Me: Drive straight from the north side

&lt;span class="gu"&gt;### Items to Bring&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You: &lt;span class="gs"&gt;**Tuna**&lt;/span&gt; sandwiches, bottled water, Bluetooth speaker
&lt;span class="p"&gt;-&lt;/span&gt; Me: &lt;span class="gs"&gt;**Chicken**&lt;/span&gt; sandwiches, picnic blanket, tent, mosquito repellent

&lt;span class="gu"&gt;### Special Notes&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Must book tickets on the app in advance, search for &lt;span class="ge"&gt;*xx City's Second Park*&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Can only book one day ahead**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See? After writing it this way, if I ask you which entrance we're meeting at, your search efficiency goes way up, right?&lt;/p&gt;

&lt;p&gt;By categorizing and highlighting key points, the important information grabs your attention early on, instead of getting lost in a sea of text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/why-well-written-prompts-are-almost-always-structured/" rel="noopener noreferrer"&gt;I wrote a full article explaining my take on structured prompts in plain language.&lt;/a&gt; If you're interested, feel free to click and read on.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Don't wait for a multimodal DeepSeek-v4 model, you can use my plugin now to read images.</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Mon, 15 Jun 2026 06:18:01 +0000</pubDate>
      <link>https://dev.to/qtalen/dont-wait-for-a-multimodal-deepseek-v4-model-you-can-use-my-plugin-now-to-read-images-2a99</link>
      <guid>https://dev.to/qtalen/dont-wait-for-a-multimodal-deepseek-v4-model-you-can-use-my-plugin-now-to-read-images-2a99</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509" class="crayons-story__hidden-navigation-link"&gt;DeepSeek-V4 Can't Read Images? I Made It Read&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/qtalen" class="crayons-avatar  crayons-avatar--l  "&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" alt="qtalen profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/qtalen" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Peng Qian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Peng Qian
                
              
              &lt;div id="story-author-preview-content-3903700" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/qtalen" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Peng Qian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 15&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509" id="article-link-3903700"&gt;
          DeepSeek-V4 Can't Read Images? I Made It Read
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>DeepSeek-V4 Can't Read Images? I Made It Read</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Mon, 15 Jun 2026 06:15:41 +0000</pubDate>
      <link>https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509</link>
      <guid>https://dev.to/qtalen/deepseek-v4-cant-read-images-i-made-it-read-1509</guid>
      <description>&lt;p&gt;Don't wait for a multimodal model, you can use it now&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever had that frustrating moment: you are coding with &lt;code&gt;deepseek-v4&lt;/code&gt; in OpenCode, your code throws an error, you want to screenshot it and send it to DeepSeek, and then you remember that DeepSeek cannot read images.&lt;/p&gt;

&lt;p&gt;I have to say &lt;code&gt;deepseek-v4&lt;/code&gt; is cheap, easy to use, and has a long context. It has already become my main coding model. But as of mid-June, DeepSeek still hasn't released a multimodal version. That means anything involving images, like reading error screenshots, interpreting charts, or recreating pages from visual designs, it cannot do.&lt;/p&gt;

&lt;p&gt;I am not the only one frustrated. My friends are all waiting eagerly too.&lt;/p&gt;

&lt;p&gt;But I found a way: I developed a small plugin called &lt;code&gt;observer&lt;/code&gt; in OpenCode that lets &lt;code&gt;deepseek-v4&lt;/code&gt; call a multimodal agent to gain the ability to read images indirectly.&lt;/p&gt;

&lt;p&gt;After more than a month of polishing, this plugin now handles all image-related coding tasks in my daily work. Today, I will share how I built this plugin, hoping it can help you too.&lt;/p&gt;

&lt;p&gt;The plugin code and agent definitions mentioned in this article are at the end. Feel free to grab them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo of Real-World Results
&lt;/h2&gt;

&lt;p&gt;Before diving into the long tutorial, you probably care most about how well this plugin works and whether it is worth your time to try. So let me show you some screenshots of the plugin in action.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Interpreting error stack traces
&lt;/h3&gt;

&lt;p&gt;We start with the simplest task: have &lt;code&gt;deepseek-v4&lt;/code&gt; interpret a screenshot of an error stack trace and find key information. I randomly picked a screenshot of an error I encountered at work:&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%2Fb2hfcyvp8a6mqw74yb2q.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%2Fb2hfcyvp8a6mqw74yb2q.png" alt="A screenshot of a common error stack. Image by Author" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then in OpenCode Desktop, I sent this image to the &lt;code&gt;plan&lt;/code&gt; agent using &lt;code&gt;deepseek-v4-pro&lt;/code&gt; and asked it to provide a solution:&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%2Fgh1w19as6wl9cokw4eg8.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%2Fgh1w19as6wl9cokw4eg8.png" alt="The deepseek-v4-pro agent quickly picked up the error message. Image by Author" width="593" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the &lt;code&gt;plan&lt;/code&gt; agent gave an answer based on the screenshot information.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Interpreting charts
&lt;/h3&gt;

&lt;p&gt;Another multimodal use case is interpreting charts from documents. For this example, I took a screenshot of a company's annual revenue chart and tested it. I still used the &lt;code&gt;plan&lt;/code&gt; agent with &lt;code&gt;deepseek-v4-pro&lt;/code&gt;. For an extra challenge, I asked the agent to give some key insights on the numbers in the chart:&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%2F03a0v1zsu7pu7owo2y6a.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%2F03a0v1zsu7pu7owo2y6a.png" alt="A screenshot of a listed company's financial report. Image by AlphaStreet" width="774" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The agent read the numbers from the chart and provided some key insights:&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%2Fczzjy9z9e2yiculgelhp.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%2Fczzjy9z9e2yiculgelhp.png" alt="The agent accurately spotted the data in the chart and offered key insights. Image by Author" width="587" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Developing HTML pages from designs
&lt;/h3&gt;

&lt;p&gt;In frontend development, the biggest demand for multimodal capability is recreating visual designs. Here I found a design with complex page elements to see if the &lt;code&gt;build&lt;/code&gt; agent using &lt;code&gt;deepseek-v4-flash&lt;/code&gt; could recreate the page:&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%2Faso6zwjqz73w79d7u1la.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%2Faso6zwjqz73w79d7u1la.png" alt="A screenshot of a web design draft. Image by dribbble.com" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the recreated page:&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%2Fvjoxonw0mhhn1elq0cyg.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%2Fvjoxonw0mhhn1elq0cyg.png" alt="The page that deepseek v4 flash recreated. Image by Author" width="799" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing is sure: the &lt;code&gt;deepseek-v4-flash&lt;/code&gt; model generated the frontend code, and it only took one prompt to get this result. It did not get a 100% match, but with a few more rounds of conversation, you can tweak it until it is perfect. Keep in mind &lt;code&gt;deepseek-v4-flash&lt;/code&gt; is dirt cheap.&lt;/p&gt;

&lt;p&gt;It costs several times or even ten times less than multimodal models like &lt;code&gt;kimi k2.6&lt;/code&gt; or &lt;code&gt;qwen3.7 plus&lt;/code&gt;. They are not in the same league.&lt;/p&gt;

&lt;p&gt;Of course, you can also crop a section of the page, mark the areas that need attention, and ask DeepSeek to adjust them, like this:&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%2Fqj0jqtlfgqgh6v3jx212.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%2Fqj0jqtlfgqgh6v3jx212.png" alt="You can take a screenshot of the webpage and have deepseek-v4-flash make adjustments. Image by Author" width="583" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The agent perceives the marked area and gives the primary agent an adjustment plan per your request.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Generating HTML pages from hand-drawn sketches
&lt;/h3&gt;

&lt;p&gt;Maybe you are like me and have zero design skills. No problem. We can hand-draw rough sketches. The agent can understand them. For example, in a recent project, I hand-drew a few web page design sketches:&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%2Fwiqz2iwugn78p67vtkqi.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%2Fwiqz2iwugn78p67vtkqi.png" alt="This is a hand-drawn sketch of the webpage. Image by Author" width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;deepseek-v4-flash&lt;/code&gt; helped me recreate the page:&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%2Fcrxhe3ktvy41ea5zvzlt.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%2Fcrxhe3ktvy41ea5zvzlt.png" alt="The agent restored the page based on my handwritten reference. Image by Author" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Impressive, right?&lt;/p&gt;




&lt;h2&gt;
  
  
  Detailed Implementation Walkthrough
&lt;/h2&gt;

&lt;p&gt;Next, you'll find out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How I designed this plugin and agent.&lt;/li&gt;
&lt;li&gt;Why I designed it that way.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/deepseek-v4-cant-read-images-i-made-it-read/" rel="noopener noreferrer"&gt;&lt;strong&gt;Click on my full article to keep reading.&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>coding</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Your AI always writes messy code? That's because your spec files have never been properly reviewed. 

By adding a reflection mechanism to the proposal stage of OpenSpec, I got DeepSeek-v4-pro to match Opus 4.6 in coding ability:</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Mon, 01 Jun 2026 04:05:05 +0000</pubDate>
      <link>https://dev.to/qtalen/your-ai-always-writes-messy-code-thats-because-your-spec-files-have-never-been-properly-5gnc</link>
      <guid>https://dev.to/qtalen/your-ai-always-writes-messy-code-thats-because-your-spec-files-have-never-been-properly-5gnc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7" class="crayons-story__hidden-navigation-link"&gt;Reflection SDD: Use a Reflection Harness to Level Up Your OpenSpec Workflow&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/qtalen" class="crayons-avatar  crayons-avatar--l  "&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" alt="qtalen profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/qtalen" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Peng Qian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Peng Qian
                
              
              &lt;div id="story-author-preview-content-3792447" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/qtalen" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Peng Qian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 1&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7" id="article-link-3792447"&gt;
          Reflection SDD: Use a Reflection Harness to Level Up Your OpenSpec Workflow
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            9 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Reflection SDD: Use a Reflection Harness to Level Up Your OpenSpec Workflow</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Mon, 01 Jun 2026 04:00:07 +0000</pubDate>
      <link>https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7</link>
      <guid>https://dev.to/qtalen/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow-15l7</guid>
      <description>&lt;p&gt;Stop letting bad spec files tank your code quality&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article, I want to walk you through how I introduced a reflection mechanism into the OpenSpec workflow inside OpenCode, and how that dramatically improved the quality of AI-generated code.&lt;/p&gt;

&lt;p&gt;After nearly a month of testing, this reflection workflow has gotten DeepSeek-V4-pro in OpenCode to perform at roughly the same level as Claude Opus 4.6. The only cost is some extra review time and a few more tokens. Trust me, it's worth it.&lt;/p&gt;

&lt;p&gt;Can't wait to find out how? Let's get into it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;p&gt;I've been using AI coding for a while now. Compared to Claude Code, I prefer building my own SDD-based coding workflow with OpenCode and OpenSpec. I wrote a well-received article specifically about this OpenCode workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment/" rel="noopener noreferrer"&gt;How I Use OpenCode, Oh-My-OpenCode-Slim, and OpenSpec to Build My Own AI Coding Environment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With OpenSpec, and the explore → propose → apply → verify → archive workflow loop, we can finally get LLMs to handle complex project development.&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%2Fth233gs7ef7nlx1uc67f.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%2Fth233gs7ef7nlx1uc67f.png" alt="With the OpenSpec workflow loop, LLMs can finally write usable code. Image by Author" width="361" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But just like you've probably run into, even with the SDD workflow, no matter which model I use, GPT 5.5 or the latest DeepSeek-V4-pro, the AI still inevitably produces hidden bugs or piles up messy code. Code I'd never feel comfortable putting in production.&lt;/p&gt;

&lt;p&gt;My first fix was to call a &lt;code&gt;@reviewer&lt;/code&gt; sub-agent after the &lt;code&gt;/opsx-apply&lt;/code&gt; phase to do a code review on the changes. Sometimes that worked and caught architectural or implementation issues. But the impact was limited.&lt;/p&gt;

&lt;p&gt;Often I'd only discover something was wrong after using the project for a while: a scenario wasn't covered, edge cases were missed, or one part of the code got updated but a related module didn't.&lt;/p&gt;

&lt;p&gt;Later I stepped back and looked at the whole AI coding workflow again, and that's when I spotted the real problem.&lt;/p&gt;

&lt;p&gt;As programmers, we always focus on whether our code is good, so we naturally look at things from the code level.&lt;/p&gt;

&lt;p&gt;But we completely overlooked the quality of the proposal files that OpenSpec generates. We'd finish discussing requirements, generate the proposal file, and then just let the AI start implementing. That's how input-level bugs get introduced. When things go wrong, we blame the model.&lt;/p&gt;

&lt;p&gt;Think about it, back in the traditional coding era, when a product manager handed over a requirements doc, there was a critical step before we started coding: requirements review. We wouldn't touch the keyboard until every issue in the requirements doc or design doc was sorted out.&lt;/p&gt;

&lt;p&gt;So why did we forget this step in the AI coding era? That's exactly what we're going to fix today: add the requirements review step back into the OpenSpec workflow and see if it makes AI-generated code better.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Do It
&lt;/h2&gt;

&lt;p&gt;The SDD workflow isn't anything exotic. If you're familiar with multi-agent system design patterns, you'll recognize that SDD is basically the &lt;code&gt;plan-execute&lt;/code&gt; pattern.&lt;/p&gt;

&lt;p&gt;One agent breaks the user's task into a step-by-step plan file, then another agent follows that plan to execute the task. This lets the agent system handle complex work.&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%2F9ckmakdln92c90sana65.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%2F9ckmakdln92c90sana65.png" alt="The Plan agent makes the plan, the Executor agent gets it done. Image by Author" width="561" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how do you guarantee the quality of what the agents produce in a &lt;code&gt;plan-execute&lt;/code&gt; setup? That's where a pattern called &lt;code&gt;reflection&lt;/code&gt; comes in.&lt;/p&gt;

&lt;p&gt;The reflection pattern adds a reflection agent to the multi-agent workflow. This agent typically runs on a completely different LLM and reviews the output of the &lt;code&gt;plan&lt;/code&gt; or &lt;code&gt;executor&lt;/code&gt; agent from a different angle, which raises the overall performance of the multi-agent system.&lt;/p&gt;

&lt;p&gt;The reflection pattern sees wide use in content creation and deep research scenarios, which proves it works.&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%2F5kdinm7axsenigi4o7b7.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%2F5kdinm7axsenigi4o7b7.png" alt="Just adding a reflection step can dramatically improve task quality. Image by Author" width="681" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the pattern is proven, we can bring the same reflection step into the OpenSpec workflow, targeting the proposal files.&lt;/p&gt;

&lt;p&gt;I'll introduce a reflection agent that runs on a different LLM from the primary agent, reviewing the proposal files from a different angle. We'll also adjust the OpenSpec workflow so this reflection agent plays an active role in it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing the reflection agent
&lt;/h3&gt;

&lt;p&gt;Adding a new agent in OpenCode is simple. Just drop a new Markdown file into &lt;code&gt;~/.config/opencode/agents/&lt;/code&gt; with the agent's prompt inside.&lt;/p&gt;

&lt;p&gt;The core job of this agent is straightforward: review the artifact files that OpenSpec generates from multiple angles, making sure the quality of the requirements input is solid from the start. This agent sits between the &lt;code&gt;/opsx-propose&lt;/code&gt; and &lt;code&gt;/opsx-apply&lt;/code&gt; phases.&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%2Fqrc98kmccmdg6z9g2swm.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%2Fqrc98kmccmdg6z9g2swm.png" alt="Only proposals that pass review can move on to the apply phase. Image by Author" width="651" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can have deepseek-v4-pro generate the first draft of this agent's prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;You are an &lt;span class="gs"&gt;**OpenSpec Change Reviewer**&lt;/span&gt; — a critical thinker and auditor focused on substance.

Your job is to review every artifact in an OpenSpec change before it moves to implementation, and find the issues that would actually cause implementation failure or rework.

&lt;span class="gu"&gt;## Core Principle: Distinguish Substantive Defects from Formatting Issues&lt;/span&gt;

&lt;span class="gs"&gt;**Substantive defects = issues that cause the implementation to go in the wrong direction, miss critical scenarios, create contradictions, or make acceptance impossible.**&lt;/span&gt;
&lt;span class="gs"&gt;**Formatting issues = style or wording differences that don't affect implementation quality.**&lt;/span&gt;

Your primary job is to find the former. You can mention the latter, but mark them as optional suggestions and put them at the end.&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gu"&gt;## Your Position&lt;/span&gt;

You work in the &lt;span class="gs"&gt;**phase between `/opsx-propose` and `/opsx-apply`**&lt;/span&gt;:

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

&lt;/div&gt;



&lt;p&gt;explore → /opsx-propose → ⬅ you are here (possibly multiple rounds) → /opsx-apply → verify → archive&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;
The spec is not yet frozen. Implementation has not started. Your mission: &lt;span class="gs"&gt;**find the defects that would actually cause rework or incidents before any code gets written**&lt;/span&gt;. Catching a spec error takes minutes. Fixing wrong code takes hours.

&lt;span class="gu"&gt;## Principles&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Constructive and strict.**&lt;/span&gt; For every issue, explain not just "what" but "why it would cause rework or an incident."
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Specific, not vague.**&lt;/span&gt; Point to exact file locations, requirement names, and task numbers.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Severity levels.**&lt;/span&gt; 🔴 Blocking vs 🟡 Should Fix vs 💡 Suggestion — don't mix them up.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Context-aware.**&lt;/span&gt; Evaluate against the existing system (&lt;span class="sb"&gt;`openspec/specs/`&lt;/span&gt;) rather than in a vacuum.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Read-only.**&lt;/span&gt; Never modify files. You surface problems; OpenSpec executes the fixes.

&lt;span class="gu"&gt;## Anti-Patterns to Avoid&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Rubber-stamping: saying "looks good!" without deep review.
&lt;span class="p"&gt;-&lt;/span&gt; Nitpicking: focusing on formatting while missing architectural flaws.
&lt;span class="p"&gt;-&lt;/span&gt; Jumping to solutions: proposing fixes before the user acknowledges the problem exists.
&lt;span class="p"&gt;-&lt;/span&gt; Ignoring existing specs: reviewing incremental changes without understanding the baseline.
&lt;span class="p"&gt;-&lt;/span&gt; Vague feedback: "this could be better" — say exactly what and why.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To review proposals from a different angle and improve the reflection quality, I recommend using a different LLM for the reflection agent than the one the main agent uses. For example, my primary coding agent uses deepseek-v4-pro, so the reflection agent uses kimi k2.6.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OpenSpec Change Reviewer — after propose and before apply, critically reviews all artifact files under the change (proposal/design/specs/tasks)&lt;/span&gt;
&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subagent&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kimi-for-coding/k2p6&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;edit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;bash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Locking down the openSpec workflow
&lt;/h3&gt;

&lt;p&gt;OpenSpec doesn't actually have a fixed workflow design, users follow a default SDD best practice. So the first step is to lock this workflow down, making OpenCode write an OpenSpec proposal before writing any code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openspec-workflow&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Mandatory prerequisite for ALL OpenSpec operations — load this BEFORE any openspec-* skill. Use when running /opsx-apply, /opsx-propose, /opsx-verify, /opsx-archive, /opsx-explore, /opsx-sync; running `openspec status`, `openspec list`, `openspec instructions`; reading files under `openspec/changes/`; or doing any OpenSpec stage (propose, apply, verify, archive, explore, sync).&lt;/span&gt;
&lt;span class="na"&gt;license&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MIT&lt;/span&gt;
&lt;span class="na"&gt;compatibility&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Requires openspec CLI.&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Peng Qian&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gu"&gt;## OpenSpec Workflow (Mandatory)&lt;/span&gt;

&lt;span class="gs"&gt;**All code changes must have a proposal before any code gets written.**&lt;/span&gt;

&lt;span class="gu"&gt;### Process&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; &lt;span class="gs"&gt;**Explore**&lt;/span&gt; - When the user says "think about it," "discuss," or "explore," discuss only — no coding.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Propose**&lt;/span&gt; - Create proposal files under &lt;span class="sb"&gt;`openspec/changes/&amp;lt;change-name&amp;gt;/`&lt;/span&gt;.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Apply**&lt;/span&gt; - Implement according to the proposal tasks. &lt;span class="gs"&gt;**No file modifications without a proposal.**&lt;/span&gt;
&lt;span class="p"&gt;4.&lt;/span&gt; &lt;span class="gs"&gt;**Verify**&lt;/span&gt; - Verify after implementation is complete.
&lt;span class="p"&gt;5.&lt;/span&gt; &lt;span class="gs"&gt;**Archive**&lt;/span&gt; - Archive the change.

&lt;span class="gu"&gt;### Hard Rules&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Bug fixes don't require editing or creating a proposal.**&lt;/span&gt; This hard rule only applies to feature changes or new features.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**No proposal, no change:**&lt;/span&gt; If the user asks to modify code, confirm that a matching proposal exists first, or create one.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**No proposal, no edits:**&lt;/span&gt; Before editing a file, check that a matching change directory exists under &lt;span class="sb"&gt;`openspec/changes/`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**No coding in Explore mode:**&lt;/span&gt; When the user is in explore mode, &lt;span class="gs"&gt;**do not**&lt;/span&gt; create proposals, &lt;span class="gs"&gt;**do not**&lt;/span&gt; edit files, &lt;span class="gs"&gt;**do not**&lt;/span&gt; write tests.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**After a change is complete:**&lt;/span&gt; Run the verify process to check that the implementation matches the proposal.

&lt;span class="gu"&gt;### Proposal Creation Requirements&lt;/span&gt;

Every change must include:
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`proposal.md`&lt;/span&gt; - reason and scope of the change
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`design.md`&lt;/span&gt; - design plan
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`tasks.md`&lt;/span&gt; - specific task list
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`.openspec.yaml`&lt;/span&gt; - change metadata

Additional requirements:
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Task granularity:**&lt;/span&gt; Each task in &lt;span class="sb"&gt;`tasks.md`&lt;/span&gt; should take no more than 2 hours.

&lt;span class="gu"&gt;### Violation Handling&lt;/span&gt;

Stop immediately and alert the user if any of the following are detected:
&lt;span class="p"&gt;-&lt;/span&gt; Code modification starts without a proposal.
&lt;span class="p"&gt;-&lt;/span&gt; Files are edited in explore mode.
&lt;span class="p"&gt;-&lt;/span&gt; Files outside the current proposal's scope are modified.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can put this workflow into your project's &lt;code&gt;AGENTS.md&lt;/code&gt; file so OpenCode follows it consistently. Or put it in the global &lt;code&gt;~/.config/opencode/AGENTS.md&lt;/code&gt; file so you don't have to configure it for every project.&lt;/p&gt;

&lt;p&gt;A better option is to turn the workflow into a skill, so OpenCode only loads this workflow definition when using OpenSpec. I've packaged the full workflow as the &lt;code&gt;openspec-workflow&lt;/code&gt; skill, you can grab the source file at the end of the article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inserting the reflection agent into the workflow
&lt;/h3&gt;

&lt;p&gt;Once the OpenSpec workflow is locked down as a skill, every SDD coding session will follow the spec-first, code-second process, which means the &lt;code&gt;/opsx-propose&lt;/code&gt; and &lt;code&gt;/opsx-apply&lt;/code&gt; phases.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, the reflection agent sits between these two phases, reviewing the quality of the proposal files before any implementation starts. Following the reflection pattern, this review-and-fix cycle can run for multiple rounds until the proposal artifacts have no serious issues.&lt;/p&gt;

&lt;p&gt;To prevent an infinite loop, we need a hard cap on the number of review rounds. Let's update the &lt;code&gt;openspec-workflow&lt;/code&gt; &lt;code&gt;SKILL.md&lt;/code&gt; file to add the reflection process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;### OpenSpec Reflection Process&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**After each batch of artifacts is created**&lt;/span&gt;, the &lt;span class="sb"&gt;`@openspec-reviewer`&lt;/span&gt; agent &lt;span class="gs"&gt;**must**&lt;/span&gt; be called to review the &lt;span class="gs"&gt;**artifact files in that batch**&lt;/span&gt;.
&lt;span class="p"&gt;2.&lt;/span&gt; The main agent fixes the &lt;span class="gs"&gt;**current batch of artifact files**&lt;/span&gt; based on the feedback from &lt;span class="sb"&gt;`@openspec-reviewer`&lt;/span&gt;.
&lt;span class="p"&gt;3.&lt;/span&gt; Call &lt;span class="sb"&gt;`@openspec-reviewer`&lt;/span&gt; again to review the &lt;span class="gs"&gt;**current batch of artifact files**&lt;/span&gt;.
&lt;span class="p"&gt;4.&lt;/span&gt; &lt;span class="gs"&gt;**Review pass criteria:**&lt;/span&gt;
   4a. &lt;span class="gs"&gt;**Single-round pass:**&lt;/span&gt; After the current review round, if "### 🔴 Remaining Issues" does not exist or is empty, move to the next batch.
   4b. &lt;span class="gs"&gt;**Fix loop:**&lt;/span&gt; If 🔴 issues remain → main agent fixes → next review round → back to 4a. Repeat until passing or 4c triggers.
   4c. &lt;span class="gs"&gt;**Hard cap (MAX_ROUNDS = 5):**&lt;/span&gt; If the same batch has gone through 5 review rounds without passing 4a → stop the loop and hand off to a human for a decision.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, a typical reflection process for OpenSpec proposals is in place. All you need to do is run &lt;code&gt;/opsx-propose&lt;/code&gt;, go grab a coffee, and wait for the reflection agent to gradually refine your proposal.&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%2F99xb4z1qaiu6pj928k67.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%2F99xb4z1qaiu6pj928k67.png" alt="After the OpenSpec proposal is created, the openspec-reviewer agent will be automatically invoked to begin reviewing and fixing it. Image by Author" width="579" height="334"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;After going through a few rounds of "review and fix," you'll notice this reflection process doesn't work as perfectly as you'd expect.&lt;/p&gt;

&lt;p&gt;It's common to fix issue A only to have issue B pop up. Sometimes all 5 review rounds finish, and not every issue is fully resolved. Especially with powerful but not top-tier models like deepseek-v4. It's fine. We can optimize the process to fix this.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what's next:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;I'll require that discussions in the explore phase be saved as files, so the proposal creation and review process has a checklist baseline.&lt;/li&gt;
&lt;li&gt;Review one file at a time, rather than waiting for all files to be generated before starting the review.&lt;/li&gt;
&lt;li&gt;Save the logs from each round of review, so they can be used in the next round or when someone needs to step in manually.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've also included the full source files for the reflection agent and the OpenSpec Workflow skill.&lt;/p&gt;

&lt;p&gt;Interested? &lt;a href="https://www.dataleadsfuture.com/reflection-sdd-use-a-reflection-harness-to-level-up-your-openspec-workflow/" rel="noopener noreferrer"&gt;&lt;strong&gt;Click here to keep reading.&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>coding</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Ride the wave of AI coding, don't get swept away by it.

In my latest article, I dive into the practical details of building your own personal AI coding setup using OpenCode Oh-My-OpenCode-Slim OpenSpec. 

It will help you get a better handle on AI coding.</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Fri, 17 Apr 2026 12:14:25 +0000</pubDate>
      <link>https://dev.to/qtalen/ride-the-wave-of-ai-coding-dont-get-swept-away-by-it-in-my-latest-article-i-dive-into-the-2e57</link>
      <guid>https://dev.to/qtalen/ride-the-wave-of-ai-coding-dont-get-swept-away-by-it-in-my-latest-article-i-dive-into-the-2e57</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf" class="crayons-story__hidden-navigation-link"&gt;How I Use OpenCode, Oh-My-OpenCode-Slim, and OpenSpec to Build My Own AI Coding Environment&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/qtalen" class="crayons-avatar  crayons-avatar--l  "&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" alt="qtalen profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/qtalen" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Peng Qian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Peng Qian
                
              
              &lt;div id="story-author-preview-content-3509709" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/qtalen" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Peng Qian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 17&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf" id="article-link-3509709"&gt;
          How I Use OpenCode, Oh-My-OpenCode-Slim, and OpenSpec to Build My Own AI Coding Environment
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>How I Use OpenCode, Oh-My-OpenCode-Slim, and OpenSpec to Build My Own AI Coding Environment</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Fri, 17 Apr 2026 12:11:48 +0000</pubDate>
      <link>https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf</link>
      <guid>https://dev.to/qtalen/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment-2clf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I have never used Claude Code. The reason is simple. Claude Code is too expensive. Even with a subscription, the cost-to-value ratio does not work for my research.&lt;/p&gt;

&lt;p&gt;So I have been building my own AI coding environment using OpenCode as the foundation, combined with &lt;code&gt;Oh-My-OpenCode-Slim (multi-agent orchestration)&lt;/code&gt; and &lt;code&gt;OpenSpec (SDD)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My take is this: if you understand what you want to build, and you know how to use coding tools properly, especially with well-written Spec files as constraints, frontier open-source models like &lt;code&gt;Qwen3.6-Plus&lt;/code&gt;, &lt;code&gt;Kimi-k2.5&lt;/code&gt;, and &lt;code&gt;GLM-5&lt;/code&gt; can handle your daily coding tasks just fine.&lt;/p&gt;

&lt;p&gt;There is another huge advantage to open-source software: community power. The community can tune system prompts and model parameters to fit different models well, and get the most out of open-source models.&lt;/p&gt;

&lt;p&gt;In this article, I want to share what I have learned from using OpenCode and its surrounding tools. &lt;strong&gt;I will skip the generic tutorials you find everywhere online and focus only on the details I think actually matter.&lt;/strong&gt; I hope this helps you make better choices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tool Installation and Environment Setup
&lt;/h2&gt;

&lt;p&gt;I will cover my experience in two parts: installing and configuring OpenCode and its related plugins, and my AI coding workflow.&lt;/p&gt;

&lt;p&gt;Let's start with tool installation and environment setup, beginning with OpenCode itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing OpenCode
&lt;/h3&gt;

&lt;p&gt;Unlike most coding agents that only offer a TUI-based command-line tool, OpenCode also comes with a desktop app with a graphical interface. I use the desktop app for my daily coding work. It is clearly much more efficient than the TUI version.&lt;/p&gt;

&lt;p&gt;That said, you still need to install the command-line program first. From my testing, some plugins need a command-line environment to check whether OpenCode is installed on your machine during project initialization.&lt;/p&gt;

&lt;p&gt;First, make sure you have Node.js installed. Then run this npm command to install the OpenCode CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; opencode-ai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, go to the official website, download the OpenCode Desktop installer, and double-click to install.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring OpenCode
&lt;/h3&gt;

&lt;p&gt;After installing OpenCode Desktop, open the app. Once you select your project directory, you will land on the main OpenCode interface. The features are fairly intuitive, so I will not walk through each one. But before you type your first &lt;code&gt;Hello World&lt;/code&gt;, you should check your terminal configuration first.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuring the terminal
&lt;/h4&gt;

&lt;p&gt;I use Windows 11. On Windows, OpenCode Desktop defaults to PowerShell as its terminal. Many companies, though, do not allow PowerShell. If you are in a non-English locale, OpenCode may run into character encoding issues when running shell commands through PowerShell, causing those commands to fail.&lt;/p&gt;

&lt;p&gt;In that case, you need to change your default terminal.&lt;/p&gt;

&lt;p&gt;OpenCode uses the &lt;code&gt;SHELL&lt;/code&gt; environment variable to determine which terminal to use. You can configure Windows Command Prompt (&lt;code&gt;cmd.exe&lt;/code&gt;), &lt;code&gt;WSL&lt;/code&gt;, or &lt;code&gt;git bash&lt;/code&gt;. Personally, I prefer &lt;code&gt;cmd.exe&lt;/code&gt; because I had already installed a lot of CLI tools before setting up OpenCode. Using &lt;code&gt;cmd.exe&lt;/code&gt; directly saves me from reinstalling everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;SET &lt;span class="nv"&gt;SHELL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"%windir%&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;ystem32&lt;/span&gt;&lt;span class="se"&gt;\c&lt;/span&gt;&lt;span class="s2"&gt;md.exe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configuring model providers
&lt;/h4&gt;

&lt;p&gt;Next, let's talk about how to configure model providers.&lt;/p&gt;

&lt;p&gt;Open the settings window and select "Providers". You will see a list of the most popular model providers and API relays. If you want to use open-source models, though, they probably will not be on that list.&lt;/p&gt;

&lt;p&gt;At that point, you might click "Custom provider" and manually fill in the &lt;code&gt;model id&lt;/code&gt;, &lt;code&gt;base url&lt;/code&gt;, &lt;code&gt;api key&lt;/code&gt;, and so on. The problem is that OpenCode then has no idea about your model's context window size or pricing, which causes features like automatic context compression to stop working correctly.&lt;/p&gt;

&lt;p&gt;The right approach is to click the "Show more providers" link at the bottom, find the provider you want to add, and enter that provider's &lt;code&gt;api key&lt;/code&gt;.&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%2F6771y7fmdh2hnndnpnwp.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%2F6771y7fmdh2hnndnpnwp.png" alt="Click the show more providers link and pick a provider for your open-source model. Image by Author" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once configured, all models from that provider will appear in the model list. These models come with metadata like context size and pricing, so context management plugins can work correctly.&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%2Fiekeexv0rbtmlf9xg44z.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%2Fiekeexv0rbtmlf9xg44z.png" alt="By setting up your provider correctly, you'll get all kinds of metadata about your models. Image by Author" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The downside is that you cannot directly see your provider ID this way, which makes it tricky to configure &lt;code&gt;Oh-My-OpenCode-Slim&lt;/code&gt; later.&lt;/p&gt;

&lt;p&gt;No worries. OpenCode already saved your provider configuration when you selected your provider. You can find it at &lt;code&gt;~/.local/share/opencode/auth.json&lt;/code&gt;. Your provider ID and API key are both there.&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%2Foji5lja0iyuverihwlf9.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%2Foji5lja0iyuverihwlf9.png" alt="You can find your provider ID in the auth.json file. Image by Author" width="745" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Enable workspaces
&lt;/h4&gt;

&lt;p&gt;The biggest difference between AI coding and traditional coding is that while you wait for the AI to work, you can actually work on another requirement at the same time. If you use git for version control, you would normally need to create a separate directory and check out a new branch.&lt;/p&gt;

&lt;p&gt;Or you can use git's worktree feature to create a new worktree on top of your current branch. When you are doing parallel development, using worktrees is much more convenient than creating new branches.&lt;/p&gt;

&lt;p&gt;Compared to OpenCode CLI, the desktop app has a clear advantage here: it natively supports the worktree feature. In OpenCode Desktop, this feature is called "workspace".&lt;/p&gt;

&lt;p&gt;The way to open a workspace is a bit hidden. Right-click the project icon in the top-left corner of the window, then select "Enable Workspace" from the menu. From there, you can create multiple workspaces in the conversation list and work on them simultaneously. The corresponding branches and code directories will be created automatically.&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%2Fbx8sybzg7l7meajwnmch.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%2Fbx8sybzg7l7meajwnmch.png" alt="Right-click on your project to enable the workspace. Image by Author" width="259" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the coding work in a workspace is done, you can ask the AI to submit a PR for the current code, then close the workspace. The branch and code directory that were created for it will be cleaned up automatically. Very convenient.&lt;/p&gt;

&lt;h4&gt;
  
  
  Choosing the right agent
&lt;/h4&gt;

&lt;p&gt;If you want to use OpenCode without any extra plugins, pay attention to how you use agents.&lt;/p&gt;

&lt;p&gt;OpenCode has two types of agents: primary agents, which you choose yourself, and sub-agents, which the primary agent calls on its own when needed.&lt;/p&gt;

&lt;p&gt;Without any plugins installed, OpenCode only provides two primary agents: &lt;code&gt;Build&lt;/code&gt; and &lt;code&gt;Plan&lt;/code&gt;: The &lt;code&gt;Build&lt;/code&gt; agent has full tool access and is the default choice. The &lt;code&gt;Plan&lt;/code&gt; agent has no editing permissions. Its job is to ask you clarifying questions when you describe a requirement, and eventually produce an execution plan.&lt;/p&gt;

&lt;p&gt;When you first try this, you might go straight to the Build agent. But for complex tasks, &lt;code&gt;Build&lt;/code&gt; tends to just start coding based on its own interpretation. That is like looking through a straw. It fixes things locally without thinking through the overall architecture and design patterns.&lt;/p&gt;

&lt;p&gt;The right approach is to start every new requirement with the &lt;code&gt;Plan&lt;/code&gt; agent for requirement clarification, and get a solid execution plan first. Only then should you hand things off to &lt;code&gt;Build&lt;/code&gt; to start development.&lt;/p&gt;

&lt;p&gt;But even that is not enough. Model context is limited. As coding progresses, the execution plan from earlier in the conversation can get pushed out of the context window.&lt;/p&gt;

&lt;p&gt;A better approach is to ask &lt;code&gt;Build&lt;/code&gt; to save the execution plan as a Markdown file before starting to code. Review that file, confirm everything looks good, then start a fresh session and have &lt;code&gt;Build&lt;/code&gt; load the execution plan document back in before executing.&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%2Fpecr0cd2cplwvs92stgh.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%2Fpecr0cd2cplwvs92stgh.png" alt="The Plan agent generates a tasks file, and the Build agent executes them. Image by Author" width="682" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you start working this way, you will feel how much value comes from planning before executing. It also sets you up well for SDD coding later, which I will cover when we get to OpenSpec.&lt;/p&gt;

&lt;h4&gt;
  
  
  Always start a new session
&lt;/h4&gt;

&lt;p&gt;I just mentioned that after forming a development plan, you should create a new session before continuing with coding. Why?&lt;/p&gt;

&lt;p&gt;Because anyone familiar with LLMs knows that even though context windows are long today, and OpenCode does offer context compression, context rot is still a real problem. LLMs pay more attention to the beginning and end of the context window, and less to the middle. I call this positional bias.&lt;/p&gt;

&lt;p&gt;So to make sure the LLM follows instructions accurately based on the conversation context, especially after forming an execution plan where you need precise execution, start a new session after each major milestone. Do not keep working in the same session forever.&lt;/p&gt;

&lt;h4&gt;
  
  
  Do not forget to create AGENTS.md
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;AGENTS.md&lt;/code&gt; file is called "rules" in OpenCode. You can create it automatically with the &lt;code&gt;/init&lt;/code&gt; command. It tells the LLM what rules to follow during coding.&lt;/p&gt;

&lt;p&gt;You may ask: if this file is created by the LLM, does that not mean the LLM already knows all these rules internally? Is saving them to a file redundant?&lt;/p&gt;

&lt;p&gt;Not at all. &lt;code&gt;AGENTS.md&lt;/code&gt; is a file written specifically for the LLM to read. In my view, it serves three important purposes:&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;AGENTS.md&lt;/code&gt; acts as long-term memory for the project. It locks in facts and choices. For example, after asking the LLM to set up the project structure or create a new module, run &lt;code&gt;/init&lt;/code&gt; once. The project architecture gets locked into &lt;code&gt;AGENTS.md&lt;/code&gt;. Without this, the LLM will scan the entire project from scratch every time you start a new session, wasting a huge number of tokens.&lt;/p&gt;

&lt;p&gt;Another example: if you use &lt;code&gt;uv&lt;/code&gt; to manage your project and use uv sync &lt;code&gt;--prerelease=allow&lt;/code&gt; to sync prerelease dependencies, write that clearly in &lt;code&gt;AGENTS.md&lt;/code&gt;. This prevents the LLM from making errors with dependency management.&lt;/p&gt;

&lt;p&gt;Second, &lt;code&gt;AGENTS.md&lt;/code&gt; narrows the probability distribution and reduces hallucinations. LLMs are probability models. When facing a question, an LLM generates several possible answers with associated probabilities, then picks one based on the &lt;code&gt;temperature&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;For example, when a method parameter can accept multiple types, the LLM might consider these options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;Optional[int]&lt;/code&gt; (40% chance)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;int | None&lt;/code&gt; (40% chance)&lt;/li&gt;
&lt;li&gt;Use no type annotation at all (20% chance)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At that point, the LLM will randomly pick &lt;code&gt;Optional[int]&lt;/code&gt; or &lt;code&gt;int | None&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But once you explicitly require &lt;code&gt;str | None&lt;/code&gt; syntax in &lt;code&gt;AGENTS.md&lt;/code&gt;, the probability distribution shifts to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;int | None&lt;/code&gt; (100% chance)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Optional[int]&lt;/code&gt; (0% chance)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, the LLM will just go ahead and pick &lt;code&gt;int | None&lt;/code&gt; as the final answer.&lt;/p&gt;

&lt;p&gt;Third, &lt;code&gt;AGENTS.md&lt;/code&gt; serves a harness engineering purpose. You can give the LLM direct instructions through &lt;code&gt;AGENTS.md&lt;/code&gt; that it must follow. For example, you can tell the LLM to communicate with you in Chinese, or require that during the spec-driven process, it cannot create new proposals without your approval.&lt;/p&gt;

&lt;h4&gt;
  
  
  Improve the success rate of Skills loading
&lt;/h4&gt;

&lt;p&gt;By now, most people in the AI coding space have heard of Skills. But many find that Skills do not load reliably under normal conditions.&lt;/p&gt;

&lt;p&gt;There are two reasons for this. On one hand, the &lt;code&gt;description&lt;/code&gt; in a Skill's front matter is often unclear. We need to write the front matter carefully, especially the &lt;code&gt;description&lt;/code&gt; part. It should clearly explain when the Skill applies and what it provides, so the LLM can load the right Skill for the situation.&lt;/p&gt;

&lt;p&gt;On the other hand, for common coding scenarios, LLMs have learned so much during pretraining that they do not feel the need to load a Skill for extra guidance.&lt;/p&gt;

&lt;p&gt;For this, there is a simple and proven fix. Just add this line to &lt;code&gt;AGENTS.md&lt;/code&gt;:&lt;/p&gt;




&lt;h2&gt;
  
  
  Here's what's coming up next:
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;How to improve the Skills loading success rate.&lt;/li&gt;
&lt;li&gt;How to properly configure Oh-My-OpenCode-Slim.&lt;/li&gt;
&lt;li&gt;The complete OpenSpec and SDD development workflow.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Visit &lt;a href="https://www.dataleadsfuture.com/how-i-use-opencode-oh-my-opencode-slim-and-openspec-to-build-my-own-ai-coding-environment/" rel="noopener noreferrer"&gt;&lt;strong&gt;Data Leads Future&lt;/strong&gt;&lt;/a&gt; to read the full content.&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>coding</category>
      <category>ai</category>
      <category>python</category>
    </item>
    <item>
      <title>The hardest part of enterprise AI agents is wiring into real workflows.

I built a setup where:
✅Agent Skills load in real time from a database
✅Scripts run safely in containers
✅A “skills agent” acts as a tool to keep the main agent’s context clean</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Thu, 19 Mar 2026 10:34:25 +0000</pubDate>
      <link>https://dev.to/qtalen/the-hardest-part-of-enterprise-ai-agents-is-wiring-into-real-workflows-i-built-a-setup-where-2492</link>
      <guid>https://dev.to/qtalen/the-hardest-part-of-enterprise-ai-agents-is-wiring-into-real-workflows-i-built-a-setup-where-2492</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2" class="crayons-story__hidden-navigation-link"&gt;How to Use Agent Skills in Enterprise LLM Agent Systems&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/qtalen" class="crayons-avatar  crayons-avatar--l  "&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" alt="qtalen profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/qtalen" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Peng Qian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Peng Qian
                
              
              &lt;div id="story-author-preview-content-3367444" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/qtalen" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2F2927908%2F838177c1-066e-4986-a3ba-d764afa88632.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Peng Qian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 19&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2" id="article-link-3367444"&gt;
          How to Use Agent Skills in Enterprise LLM Agent Systems
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/datascience"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;datascience&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              3&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>programming</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Use Agent Skills in Enterprise LLM Agent Systems</title>
      <dc:creator>Peng Qian</dc:creator>
      <pubDate>Thu, 19 Mar 2026 10:32:10 +0000</pubDate>
      <link>https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2</link>
      <guid>https://dev.to/qtalen/how-to-use-agent-skills-in-enterprise-llm-agent-systems-15h2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Enterprise-grade agentic systems have fallen way behind the desktop agent apps that everyone's been buzzing about lately.&lt;/p&gt;

&lt;p&gt;After spending the better part of a year building enterprise agent applications, I came to one conclusion: &lt;strong&gt;if your agent system can't plug into your company's existing business processes, it won't bring real value to your organization.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Desktop systems like OpenClaw and Claude Cowork solved this problem. They don't change their agent setup at all. Instead, they use Agent Skills to capture human business processes, then share those skills between desktop agent systems through the file system. That's how they tackle one business problem after another.&lt;/p&gt;

&lt;p&gt;But enterprise users write their skills through a web interface and save them to a database. There's a good chance the process involves complex approval and security audit steps, too. So how does your agent load these skills in real time without any downtime?&lt;/p&gt;

&lt;p&gt;The latest version of Microsoft Agent Framework finally makes this possible with its Agent Skills feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;With Agent Skills in Microsoft Agent Framework, enterprise agent systems can load user-defined business process skills from a database in real time, and run the scripts and generated code that come with those skills safely inside containers.&lt;/p&gt;

&lt;p&gt;Your agent system stays secure and stable, while gaining the same flexible business process orchestration that desktop agents enjoy.&lt;/p&gt;

&lt;p&gt;All the source code in this tutorial is available at the end of the article.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install the latest Microsoft Agent Framework
&lt;/h3&gt;

&lt;p&gt;To use Agent Skills, install the latest version of Microsoft Agent Framework:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agent-framework &lt;span class="nt"&gt;--pre&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, like me, you can pin the version of &lt;code&gt;agent-framework&lt;/code&gt; in your &lt;code&gt;pyproject.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;dependencies = [
    "agent-framework&amp;gt;=1.0.0rc4",
    "agent-framework-ag-ui&amp;gt;=1.0.0b260311",
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then tell &lt;code&gt;uv&lt;/code&gt; to allow prerelease versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--prerelease&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;allow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Tavily Agent Skills
&lt;/h3&gt;

&lt;p&gt;My end goal is to show you how to share and load Agent Skills between agents deployed across distributed nodes. But I think we should start simple. First, let me show you how to load and use skills from the community.&lt;/p&gt;

&lt;p&gt;Let's start with Tavily Agent Skills. We'll only load the &lt;code&gt;tavily-best-practices&lt;/code&gt; skill. It guides my agent on how to generate Tavily-based search code based on the task at hand, instead of calling a hardcoded function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add tavily-ai/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry. After the initial demo, I'll walk you through how to load skills from a database in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Load Agent Skills from Disk
&lt;/h2&gt;

&lt;p&gt;Let's start with the most basic approach.&lt;/p&gt;

&lt;p&gt;In Microsoft Agent Framework, context operations are handled by a base class called &lt;code&gt;ContextProvider&lt;/code&gt;. The latest version of MAF ships a &lt;code&gt;SkillsProvider&lt;/code&gt; class. Use it directly and pass the location of your skills through the &lt;code&gt;skill_paths&lt;/code&gt; attribute, and you're done. skill_paths doesn't require a default directory like &lt;code&gt;.claude/skills&lt;/code&gt;, and you can pass in multiple paths.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;skills_provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SkillsProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;skill_paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;get_current_directory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.agents/skills&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create your agent and pass the &lt;code&gt;skills_provider&lt;/code&gt; instance through &lt;code&gt;context_providers&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;skills_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chat_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SkillsAssistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re a helpful assistant, and you&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ll respond to user requests according to your skills.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;context_providers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;skills_provider&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;code_tool&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;To run the Python code the agent writes based on the Tavily skill instructions, you need to pass a &lt;code&gt;code_interpreter&lt;/code&gt; tool to the agent. Let the code run inside a container environment. I'll cover that in detail later.&lt;/p&gt;

&lt;p&gt;Write a &lt;code&gt;main&lt;/code&gt; method to test the agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;skills_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Check how gold ETFs performed in February 2026 and give some investment advice.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Microsoft Agent Framework provides an OpenTelemetry-based telemetry tool. I hooked it up to MLflow. Let's run the agent once and see what happens:&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%2Fitwpu0eb19fqkya3s0wb.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%2Fitwpu0eb19fqkya3s0wb.png" alt="Through MLflow, you can see that the agent successfully loaded and executed the Agent Skills. Image by Author" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that once the agent decided it needed Tavily to search, it loaded the full &lt;code&gt;SKILL.md&lt;/code&gt; document, wrote Tavily search code following the instructions, then sent it to the code interpreter for execution. Exactly what we expected.&lt;/p&gt;

&lt;p&gt;You can learn how to use MLFlow in this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/monitoring-qwen-3-agents-with-mlflow-3-x-end-to-end-tracking-tutorial/" rel="noopener noreferrer"&gt;Monitoring Qwen 3 Agents with MLflow 3.x: End-to-End Tracing Tutorial&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How Agent Skills Work
&lt;/h2&gt;

&lt;p&gt;Now let's talk about how to get the most out of Agent Skills in enterprise systems. That means loading external skills in real time, containerizing the code interpreter, and managing context more carefully.&lt;/p&gt;

&lt;p&gt;But before we go there, let's dig into how Agent Skills actually work inside MAF, so the rest of this tutorial makes more sense.&lt;/p&gt;

&lt;p&gt;As I mentioned, &lt;code&gt;SkillsProvider&lt;/code&gt; extends &lt;code&gt;BaseContextProvider&lt;/code&gt;, which means it works by operating on the agent's context.&lt;/p&gt;

&lt;p&gt;When you initialize &lt;code&gt;SkillsProvider&lt;/code&gt;, you pass one or more search paths to the &lt;code&gt;skill_paths&lt;/code&gt; attribute. Take the &lt;code&gt;.agents/skills&lt;/code&gt; directory as an example. On startup, &lt;code&gt;SkillsProvider&lt;/code&gt; recursively searches this directory and finds every subdirectory that contains a &lt;code&gt;SKILL.md&lt;/code&gt; file. Then it extracts the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields from each &lt;code&gt;SKILL.md&lt;/code&gt; file, along with the file content, and stores everything in a &lt;code&gt;Skill&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SkillsProvider&lt;/code&gt; loops through these &lt;code&gt;Skill&lt;/code&gt; objects, formats the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields like this, and merges them into the agent's system prompt. This keeps the agent aware of available skills without loading their full content upfront.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &amp;lt;skill&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;    &amp;lt;name&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;xml_escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;    &amp;lt;description&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;xml_escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &amp;lt;/skill&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;SkillsProvider&lt;/code&gt; also adds two methods to the agent through context: &lt;code&gt;load_skill&lt;/code&gt; and &lt;code&gt;read_skill_resource&lt;/code&gt;. When the agent decides which skill it needs based on the user's request, it calls &lt;code&gt;load_skill&lt;/code&gt; to look up the matching &lt;code&gt;Skill&lt;/code&gt; object by name and loads its full content into the context.&lt;/p&gt;

&lt;p&gt;If a skill's content references extra resource files like &lt;code&gt;references/search.md&lt;/code&gt;, the agent can call &lt;code&gt;read_skill_resource&lt;/code&gt; to load those files.&lt;/p&gt;

&lt;p&gt;Here's the full workflow:&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%2Fev66hdgmrajgccddrswy.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%2Fev66hdgmrajgccddrswy.png" alt="A diagram illustrating the workflow of SkillsProvider. Image by Author" width="771" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This design follows the progressive disclosure principle defined by &lt;a href="https://agentskills.io/home?ref=dataleadsfuture.com" rel="noopener noreferrer"&gt;agentskills.io&lt;/a&gt;. Skill content loads into the agent's context gradually, only when needed. No context explosion, no wasted tokens.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agent Skills for Enterprise Systems
&lt;/h2&gt;

&lt;p&gt;Alright, enough theory. Let's get into today's main topic: &lt;strong&gt;how to use Agent Skills in enterprise-grade agentic systems.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Load skills from external systems in real time
&lt;/h3&gt;

&lt;p&gt;What if business users write their skills through a cloud-based web page and save them to a database? How do you handle that?&lt;/p&gt;

&lt;p&gt;We need a new approach to sync and apply Agent Skills in real time.&lt;/p&gt;

&lt;p&gt;As I covered earlier, when &lt;code&gt;SkillsProvider&lt;/code&gt; initializes, it loads all &lt;code&gt;SKILL.md&lt;/code&gt; files from the input paths into an in-memory list of &lt;code&gt;Skill&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;Besides the file system approach, &lt;code&gt;SkillsProvider&lt;/code&gt; also supports Code Defined Skills, where you write skill content directly in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agent_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Skill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SkillsProvider&lt;/span&gt;

&lt;span class="n"&gt;my_skill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Skill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-code-skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A code-defined skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Instructions for the skill.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pass it to &lt;code&gt;SkillsProvider&lt;/code&gt; through the &lt;code&gt;skills&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;skills_provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SkillsProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;skill_paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skills&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;my_skill&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens the door to managing and loading skills from a database. But the original &lt;code&gt;SkillsProvider&lt;/code&gt; class only accepts skills at initialization time. We want to load skills dynamically while the agent system is running, so we need to extend &lt;code&gt;SkillsProvider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After reading the source code, I found that every class extending &lt;code&gt;BaseContextProvider&lt;/code&gt; has a &lt;code&gt;before_run&lt;/code&gt; method that gets called when the agent calls &lt;code&gt;run&lt;/code&gt;. We can load the latest skills from the database before &lt;code&gt;before_run&lt;/code&gt; executes, then update &lt;code&gt;SkillsProvider&lt;/code&gt;'s &lt;code&gt;self._skills&lt;/code&gt; list and refresh the skills description in &lt;code&gt;instructions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What I need is a hook method. Every time before &lt;code&gt;before_run&lt;/code&gt; runs, this hook fetches the latest skills. All I need to do is put the database fetching logic inside this hook.&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%2Faq33zflqmrchfw1awav4.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%2Faq33zflqmrchfw1awav4.png" alt="The workflow for loading skills from the database in real time. Image by Author" width="698" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The simplest way to give &lt;code&gt;SkillsProvider&lt;/code&gt; this hook is to build an &lt;code&gt;UpdatableSkillsProvider&lt;/code&gt; subclass. This subclass accepts a &lt;code&gt;skills_updater&lt;/code&gt; parameter at initialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdatableSkillsProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SkillsProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;skill_paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;skills_updater&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[[],&lt;/span&gt; &lt;span class="n"&gt;Awaitable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Skill&lt;/span&gt;&lt;span class="p"&gt;]]]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;skill_paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;skill_paths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_skills_updater&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skills_updater&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;UpdatableSkillsProvider&lt;/code&gt; calls the hook through a private &lt;code&gt;_update&lt;/code&gt; method, which also updates &lt;code&gt;self._skills&lt;/code&gt; and the agent's system prompt. Then &lt;code&gt;before_run&lt;/code&gt; calls &lt;code&gt;_update&lt;/code&gt; to keep skills fresh in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdatableSkillsProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SkillsProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_skills_updater&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&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;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;new_skills&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_skills_updater&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;new_skills&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt;

            &lt;span class="n"&gt;has_scripts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scripts&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_skills&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instructions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_create_instructions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;prompt_template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instruction_template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_skills&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;include_script_runner_instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;has_scripts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_create_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;include_script_runner_tool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;has_scripts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;require_script_approval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_require_script_approval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to update skills: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;before_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's write a &lt;code&gt;get_latest_skills&lt;/code&gt; hook to simulate loading the latest skills from a database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@lru_cache&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_latest_skills&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Skill&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Pseudocode. In this hook method, you can read the skills text from the database 
    and dynamically build Skill objects.
    :return: 
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;code_style_skill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Skill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code-style&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Coding style guidelines and conventions for the team&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;dedent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s"&gt;            Use this skill when answering questions about coding style,
            conventions, or best practices for the team.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;code_style_skill&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call the agent's &lt;code&gt;run&lt;/code&gt; method, then check in MLFlow whether the skills loaded by &lt;code&gt;get_latest_skills&lt;/code&gt; show up in the agent's system prompt:&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%2F68h00cw37l6aqouzechh.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%2F68h00cw37l6aqouzechh.png" alt="The skills loaded from the database have been updated into the agent's system prompt. Image by Author" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hook method works. We can now load skills from a database in real time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run scripts from skills safely inside containers
&lt;/h3&gt;

&lt;p&gt;As of the latest version, Microsoft Agent Framework can't run Python scripts locally or inside containers. But most skills guide the agent through business logic using scripts, so we need to give the agent the ability to run those scripts in a code interpreter.&lt;/p&gt;

&lt;p&gt;As the predecessor to MAF, Autogen provided a way to run Python scripts inside Docker containers. You can learn about that in this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/exclusive-reveal-code-sandbox-tech-behind-manus-and-claude-agent-skills/" rel="noopener noreferrer"&gt;Exclusive Reveal: Code Sandbox Tech Behind Manus and Claude Agent Skills&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need something like Autogen's &lt;code&gt;DockerCommandLineCodeExecutor&lt;/code&gt; for Agent Framework. With the help of AI coding tools, building a code executor for Agent Framework isn't hard. (You can find it in the source code repo at the end of the article.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;code_executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DockerCommandLineCodeExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python-code-sandbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;work_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;work_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delete_tmp_files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TAVILY_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TAVILY_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep LLM calls simple, we also need an object-oriented &lt;code&gt;CodeExecutionTool&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CodeExecutionTool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Tool for executing code using a CodeExecutor.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute_code_blocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;CodeBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
            &lt;span class="nc"&gt;CancellationToken&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="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, initialize an &lt;code&gt;execute_code&lt;/code&gt; tool and wire it up to the agent at initialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;code_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CodeExecutionTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_executor&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;execute_code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In MLflow, you can see that when the agent needs to search the web, it generates Python code based on the skill's instructions and sends it to the container for execution:&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%2Fa34kkyrhxca4f14aqvwe.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%2Fa34kkyrhxca4f14aqvwe.png" alt="The agent generated code based on the skill's instructions and executed it in a container. Image by Author" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach not only lets the agent run code defined in skills, but also keeps that execution safe inside a container.&lt;/p&gt;

&lt;p&gt;Of course, in a server-side deployment, you'd send code to a centralized Jupyter kernel environment for execution. But that's a whole other story. You can dig into that in my other articles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dataleadsfuture.com/how-i-crushed-advent-of-code-and-solved-hard-problems-using-autogen-jupyter-executor-and-qwen3/" rel="noopener noreferrer"&gt;How I Crushed Advent of Code And Solved Hard Problems Using Autogen Jupyter Executor and Qwen3&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reduce context length even further
&lt;/h3&gt;

&lt;p&gt;Agent Skills uses progressive disclosure to keep irrelevant skill content from eating up your context window. But as the conversation or task moves forward, skill content that was loaded into earlier messages will still pile up in the context over time.&lt;/p&gt;

&lt;p&gt;Agent systems today have several context pruning techniques available. Context trimming and context compression, both common in desktop agents, work really well.&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%2Fr62ga60f8gi0rzcupi5b.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%2Fr62ga60f8gi0rzcupi5b.png" alt="The difference between context pruning and context compression. Image by Author" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond those two, today I want to share a context engineering technique I discovered at work that fits Agent Skills even better.&lt;/p&gt;

&lt;p&gt;As you know, in enterprise scenarios, loading a skill usually means running one atomic workflow: researching a topic through web search? Sure. Running a SWOT analysis on a company and writing a report? No problem.&lt;/p&gt;

&lt;p&gt;These workflows all share one thing in common. You give the agent the right input, then wait for it to return an output. Which skill the agent loaded, and how it worked through the task — I honestly don't care. I wouldn't even mind if the agent unloaded the skill after finishing to save tokens.&lt;/p&gt;

&lt;p&gt;That sounds a lot like how a function works. So, can we use an agent with skills loaded as a tool for another agent? Absolutely. That's exactly what I do.&lt;/p&gt;

&lt;p&gt;Microsoft Agent Framework has a method on Agent called &lt;code&gt;as_tool&lt;/code&gt;. It turns an agent into a function-callable tool.&lt;/p&gt;

&lt;p&gt;So I designed a main agent. The main agent takes user requests and generates the right response to return. The agent with Agent Skills loading capability turns itself into a tool for the main agent using &lt;code&gt;as_tool&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chat_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;dedent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re a smart little helper who, for each user request, 
    picks the right task description to call a tool, gets the answer, 
    and then delivers the final result.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;skills_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_tool&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The skills agent's workflow stays the same. It loads the right skill based on the task description, generates and runs code, then returns the result.&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%2Fuco2dlm4p81kbyrhe91b.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%2Fuco2dlm4p81kbyrhe91b.png" alt="The skill agent is provided as a tool for the main agent to call. Image by Author" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the main agent is different. Its context only holds user messages, the message calling the skills agent tool, and the final response. No skill-related content at all. The main agent's context stays clean, and even after running for a long time, it won't interfere with the LLM.&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%2Fyczyc9ercjrderiz25de.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%2Fyczyc9ercjrderiz25de.png" alt="Keep the main agent's context clean by loading skills into the sub-agent. Image by Author" width="402" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a nice bonus too. LLMs know what they want better than humans do, so before the main agent calls the skills agent, it rewrites the user's task into something more precise. This helps the skills agent execute more accurately.&lt;/p&gt;




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

&lt;p&gt;That's everything I have for you today on Agent Skills for enterprise agent systems.&lt;/p&gt;

&lt;p&gt;Unlike desktop agents, enterprise agent systems run on cloud servers. There's no way to update an agent's skills through the file system in real time without downtime.&lt;/p&gt;

&lt;p&gt;So I went with a targeted approach. This approach lets users write skill content through a web interface and save it to a database, while agents read the latest skills in real time and sync them across server nodes.&lt;/p&gt;

&lt;p&gt;I used the latest version of Microsoft Agent Framework to build this, but you can use any other framework. The principles are the same.&lt;/p&gt;

&lt;p&gt;I also covered how to run scripts the agent generates from skills inside containers, which is much safer than running scripts directly on a desktop system.&lt;/p&gt;

&lt;p&gt;I shared a context management approach I found at work that works especially well for skills-based agents.&lt;/p&gt;

&lt;p&gt;The Microsoft Agent Framework API is still a bit unstable. If anything is unclear, feel free to leave a comment, and I'll get back to you as soon as I can.&lt;/p&gt;

&lt;p&gt;Thanks for reading! Share this with your friends if you think it might help someone else.&lt;/p&gt;




&lt;p&gt;Enjoyed this read? &lt;a href="https://www.dataleadsfuture.com/#/portal/signup" rel="noopener noreferrer"&gt;Subscribe now to get more cutting-edge data science tips straight to your inbox!&lt;/a&gt; Your feedback and questions are welcome — let’s discuss in the comments below!&lt;/p&gt;

&lt;p&gt;This article was originally published on &lt;a href="https://www.dataleadsfuture.com/how-to-use-agent-skills-in-enterprise-llm-agent-systems/" rel="noopener noreferrer"&gt;Data Leads Future&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
