<?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: LakBud</title>
    <description>The latest articles on DEV Community by LakBud (@lakbud).</description>
    <link>https://dev.to/lakbud</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%2F4038257%2Febb36e71-ca54-4d4c-858f-a655661f1673.jpg</url>
      <title>DEV Community: LakBud</title>
      <link>https://dev.to/lakbud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lakbud"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>LakBud</dc:creator>
      <pubDate>Wed, 19 Aug 2026 17:28:42 +0000</pubDate>
      <link>https://dev.to/lakbud/-2fif</link>
      <guid>https://dev.to/lakbud/-2fif</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76" class="crayons-story__hidden-navigation-link"&gt;14 Core Features you need for your LLM calls which VernLLM covers&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="/lakbud" 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%2F4038257%2Febb36e71-ca54-4d4c-858f-a655661f1673.jpg" alt="lakbud profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/lakbud" class="crayons-story__secondary fw-medium m:hidden"&gt;
              LakBud
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                LakBud
                
                
              
              &lt;div id="story-author-preview-content-4419105" 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="/lakbud" 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%2F4038257%2Febb36e71-ca54-4d4c-858f-a655661f1673.jpg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;LakBud&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/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 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/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76" id="article-link-4419105"&gt;
          14 Core Features you need for your LLM calls which VernLLM covers
        &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/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&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;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76" 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/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76#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;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>14 Core Features you need for your LLM calls which VernLLM covers</title>
      <dc:creator>LakBud</dc:creator>
      <pubDate>Mon, 17 Aug 2026 15:13:20 +0000</pubDate>
      <link>https://dev.to/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76</link>
      <guid>https://dev.to/lakbud/14-core-features-you-need-for-your-llm-calls-which-vernllm-covers-k76</guid>
      <description>&lt;p&gt;The first version of any LLM app always works. Send a prompt, get a response, ship it.&lt;/p&gt;

&lt;p&gt;Then real traffic shows up. Providers go down. Rate limits kick in. Requests hang and time out. Models return broken JSON. Users double click submit and you pay twice. Nobody can say how much you spent last month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VernLLM&lt;/strong&gt; exists so you don't relearn all of this the hard way. The core call stays simple, and the reliability and control features are ready to switch on when you need them. Everything is opt-in.&lt;/p&gt;

&lt;p&gt;Here are the 14 features that make that possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Provider Fallback
&lt;/h2&gt;

&lt;p&gt;Every provider has bad days. Fallback lets you define backup targets and a policy for when to switch to them. It's not "try everything until something works." It's a deliberate policy for which errors trigger a switch and in what order. Your app stays up even when one provider doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Circuit Breaker
&lt;/h2&gt;

&lt;p&gt;Retrying a dead provider just adds load to something already struggling. A circuit breaker tracks failure patterns and, once a provider is clearly unhealthy, stops sending it traffic for a while. This works especially well alongside fallback: the circuit breaker keeps a bad provider from eating retry attempts while a healthy one picks up the slack.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Retries
&lt;/h2&gt;

&lt;p&gt;Some failures deserve another attempt: a network blip, a temporary 500. VernLLM's retries include exponential backoff, jitter (so failures don't all retry in sync), and &lt;code&gt;Retry-After&lt;/code&gt; awareness. The goal is to retry what's worth retrying and let permanent errors fail fast instead of burning attempts on something that was never going to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Rate Limiting
&lt;/h2&gt;

&lt;p&gt;Providers cap requests, tokens, concurrency, or time based quotas. Most teams discover these limits by hitting them. VernLLM's rate limiter lets you define those limits ahead of time and coordinate traffic before the provider has to say no.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Usage Metering
&lt;/h2&gt;

&lt;p&gt;Metering can reserve budget before a call and refund it automatically if the call fails. That refund step matters: without it, a failed request still looks like spent budget, and your internal usage numbers quietly drift from reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Caching
&lt;/h2&gt;

&lt;p&gt;A lot of LLM traffic is repeats: the same prompt twice, a page refresh, an unnecessary retry. &lt;code&gt;cachedCall&lt;/code&gt; wraps requests so identical work doesn't get redone, which means fewer provider calls, lower cost, and faster responses for anything stable enough to reuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Observability
&lt;/h2&gt;

&lt;p&gt;Reliability features you can't see are hard to trust. VernLLM emits one unified event stream for retries, circuit breaker transitions, rate limit waits, and fallback events, so you can actually answer questions like why a request was slow or why the provider switched, instead of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Usage Tracking
&lt;/h2&gt;

&lt;p&gt;Metering controls usage in the moment; tracking tells you what was actually consumed afterward. VernLLM captures token usage from provider responses, which is the raw material for dashboards, cost reports, per user or per model accounting, quotas, and billing.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Error Handling
&lt;/h2&gt;

&lt;p&gt;Not all failures are the same, but a single generic catch block treats them that way. VernLLM's structured &lt;code&gt;LLMError&lt;/code&gt; types let you tell a rate limit from a timeout from a broken request, so you can decide what's worth retrying and what should fail immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Cancellation &amp;amp; Timeouts
&lt;/h2&gt;

&lt;p&gt;Requests take time, and users don't always want to wait. VernLLM supports &lt;code&gt;AbortSignal&lt;/code&gt;, per-attempt timeouts, and retry-aware cancellation, so a user backing out mid-request actually stops the flow instead of letting it keep retrying in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Structured Output
&lt;/h2&gt;

&lt;p&gt;A model that "usually" returns JSON isn't the same as data you can trust. VernLLM supports structured output through client-side Zod validation and provider-native JSON Schema modes, so every response gets checked against a real schema before your app touches it.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Tool Calling
&lt;/h2&gt;

&lt;p&gt;VernLLM supports tool calling but never executes tools itself. The model can request a tool call; your application decides which tools exist, what arguments are valid, whether the call is authorized, how it runs, and what result goes back. The model proposes, your app disposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Streaming
&lt;/h2&gt;

&lt;p&gt;Streaming pushes chunks to the user as they're generated instead of making everyone wait for the full response. VernLLM streams without losing the reliability layer around it, retries and caching still apply, so it's not a separate, lesser API.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Pluggable Logger
&lt;/h2&gt;

&lt;p&gt;Every team logs differently: console output, structured JSON, an observability platform, an internal abstraction. VernLLM lets you plug in your own logger instead of forcing you to adopt its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;Each feature solves a narrow problem. Together, they answer a bigger one: how do you turn a raw LLM call into a production-ready capability?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    Your Application
                           │
                           ▼
                    ┌─────────────┐
                    │   VernLLM   │
                    └─────────────┘
                           │
          ┌────────────────┼────────────────┐
          │                │                │
          ▼                ▼                ▼
     Rate Limit        Cache          Usage Meter
          │                │                │
          └────────────────┼────────────────┘
                           ▼
                    Provider Request
                           │
                 ┌─────────┴─────────┐
                 │                   │
              Success              Failure
                 │                   │
                 ▼                   ▼
          Usage Tracking         Retry /
          + Streaming           Circuit Breaker
                                     │
                                     ▼
                                  Fallback
                                     │
                                     ▼
                              Backup Provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need all 14 at once. A small project might just want structured output and streaming. A production platform might use all of it together. You choose what your app needs.&lt;/p&gt;

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

&lt;p&gt;Networks fail, dependencies go down, users cancel, providers have limits, and responses need validation. That was true before LLMs and it's still true now. Getting a model to generate a good answer was never the hard part. Building a system that can rely on it at scale is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use one feature. Use all fourteen. The architecture stays yours.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://vernllm.vercel.app" rel="noopener noreferrer"&gt;https://vernllm.vercel.app&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>programming</category>
      <category>llm</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Thanks for 1,000+ downloads! VernLLM v1.0.0 is here</title>
      <dc:creator>LakBud</dc:creator>
      <pubDate>Fri, 24 Jul 2026 14:04:11 +0000</pubDate>
      <link>https://dev.to/lakbud/thanks-for-1000-downloads-vernllm-v100-is-here-2m7c</link>
      <guid>https://dev.to/lakbud/thanks-for-1000-downloads-vernllm-v100-is-here-2m7c</guid>
      <description>&lt;p&gt;Thanks for 1,000+ downloads! VernLLM just hit &lt;strong&gt;v1.0.0&lt;/strong&gt;, and it comes with one breaking change worth knowing about if you're using a custom cache adapter, plus a handful of smaller improvements that landed alongside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is VernLLM?
&lt;/h2&gt;

&lt;p&gt;VernLLM is a lightweight resilience layer for LLM chat completions: retries, timeouts, caching, circuit breaking, structured output, and usage tracking. All behind one typed interface, with adapters for OpenAI-compatible providers (OpenAI, Groq, Mistral, DeepSeek, Cerebras, Together AI, Fireworks, Ollama), plus Anthropic, Gemini, and AWS Bedrock.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VernLLM&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vern-llm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VernLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Return JSON: { "skills": string[] }&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Extract skills from: ...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The breaking change: &lt;code&gt;CacheAdapter.get()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Previously, &lt;code&gt;CacheAdapter.get()&lt;/code&gt; returned &lt;code&gt;Promise&amp;lt;T | null&amp;gt;&lt;/code&gt;. The problem: there was no way to tell the difference between "nothing is cached for this key" and "the cached value legitimately is &lt;code&gt;null&lt;/code&gt;." Both looked identical, so a real &lt;code&gt;null&lt;/code&gt; result got treated as a cache miss and silently re-triggered another LLM call every time.&lt;/p&gt;

&lt;p&gt;In v1.0.0, &lt;code&gt;get()&lt;/code&gt; now returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;hit&lt;/code&gt; reflects whether the key existed in the underlying store, independent of what the value was. &lt;code&gt;{ hit: true, value: null }&lt;/code&gt; means "we have a cached result, and it's null." &lt;code&gt;{ hit: false, value: null }&lt;/code&gt; means "nothing is cached."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're using the built-in &lt;code&gt;InMemoryCacheAdapter&lt;/code&gt;, you don't need to do anything&lt;/strong&gt;, it's already updated.&lt;/p&gt;

&lt;p&gt;If you've written a custom adapter (Redis, Upstash, etc.), you'll need to update &lt;code&gt;get()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyValue&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&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="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyValue&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&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="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&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;Most stores already give you this signal for free — Redis's &lt;code&gt;GET&lt;/code&gt; returning &lt;code&gt;null&lt;/code&gt; for "key doesn't exist" is distinguishable from a &lt;code&gt;null&lt;/code&gt; you stored yourself, so the fix is usually just an existence check rather than a &lt;code&gt;value !== null&lt;/code&gt; check.&lt;/p&gt;

&lt;p&gt;If you'd rather not bother with the distinction and are fine with &lt;code&gt;null&lt;/code&gt; results never being served from cache, there's also a one-line shim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Also in this release
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CallParams.systemPrompt&lt;/code&gt; is now optional — omit it and no system message is sent at all, instead of forcing an empty string through.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AnthropicClient&lt;/code&gt;, &lt;code&gt;GeminiClient&lt;/code&gt;, and &lt;code&gt;BedrockConverseClient&lt;/code&gt; are now exported as public types, so you can type your own client instances against them without reaching into internals.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;adapters&lt;/code&gt; barrel export — &lt;code&gt;import { fromAnthropic, fromGemini, fromBedrock, fromFetch, fromOpenAICompatible } from 'vern-llm/adapters'&lt;/code&gt; instead of digging through individual files.&lt;/li&gt;
&lt;li&gt;In-memory cache now has a size limit to prevent unbounded growth, evicting the oldest entries once the limit is hit.&lt;/li&gt;
&lt;li&gt;Internal types got refactored into focused modules, and test coverage was extended for optional system prompts, adapter payloads, and cache adapter edge cases (custom adapters, size bounds, failure handling).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Upgrading
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vern-llm@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're only using the built-in &lt;code&gt;InMemoryCacheAdapter&lt;/code&gt; (the default), this is a drop-in upgrade. If you've implemented a custom &lt;code&gt;CacheAdapter&lt;/code&gt;, update its &lt;code&gt;get()&lt;/code&gt; method per the migration guide above before upgrading in production.&lt;/p&gt;

&lt;p&gt;Full changelog and docs: &lt;a href="https://vernllm.vercel.app" rel="noopener noreferrer"&gt;vernllm.vercel.app&lt;/a&gt; · &lt;a href="https://github.com/LakBud/vernLLM" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for using VernLLM, and for the 1,000+ downloads. If you hit any issues with the migration, open an issue on GitHub.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>productivity</category>
      <category>news</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>LakBud</dc:creator>
      <pubDate>Tue, 21 Jul 2026 00:05:36 +0000</pubDate>
      <link>https://dev.to/lakbud/-19jg</link>
      <guid>https://dev.to/lakbud/-19jg</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0" class="crayons-story__hidden-navigation-link"&gt;VernLLM - lightweight resilience layer for LLM Applications&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="/lakbud" 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%2F4038257%2Febb36e71-ca54-4d4c-858f-a655661f1673.jpg" alt="lakbud profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/lakbud" class="crayons-story__secondary fw-medium m:hidden"&gt;
              LakBud
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                LakBud
                
              
              &lt;div id="story-author-preview-content-4190901" 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="/lakbud" 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%2F4038257%2Febb36e71-ca54-4d4c-858f-a655661f1673.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;LakBud&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/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 20&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/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0" id="article-link-4190901"&gt;
          VernLLM - lightweight resilience layer for LLM Applications
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&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/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&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/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0" 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/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&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/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0#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;
            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>VernLLM - lightweight resilience layer for LLM Applications</title>
      <dc:creator>LakBud</dc:creator>
      <pubDate>Mon, 20 Jul 2026 21:20:29 +0000</pubDate>
      <link>https://dev.to/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0</link>
      <guid>https://dev.to/lakbud/vernllm-lightweight-resilience-layer-for-openai-sdk-6c0</guid>
      <description>&lt;h1&gt;
  
  
  Introducing vernLLM: A Resilience Layer for LLM Applications
&lt;/h1&gt;

&lt;p&gt;Building production-ready LLM applications is not just about sending prompts and receiving responses. Real-world AI systems need to handle timeouts, provider failures, rate limits, inconsistent outputs, and reliability issues.&lt;/p&gt;

&lt;p&gt;That is where &lt;strong&gt;vernLLM&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vernLLM is a lightweight resilience layer for OpenAI-compatible chat completion APIs&lt;/strong&gt;, providing a single interface with built-in retries, timeouts, circuit breaking, caching, structured output, and usage tracking.&lt;/p&gt;

&lt;p&gt;Instead of rebuilding the same reliability features for every LLM project, vernLLM gives you the tools needed to make your AI integrations more robust from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Automatic retries with backoff
&lt;/h3&gt;

&lt;p&gt;Transient failures happen. vernLLM automatically retries recoverable errors while failing fast on validation errors and non-retryable responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timeouts &amp;amp; cancellation
&lt;/h3&gt;

&lt;p&gt;Prevent hanging requests with configurable timeouts and cancellation support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Circuit breaker protection
&lt;/h3&gt;

&lt;p&gt;Automatically stop sending requests to failing providers and recover when the service becomes healthy again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured output with type safety
&lt;/h3&gt;

&lt;p&gt;Pass a Zod schema and receive validated, typed results back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Return JSON: { "skills": string[] }&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Extract skills from: ...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SkillsSchema&lt;/span&gt; &lt;span class="c1"&gt;// zod schema&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provider-native JSON Schema support
&lt;/h3&gt;

&lt;p&gt;Constrain model generation itself instead of only validating responses afterward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in caching support
&lt;/h3&gt;

&lt;p&gt;Cache LLM responses using your own cache adapter with &lt;code&gt;cachedCall&lt;/code&gt; and &lt;code&gt;cachedLLMCall&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  One interface across providers
&lt;/h3&gt;

&lt;p&gt;Use the same API across multiple providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI&lt;/li&gt;
&lt;li&gt;Groq&lt;/li&gt;
&lt;li&gt;Mistral&lt;/li&gt;
&lt;li&gt;DeepSeek&lt;/li&gt;
&lt;li&gt;Cerebras&lt;/li&gt;
&lt;li&gt;Together AI&lt;/li&gt;
&lt;li&gt;Fireworks AI&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;Anthropic&lt;/li&gt;
&lt;li&gt;Gemini&lt;/li&gt;
&lt;li&gt;AWS Bedrock&lt;/li&gt;
&lt;li&gt;Any HTTP-compatible provider through &lt;code&gt;fromFetch&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why vernLLM?
&lt;/h2&gt;

&lt;p&gt;Many LLM applications end up creating their own wrappers around provider SDKs to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retry logic&lt;/li&gt;
&lt;li&gt;API failures&lt;/li&gt;
&lt;li&gt;provider switching&lt;/li&gt;
&lt;li&gt;response validation&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;vernLLM packages these patterns into a reusable, lightweight library so developers can focus on building AI features instead of maintaining infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add vern-llm openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VernLLM&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vern-llm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VernLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;onUsage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;totalTokens&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Used &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;totalTokens&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; tokens`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="c1"&gt;// now do something with it!&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cachedLLMCall&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;cacheKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`resume:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resumeId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Analyze this resume and return structured hiring insights.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resumeText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HiringSummarySchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Zod schema&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;h2&gt;
  
  
  Built for Production
&lt;/h2&gt;

&lt;p&gt;vernLLM is designed with production usage in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero bundled dependencies&lt;/li&gt;
&lt;li&gt;TypeScript-first API&lt;/li&gt;
&lt;li&gt;Provider adapters&lt;/li&gt;
&lt;li&gt;Extensive test coverage&lt;/li&gt;
&lt;li&gt;MIT licensed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you are building AI agents, document processing pipelines, chat applications, or LLM-powered tools, vernLLM provides the reliability layer needed to ship with confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://vernllm.vercel.app/" rel="noopener noreferrer"&gt;https://vernllm.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/LakBud/vernLLM" rel="noopener noreferrer"&gt;https://github.com/LakBud/vernLLM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contributions, feedback, and ideas are welcome!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
