<?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: Sayan "Riju" Chakrabarti</title>
    <description>The latest articles on DEV Community by Sayan "Riju" Chakrabarti (@sayanriju).</description>
    <link>https://dev.to/sayanriju</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3387729%2Fb040a2ce-32ee-4060-9d6e-6ae4ec5d3c46.jpeg</url>
      <title>DEV Community: Sayan "Riju" Chakrabarti</title>
      <link>https://dev.to/sayanriju</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sayanriju"/>
    <language>en</language>
    <item>
      <title>Kimten: a tiny agent loop for Node.js (without the framework weight)</title>
      <dc:creator>Sayan "Riju" Chakrabarti</dc:creator>
      <pubDate>Tue, 17 Feb 2026 08:47:16 +0000</pubDate>
      <link>https://dev.to/sayanriju/kimten-a-tiny-agent-loop-for-nodejs-without-the-framework-weight-4d29</link>
      <guid>https://dev.to/sayanriju/kimten-a-tiny-agent-loop-for-nodejs-without-the-framework-weight-4d29</guid>
      <description>&lt;p&gt;While building small AI utilities, I kept running into the same problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agent frameworks felt heavy&lt;/li&gt;
&lt;li&gt;ad-hoc tool calling became messy&lt;/li&gt;
&lt;li&gt;workflows quickly turned into glue code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something in between.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Kimten&lt;/strong&gt; — a minimal micro-agent loop on top of the Vercel AI SDK.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Kimten is
&lt;/h3&gt;

&lt;p&gt;Kimten is a thin wrapper over the AI SDK Agent interface that gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a bounded agent loop (no infinite reasoning spirals)&lt;/li&gt;
&lt;li&gt;tool/function calling&lt;/li&gt;
&lt;li&gt;short-term conversation memory&lt;/li&gt;
&lt;li&gt;optional structured output via Zod&lt;/li&gt;
&lt;li&gt;predictable, minimal behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No planners. No orchestration. No runtime magic.&lt;/p&gt;

&lt;p&gt;It’s meant to feel like a smart helper, not a framework.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why I built it
&lt;/h3&gt;

&lt;p&gt;Many LLM apps don’t need multi-agent graphs or orchestration layers.&lt;/p&gt;

&lt;p&gt;They just need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“let the model call a function”&lt;/li&gt;
&lt;li&gt;small automation workflows&lt;/li&gt;
&lt;li&gt;structured extraction&lt;/li&gt;
&lt;li&gt;quick utilities &amp;amp; scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kimten is designed for &lt;strong&gt;tiny, disposable agents&lt;/strong&gt; that solve one job well.&lt;/p&gt;




&lt;h3&gt;
  
  
  Where it fits well
&lt;/h3&gt;

&lt;p&gt;Kimten works nicely for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI helpers&lt;/li&gt;
&lt;li&gt;scripting &amp;amp; automations&lt;/li&gt;
&lt;li&gt;local utilities&lt;/li&gt;
&lt;li&gt;quick AI tools&lt;/li&gt;
&lt;li&gt;structured extraction tasks&lt;/li&gt;
&lt;li&gt;“summarize → refine → extract” flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each instance keeps short-term memory, so follow-ups like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;summarize this → make it shorter → extract bullets&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;just work.&lt;/p&gt;




&lt;h3&gt;
  
  
  What it intentionally does NOT do
&lt;/h3&gt;

&lt;p&gt;To keep behavior predictable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no planners or state machines&lt;/li&gt;
&lt;li&gt;no persistence or long-term memory&lt;/li&gt;
&lt;li&gt;no multi-agent orchestration&lt;/li&gt;
&lt;li&gt;no plugin ecosystem&lt;/li&gt;
&lt;li&gt;no streaming API surface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need 50+ steps, you probably need a planner — not Kimten.&lt;/p&gt;




&lt;h3&gt;
  
  
  Usage Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @tabbybyte/kimten ai zod @ai-sdk/openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;openai&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;@ai-sdk/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;z&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;zod&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="nx"&gt;Kimten&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;@tabbybyte/kimten&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// schema used only when we want structured output&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SummaryBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&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;cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Kimten&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;brain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;openai&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-mini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;personality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You summarize content clearly.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 1️⃣ free-form text output&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Explain what Node.js is in one sentence.&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → plain string&lt;/span&gt;


&lt;span class="c1"&gt;// 2️⃣ structured output using box mode&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonCat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Kimten&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;brain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;openai&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-mini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;personality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Summarize and extract keywords.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;box&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SummaryBox&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;structured&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;jsonCat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
Node.js is an open-source runtime built on Chrome’s V8 engine.
It allows JavaScript to run on the server and is widely used
for scalable network applications.
`&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="nx"&gt;structured&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { summary: "...", keywords: [...] }&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Design philosophy
&lt;/h3&gt;

&lt;p&gt;Kimten focuses on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Predictability over magic&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Small surface area over extensibility&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Disposable agents over runtime mutation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of rewiring behavior, you steer the agent via:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prompt input&lt;/li&gt;
&lt;li&gt;ephemeral context&lt;/li&gt;
&lt;li&gt;tool definitions&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  When a simple loop stops being enough
&lt;/h3&gt;

&lt;p&gt;In my experience, complexity creeps in when you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;long-running workflows&lt;/li&gt;
&lt;li&gt;task planning &amp;amp; decomposition&lt;/li&gt;
&lt;li&gt;shared memory across agents&lt;/li&gt;
&lt;li&gt;persistence &amp;amp; retrieval&lt;/li&gt;
&lt;li&gt;human-in-the-loop orchestration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until then, a tiny loop often gets the job done.&lt;/p&gt;




&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/tabbybyte-technologies/kimten" rel="noopener noreferrer"&gt;https://github.com/tabbybyte-technologies/kimten&lt;/a&gt;&lt;br&gt;
npm: &lt;a href="https://www.npmjs.com/package/@tabbybyte/kimten" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@tabbybyte/kimten&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d love feedback from folks building real-world LLM tooling — especially where you think the “tiny loop” approach breaks down.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>node</category>
    </item>
  </channel>
</rss>
