<?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: U G Murthy</title>
    <description>The latest articles on DEV Community by U G Murthy (@murthyug).</description>
    <link>https://dev.to/murthyug</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%2F312658%2F775617a1-b8f2-408a-8122-1a611ea2abca.jpeg</url>
      <title>DEV Community: U G Murthy</title>
      <link>https://dev.to/murthyug</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/murthyug"/>
    <language>en</language>
    <item>
      <title>The Soul of an Agent: Why You Should Stop Worrying and Start Building</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Sun, 15 Feb 2026 04:10:14 +0000</pubDate>
      <link>https://dev.to/murthyug/the-soul-of-an-agent-why-you-should-stop-worrying-and-start-building-521k</link>
      <guid>https://dev.to/murthyug/the-soul-of-an-agent-why-you-should-stop-worrying-and-start-building-521k</guid>
      <description>&lt;p&gt;Why You Should Stop Worrying and Start Building?&lt;/p&gt;

&lt;p&gt;Hey there, young hustlers and code curious! 🚀 Tired of all the doom-scrolling on social media? "AI agents are gonna steal your job!" "Everything's automating away!" Chill out. These thoughts belong to U G Murthy, paraphrased by AI – and here's the real tea: AI agents aren't the villain in your story. They're your sidekick, ready to level up your game. The future isn't about fearing them; it's about mastering &lt;em&gt;how to work with them&lt;/em&gt;. That's the superpower skill that'll keep you ahead as AI models get smarter and cheaper every day. Think Clawdbot or Moltbot going viral, or Claude CoWork shaking up stocks – more game-changers are coming. Time to gear up and build!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's an AI Agent, Anyway? (The Fun Spectrum)
&lt;/h2&gt;

&lt;p&gt;Picture agents like levels in your favorite video game – from noob to boss mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple Agents&lt;/strong&gt;: Just a quick chat or a chain of convos. Like texting a buddy for advice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Moderate Agents&lt;/strong&gt;: They search the web, pull out info, analyze it. Boom, instant research ninja!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Epic Agents&lt;/strong&gt;: All that plus tools, workflows, and magic. They plan, execute, and adapt on their own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents don't judge – they don't know you're "stupid" (your words, not mine!). They're always down to help, explain stuff, brainstorm wild ideas, teach you new tricks, or consult like a pro. Bonus: They mutate and evolve solo, and you can make 'em play any role – chef, coder, storyteller, you name it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Secret Sauce: Help Your Agent Win (And Watch Magic Happen)
&lt;/h2&gt;

&lt;p&gt;Agents are smart, but they're not mind-readers. Your success = their success. Here's how to team up like pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build the vibe&lt;/strong&gt;: Show 'em relevant context. "Hey, check this data..."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steer the ship&lt;/strong&gt;: "Consider this angle or that one." Give direction!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spill your goals&lt;/strong&gt;: "Do this exact thing for me."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spark options&lt;/strong&gt;: "What if we try A, B, or C?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get reflective&lt;/strong&gt;: Ask questions like, "Why this over that?" to make 'em think deeper.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nail this, and you're unstoppable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bother? The Perks Will Blow Your Mind
&lt;/h2&gt;

&lt;p&gt;Working with agents? It's a cheat code for life:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fresh ideas galore&lt;/strong&gt;: Exposure to solutions you never dreamed of.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ultimate sounding board&lt;/strong&gt;: Bounce thoughts, reflect, and grow sharper.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn at warp speed&lt;/strong&gt;: Pick up skills faster than binge-watching tutorials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Playtime vibes&lt;/strong&gt;: The journey's the real win – experiment, fail fast, laugh it off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlock new worlds&lt;/strong&gt;: Dive into stuff you never knew existed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bravery boost&lt;/strong&gt;: With an agent in your corner, take risks, build the unknown. No fear!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Wild Ride (U G Murthy's Story – Straight Fire)
&lt;/h2&gt;

&lt;p&gt;I retired in 2016 with dusty programming skills from my youth – off coding for 20+ years. But hey, time on my hands? I dove back in, learned fresh, and loved it. Fast-forward to 2025: Coding agents popped up. I tried 'em all – CoPilot, Bolt, Cursor, Windsurf, Kilo Code (solid for a bit), then &lt;em&gt;boom&lt;/em&gt;, AmpCode stole my heart.&lt;/p&gt;

&lt;p&gt;Got hyped from blogs by Lex Fridman and Dwarfish, but my fave? The Latent Space podcast &lt;a&gt;The AI Engineer Podcast&lt;/a&gt; – that's where agents hooked me. By 2026, I was building one &lt;em&gt;without a plan&lt;/em&gt;. Every step sparked new ideas, like prizes for grinding the last level. Sleepless nights? Sure. But waking up buzzing with vibes? Priceless. Slowly, I shipped &lt;a href="https://github.com/ugmurthy/desiAgent#readme" rel="noopener noreferrer"&gt;&lt;strong&gt;desiAgent&lt;/strong&gt;&lt;/a&gt;, an SDK for agents – mostly powered by AmpCode, which I used to paraphrase this post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://podcasts.apple.com/in/podcast/lex-fridman-podcast/id1434243584?i=1000749366733" rel="noopener noreferrer"&gt;This Lex Fridman Podcast&lt;/a&gt; hit me mid-walk, and was the inspiration for doing this post.&lt;/p&gt;

&lt;p&gt;
  My thoughts 💭 - the prompt used for this post
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The following is a list of thoughts for an essay - I want you convert this to a an essay jovial to natural tone easily readable and targeted mostly to youngster. Write the final essay to soul-of-an-agent-v1.md

The inspiration for writing this has come from  a podcast: https://podcasts.apple.com/in/podcast/lex-fridman-podcast/id1434243584?i=1000749366733  and lesson from my personal jouney 

Ensure you mention somewhere : that the though are mine (U G Murthy) Paraphrased by AI

### Soul of an Agent

### Key Message to drive home

AI Agents are not all gloom and doom as being discussed on most social media. Jobs will vanish etc. Gear your self develop a very important skill -  How work with agent and this requires us to understand what an agent is and how should I go about build my skill to use Agent. The AI models landscape is changing fast both in terms of capability and reducing cost. But its core is till the same allowing individuals to creating interesting use cases the one to go most viral is Clawdbot or Moltbot now and the other that crashed tech stocks is Claude CoWork and there will be more.

### Outline:

Following is an outline that needs to paraphrase and arrange in a logical flow

- Spectrum of agents
        - Simple - 1 chat conversation, chain of conversations 
        - Moderate - Search, extract, Analyse 
        - All of above + more tools + Agent workflows
    - Agent does not know I am stupid
    - Always there to help, explain, brainstorm, teach, consult
    - Agent can be mutate on its own
    - Agent can play different roles
- Every Agent needs help to succeed - your success lies in there
    - Show the the agent - build relevant context
    - Consider this and that - give it some direction
    - Do this… - expose your goal
    - Provide options - make it think about alternatives
    - Ask questions - Help the agent reflect
- How does it benefit me?
    - Exposure to new solutions
    - You get a sounding board making you reflect
    - Learn on the way and that too very quickly
    - Play - journey is more imp that end goal
    - Learn new things
     -  Don’t forget you have an agent to help you - be brave , take risks in building the unknown

- Personal journey 
    - I have been building ever since I retired in 2016. Though I had programming experience when I was younger, I was off coding for more than 2 decades. I had all the time in the world to learn - so I did
    - Glad I pursued learning to code. 2025, coding agents started to appear on the horizon and I embraced it -built and  Ditched many projects. Tried  Co Pilot, bolt, cursor, windsurf, settled on kilo code for a couple months and then I discovered ampCode   
    - Got inspired by many blog posts from Lex Freidman, Dwarfish,
    - favrouite podcast remains https://www.latent.space/podcast This is where I got curious about agents
    - 2026 I just started building an agent without a plan or a direction - every step in this direction gave birth to new ideas, it almost felt like a prize for the effort of previous step - there were sleepless nights but the journey was fun. I woke up every day with new ideas buzzing, it was hard to implement but slowly and steadily I build it
    - Here is desiAgent an SDK for agents : Most of the work was Ampcode, I review and understand its core.
        - Sharing my high level learnings of working fearlessly with agents by understanding their Soul
    - I got to writing this outline for this article while on a walk listening to Lex Friedman’s pod OpenClaw - https://podcasts.apple.com/in/podcast/lex-fridman-podcast/id1434243584?i=1000749366733


- Health warning:
    - AI Agents can consume you - beware of how much time and money you spend here
    - Do not take your eye of from - if you want to enjoy the future
        - The number of hours you sleep
        - Taking action to stay fit
        - 

- Conclusion
    - If you are young or retired dev wakeup / shapeup and start building stuff - 

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

&lt;/div&gt;




&lt;/p&gt;

&lt;h2&gt;
  
  
  Health Warning: Don't Let It Own You ⚠️
&lt;/h2&gt;

&lt;p&gt;Agents are addictive AF – time and cash can vanish. Keep your eyes on the prize for that epic future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sleep those 8 hours, no excuses.&lt;/li&gt;
&lt;li&gt;Hit the gym, stay fit – action over screens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Balance or burn out, fam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-Up: Wake Up, Shape Up, Build Now!
&lt;/h2&gt;

&lt;p&gt;Young guns or retired devs – this is your call to action. Stop scrolling, start shipping. Grab an agent, team up, and build cool stuff. The world's your playground. What's your first project? Go wild! 🌟&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>How to Build an Agent (in JavaScript)</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Sun, 19 Oct 2025 13:02:35 +0000</pubDate>
      <link>https://dev.to/murthyug/how-to-build-an-agent-in-javascript-5hgp</link>
      <guid>https://dev.to/murthyug/how-to-build-an-agent-in-javascript-5hgp</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclaimer: I am not affiliated with AmpCode in any way. This content is created solely as a user of AmpCode's free mode.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inspired by &lt;a href="https://ampcode.com/how-to-build-an-agent" rel="noopener noreferrer"&gt;Thorsten Ball's article&lt;/a&gt; on building a Golang agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This article, including all code generation, implementation, and debugging was by &lt;a href="https://ampcode.com/free" rel="noopener noreferrer"&gt;Amp Free&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s not that hard to build a fully functioning, code-editing agent.&lt;/p&gt;

&lt;p&gt;It seems like it would be. When you look at an agent editing files, running commands, wriggling itself out of errors, retrying different strategies - it seems like there has to be a secret behind it.&lt;/p&gt;

&lt;p&gt;There isn’t. It’s an LLM, a loop, and enough tokens. It’s what we’ve been saying. The rest, the stuff that makes agents so addictive and impressive? Elbow grease.&lt;/p&gt;

&lt;p&gt;But building a small and yet highly impressive agent doesn’t even require that. You can do it in less than 400 lines of code, most of which is boilerplate.&lt;/p&gt;

&lt;p&gt;I’m going to show you how, right now. We’re going to write some code together and go from zero lines of code to "oh wow, this is… a game changer."&lt;/p&gt;

&lt;p&gt;Here’s what we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openrouter.ai/" rel="noopener noreferrer"&gt;An OpenRouter API key&lt;/a&gt; that you set as an environment variable, &lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pencils out!
&lt;/h2&gt;

&lt;p&gt;Let’s dive right in and get ourselves a new Node.js project set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;js-coding-agent
&lt;span class="nb"&gt;cd &lt;/span&gt;js-coding-agent
pnpm init &lt;span class="nt"&gt;-y&lt;/span&gt;
pnpm add openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s create our files: &lt;code&gt;index.js&lt;/code&gt;, &lt;code&gt;agent.js&lt;/code&gt;, and &lt;code&gt;tools.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;agent.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getUserMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUserMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getUserMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;run&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;conversation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chat with Claude (use 'ctrl-c' to quit)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;readUserInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while &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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;readUserInput&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;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMessage&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&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;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nx"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userMessage&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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runInference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;toolResults&lt;/span&gt; &lt;span class="o"&gt;=&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;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&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="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;`\x1b[93mClaude\x1b[0m: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for &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;toolCall&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;toolCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;toolCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;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;toolCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;toolResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;readUserInput&lt;/span&gt; &lt;span class="o"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;readUserInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;toolResults&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;runInference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conversation&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;openaiTools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tool&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="k"&gt;try&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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="s2"&gt;anthropic/claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;openaiTools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tool_choice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`API Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&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;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;name&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;tool&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;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tool not found&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="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;`\x1b[92mtool\x1b[0m: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;(&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;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="k"&gt;try&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;response&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;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, this compiles. But what we have here is an &lt;code&gt;Agent&lt;/code&gt; that has access to an OpenAI client (configured for OpenRouter) and that can get a user message by reading from stdin on the terminal.&lt;/p&gt;

&lt;p&gt;Now let’s add the missing &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&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;readline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;readline&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;Agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./agent&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;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please set OPENROUTER_API_KEY environment variable&lt;/span&gt;&lt;span class="dl"&gt;"&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="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://openrouter.ai/api/v1&lt;/span&gt;&lt;span class="dl"&gt;"&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;OPENROUTER_API_KEY&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;rl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createInterface&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;input&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;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&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;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;question&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x1b[94mYou&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x1b[0m: &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="nx"&gt;input&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;trimmed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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;trimmed&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;resolve&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trimmed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;agent&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;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getUserMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;tools.js&lt;/code&gt; as an empty array for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tools&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 run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_api_key_here"&lt;/span&gt;
pnpm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can just talk to Claude, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pnpm start

Chat with Claude (use 'ctrl-c' to quit)

You: Hey! I'm [Your Name]! How are you?

Claude: Hi [Your Name]! I'm doing well, thanks for asking. It's nice to meet you. How are you doing today? Is there something I can help you with?

You:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we kept the same conversation going over multiple turns. It remembers my name from the first message. The &lt;code&gt;conversation&lt;/code&gt; grows longer with every turn and we send the whole conversation every time.&lt;/p&gt;

&lt;p&gt;Okay, let’s move on, because this is not an agent yet. What’s an agent? An LLM with &lt;em&gt;access to tools&lt;/em&gt;, giving it the ability to modify something outside the context window.&lt;/p&gt;

&lt;h2&gt;
  
  
  A First Tool
&lt;/h2&gt;

&lt;p&gt;An LLM with &lt;em&gt;access to tools&lt;/em&gt;? You send a prompt to the model that says it should reply in a certain way if it wants to use "a tool". Then you, as the receiver, "use the tool" by executing it and replying with the result.&lt;/p&gt;

&lt;p&gt;To make (1) easier, the big model providers have built-in APIs to send tool definitions along.&lt;/p&gt;

&lt;p&gt;Okay, now let’s build our first tool: &lt;code&gt;read_file&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;read_file&lt;/code&gt; tool
&lt;/h2&gt;

&lt;p&gt;In order to define the &lt;code&gt;read_file&lt;/code&gt; tool, we’re going to use JSON schemas, but keep in mind: this will all end up as strings that are sent to the model.&lt;/p&gt;

&lt;p&gt;Each tool requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A name&lt;/li&gt;
&lt;li&gt;A description&lt;/li&gt;
&lt;li&gt;An input schema (JSON schema)&lt;/li&gt;
&lt;li&gt;A function that executes the tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s add that to our &lt;code&gt;tools.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs/promises&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;readFileSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The path to the file to read&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&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;content&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&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;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to read file: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read_file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Read the contents of a file at the given path.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;readFileSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;readFile&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy here. It’s a single async function, &lt;code&gt;readFile&lt;/code&gt;, and descriptions the model will see.&lt;/p&gt;

&lt;p&gt;Now, update &lt;code&gt;index.js&lt;/code&gt; to use the tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tools&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;agent&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;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getUserMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to try it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pnpm start

Chat with Claude (use 'ctrl-c' to quit)

You: what's in index.js?

Claude: I'll help you check what's in the index.js file. Let me read it for you.

tool: read_file({"path":"index.js"})

Claude: Based on my review, index.js implements the main entry point for a Node.js CLI application that creates an AI agent. Here's a summary: - Imports necessary modules including OpenAI client, readline for CLI input, and custom Agent and tools - Checks for the OPENROUTER_API_KEY environment variable - Configures the OpenAI client to use OpenRouter's API endpoint - Sets up a readline interface for user input with colored prompts - Defines an async function to get user input - Initializes the Agent with the client, input function, and tools - Runs the agent in a try-catch block for error handling - Closes the readline interface and exits gracefully The code essentially bootstraps a conversational AI assistant that can interact with the user via command line and potentially use tools for additional functionality.

You:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can read files now!&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;list_files&lt;/code&gt; tool
&lt;/h2&gt;

&lt;p&gt;If you’re anything like me, the first thing you do when you log into a new computer is to get your bearings by running &lt;code&gt;ls&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s give Claude the same ability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listFilesSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Optional path to list files from, defaults to current directory&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;listFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&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;entries&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;withFileTypes&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;entry&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;()&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="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&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;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to list files: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to tools array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;list_files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;List files and directories at the given path. If no path provided, lists current directory.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;listFilesSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;listFiles&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;Let’s ask Claude what it can see in this directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pnpm start

Chat with Claude (use 'ctrl-c' to quit)

You: what do you see in this directory?

Claude: I'll help you see what's in the current directory. Let me list the files and directories for you.

tool: list_files({})

Claude: I can see several files and directories in the current directory: - README.md - agent.js - how-to-build-an-agent-js.md - index.js - node_modules/ - package.json - plan.md - tools.js - .gitignore

You:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works! It can list the directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let it &lt;code&gt;edit_file&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The last tool is &lt;code&gt;edit_file&lt;/code&gt; — a tool that lets Claude edit files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;editFileSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The path to the file to edit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;old_str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The string to search for and replace. If empty, creates a new file.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;new_str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The replacement string&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;old_str&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_str&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;editFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;old_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;new_str&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;content&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;old_str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;old_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;new_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;File edited successfully&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="k"&gt;else&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;old_str&lt;/span&gt; &lt;span class="o"&gt;===&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;new_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;File created successfully&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;old_str not found in file&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to edit file: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;edit_file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Edit a file by replacing old_str with new_str. If old_str is empty, creates a new file.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;editFileSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;old_str&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_str&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;editFile&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;Let’s tell Claude to create a new FizzBuzz function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pnpm start

Chat with Claude (use 'ctrl-c' to quit)

You: hey claude, create fizzbuzz.js that I can run with Nodejs and that has fizzbuzz in it and executes it

Claude: I'll create a fizzbuzz.js file that you can run with Node.js. First, let me check if the file already exists:

tool: list_files({})

Claude: I don't see a fizzbuzz.js file, so I'll create one with a classic FizzBuzz implementation. This program will print numbers from 1 to 100, but for multiples of 3 it will print "Fizz", for multiples of 5 it will print "Buzz", and for numbers that are multiples of both 3 and 5 it will print "FizzBuzz".

tool: edit*file({"path":"fizzbuzz.js","old_str":"","new_str":"/\**\\n _ FizzBuzz implementation in JavaScript\\n _ Prints numbers from 1 to 100, but:\\n _ - For multiples of 3, print \\"Fizz\\" instead of the number\\n _ - For multiples of 5, print \\"Buzz\\" instead of the number\\n \_ - For multiples of both 3 and 5, print \\"FizzBuzz\\"\\n \*/\\n\\nfunction fizzBuzz(n) {\\n for (let i = 1; i &amp;lt;= n; i++) {\\n let output = '';\\n \\n if (i % 3 === 0) output += 'Fizz';\\n if (i % 5 === 0) output += 'Buzz';\\n \\n console.log(output || i);\\n }\\n}\\n\\n// Execute FizzBuzz for numbers 1 to 100\\nconsole.log('Running FizzBuzz:');\\nfizzBuzz(100);"})

Claude: I've created a fizzbuzz.js file that you can run with Node.js. The program: 1. Defines a function called `fizzBuzz` that takes a parameter `n` for the upper limit 2. Loops from 1 to n (set to 100 in the execution) 3. For each number: - If it's divisible by 3, it adds "Fizz" to the output - If it's divisible by 5, it adds "Buzz" to the output - If it's divisible by both, it adds both resulting in "FizzBuzz" - If it's not divisible by either 3 or 5, it outputs the number itself 4. The script automatically executes the function for numbers 1 to 100 You can run this script using Node.js with the following command in your terminal: node fizzbuzz.js This will output the FizzBuzz sequence from 1 to 100 to your console.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right?! It’s impressive, isn’t it? And that’s the &lt;em&gt;most basic implementation&lt;/em&gt; of an agent you can probably come up with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isn’t this amazing?
&lt;/h2&gt;

&lt;p&gt;If you’re anything like the engineers I’ve talked to, chances are that, while reading this, you have been waiting for the rabbit to be pulled out of the hat. But it’s not.&lt;/p&gt;

&lt;p&gt;This is essentially all there is to the inner loop of a code-editing agent. Sure, integrating it into your editor, tweaking the system prompt, giving it the right feedback at the right time, a nice UI around it, support for multiple agents, and so on — we’ve built all of that in Amp, but it didn’t require moments of genius. All that was required was practical engineering and elbow grease.&lt;/p&gt;

&lt;p&gt;These models are incredibly powerful now. 300 lines of code and three tools and now you’re to be able to talk to an alien intelligence that edits your code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That&lt;/em&gt;’s why everything’s changing.&lt;/p&gt;

&lt;p&gt;This article, including all code generation, implementation, and debugging, was by &lt;a href="https://ampcode.com/free" rel="noopener noreferrer"&gt;Amp Free&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This implementation was built in this &lt;a href="https://ampcode.com/threads/T-b5693bb2-0309-4a75-bdf7-14c681e6676e" rel="noopener noreferrer"&gt;AmpCode thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Inspired by &lt;a href="https://ampcode.com/how-to-build-an-agent" rel="noopener noreferrer"&gt;Thorsten Ball's original article&lt;/a&gt; on building agents in Golang.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy/CodingAgent" rel="noopener noreferrer"&gt;Code repo on github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>javascript</category>
      <category>coding</category>
    </item>
    <item>
      <title>Github Stats on your Github profile page</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Sat, 21 Dec 2024 00:42:39 +0000</pubDate>
      <link>https://dev.to/murthyug/github-stats-on-you-github-profile-page-5d9f</link>
      <guid>https://dev.to/murthyug/github-stats-on-you-github-profile-page-5d9f</guid>
      <description>&lt;p&gt;&lt;em&gt;Header picture credit: Grok2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ever wondered how some GitHub profiles stand out with dynamic stats, vibrant visuals, and an interactive feel? Welcome to the art of creating a dynamic GitHub profile page! In this post, we'll dive into showcasing your coding prowess through GitHub statistics to turn your profile into a living resume of your coding journey. Let's make your GitHub profile not just a page, but an experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a GitHub Profile README:
&lt;/h3&gt;

&lt;p&gt;GitHub allows you to create a special repository named after your username (e.g., &lt;code&gt;yourusername/yourusername&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Navigate to GitHub's homepage and start creating a new repository. Set the name of the repository to your GitHub &lt;code&gt;username&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensure the repository is initialised with a &lt;code&gt;README.md&lt;/code&gt; file. This file will be displayed on your profile page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Here is how you add Dynamic GitHub Stats:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  GitHub Readme Stats:
&lt;/h4&gt;

&lt;p&gt;Use services like &lt;code&gt;github-readme-stats&lt;/code&gt; by &lt;a href="https://github.com/anuraghazra" rel="noopener noreferrer"&gt;&lt;em&gt;Anurag Hazra&lt;/em&gt;&lt;/a&gt; to generate dynamic stats. You can include your GitHub contributions, stars, forks, and languages used. Here's how you can add it to your README:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Copy the Markdown link below, replacing &lt;code&gt;yourname&lt;/code&gt; with your GitHub username:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[![yourname's GitHub stats](https://github-readme-stats.vercel.app/api?username=yourname)](https://github.com/yourname)&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub-readme-stats.vercel.app%2Fapi%3Fusername%3Dugmurthy" alt="Murthy's GitHub stats" width="450" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can customise the appearance via query parameters - &lt;a href="https://github.com/anuraghazra/github-readme-stats" rel="noopener noreferrer"&gt;more details here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is one example - adding icons and changing the theme&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Copy the Markdown link below, replacing &lt;code&gt;yourname&lt;/code&gt; with your GitHub username&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[![yourname's GitHub stats](https://github-readme-stats.vercel.app/api?username=yourname&amp;amp;show_icons=true&amp;amp;theme=radical)](https://github.com/yourname)&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub-readme-stats.vercel.app%2Fapi%3Fusername%3Dugmurthy%26show_icons%3Dtrue%26theme%3Dradical" alt="Murthy's GitHub stats" width="467" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Displaying Specific Stats:
&lt;/h4&gt;

&lt;p&gt;Top Languages: Show the languages you most frequently use by adding:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=yourname)](https://github.com/yourname)&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub-readme-stats.vercel.app%2Fapi%2Ftop-langs%2F%3Fusername%3Dugmurthy" alt="Top Langs" width="300" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Streak Stats: Include your coding streak with:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Copy the Markdown link below, replacing &lt;code&gt;yourname&lt;/code&gt; with your GitHub username&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[![GitHub Streak](https://streak-stats.demolab.com?user=yourname&amp;amp;border_radius=6)](https://github.com/yourname)&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstreak-stats.demolab.com%3Fuser%3Dugmurthy%26border_radius%3D6" alt="GitHub Streak" width="495" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Profile Readme Generator Tools:
&lt;/h3&gt;

&lt;p&gt;If you're looking for a more user-friendly way, tools like&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://profile-readme-generator.com/" rel="noopener noreferrer"&gt;GitHub Profile README Generator&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gh-stats-gen.vercel.app/" rel="noopener noreferrer"&gt;GitHub Stats generator&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github-stats.omsimos.com/" rel="noopener noreferrer"&gt;Omsimos GitHub StatsGenerator&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;can help you create a personalised README with various stats and styles. These tools provide templates and easy customisation options for your profile.&lt;/p&gt;

&lt;p&gt;I am sure there is more you can showcase such as, list your top repos and the stats relating to them - check out &lt;a href="https://githubtracker.com/dashboard" rel="noopener noreferrer"&gt;GitHub Tracker&lt;/a&gt; in case you are interested.&lt;/p&gt;

&lt;p&gt;That's it devs. By integrating these elements, you can enhance your GitHub profile to better showcase your coding activity and statistics. The exact customisation and choice of services depend on what you want to highlight on your profile.&lt;/p&gt;

</description>
      <category>github</category>
      <category>statistics</category>
    </item>
    <item>
      <title>SpeechTrack</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Sun, 24 Nov 2024 04:47:48 +0000</pubDate>
      <link>https://dev.to/murthyug/speechtrack-5c46</link>
      <guid>https://dev.to/murthyug/speechtrack-5c46</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/assemblyai"&gt;AssemblyAI Challenge &lt;/a&gt;: 1) Sophisticated Speech to Text, 2) Really Rad Real-Time. and 3) No more Monkey Business&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SpeechTrack
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Getting a deeper understanding of speech with &lt;a href="https://www.assemblyai.com/" rel="noopener noreferrer"&gt;AssemblyAI&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
Ever wondered how your speech sounds to others? Clarity and speed are the heartbeat of effective communication, but striking the perfect balance can be a challenge. &lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;SpeechTrack&lt;/strong&gt;, your real-time speech companion. &lt;br&gt;
With intuitive visual indicators for &lt;code&gt;Clarity&lt;/code&gt; and &lt;code&gt;Tempo&lt;/code&gt;, &lt;strong&gt;SpeechTrack&lt;/strong&gt; empowers you to refine your delivery through post speech &lt;code&gt;Feedback&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Whether you’re preparing for a big presentation, a podcast, or an important conversation, &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SpeechTrack&lt;/strong&gt; helps you speak with confidence, precision, and impact. &lt;/p&gt;

&lt;p&gt;Try it now and transform the way you communicate!&lt;/p&gt;

&lt;p&gt;
  Technical Overview
  &lt;ol&gt;
&lt;li&gt;App - built using &lt;code&gt;REMIX.run&lt;/code&gt; &amp;amp; &lt;code&gt;React&lt;/code&gt; web framework &lt;code&gt;tailwind.css&lt;/code&gt; and &lt;code&gt;daisyUI&lt;/code&gt; for styling&lt;/li&gt;
&lt;li&gt;App modules (at a high level)

&lt;ol&gt;
&lt;li&gt;Microphone - to stream Audio&lt;/li&gt;
&lt;li&gt;Websocket module for receiving messages from AssemblyAI&lt;/li&gt;
&lt;li&gt;AudioProcessor - to combine streamed Audio chunks to a .wav File object&lt;/li&gt;
&lt;li&gt;Various React components to process &amp;amp; assemble received messages and maintain application state&lt;/li&gt;
&lt;li&gt;Backend for front to deal with:

&lt;ul&gt;
&lt;li&gt; API keys and temporary tokens&lt;/li&gt;
&lt;li&gt; Uploading audio, &lt;/li&gt;
&lt;li&gt; Getting transcripts, &lt;/li&gt;
&lt;li&gt; asking LeMUR to do evaluation of Speech&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Finally present the Report in MARKDOWN format&lt;/li&gt;
&lt;li&gt;Maintain a history of last 3 Speeches in localStorage on client side
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;





&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;



&lt;p&gt;Six minute video explaining how &lt;strong&gt;SpeechTrack&lt;/strong&gt; works&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/fPCqXuN4JLY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;
  Screenshot: Show's Server Logs while doing above video
  &lt;br&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%2Fw6atithr9kbbkkf9gdtz.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%2Fw6atithr9kbbkkf9gdtz.png" alt="ServerLogs" width="800" height="490"&gt;&lt;/a&gt;&lt;br&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Here are some use cases:
&lt;/h3&gt;

&lt;h3&gt;
  
  
  1. Learning from good speakers.
&lt;/h3&gt;

&lt;p&gt;A good speaker can keep the audience spell bound. What is it that they do well that we can replicate. This inspiring speech is from the movie &lt;strong&gt;Coach Carter&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;
  Here is the Speech Evaluation Report from LeMUR
  &lt;h2&gt;
  
  
  Analysis &amp;amp; Feedback
&lt;/h2&gt;

&lt;p&gt;Here's my analysis and feedback for the speech transcript in a human-readable Markdown format:&lt;/p&gt;
&lt;h3&gt;
  
  
  Speech Evaluation
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Strengths
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effective Use of Pauses&lt;/strong&gt;: With 8.75 pauses per minute (ppm), the speaker is within the ideal range of 5-10 ppm. This allows listeners to process key ideas and adds emphasis to important points.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inspirational Content&lt;/strong&gt;: The speech contains powerful, motivational messages about personal empowerment and positive influence on others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concise Delivery&lt;/strong&gt;: At 104 words, the speech is relatively brief, which can help maintain audience attention and focus on core ideas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Areas for Improvement
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Speaking Speed&lt;/strong&gt;: At 130 words per minute (wpm), the pace is slightly below the ideal range of 140-200 wpm. Increasing the speed slightly could make the delivery more engaging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Filler Words&lt;/strong&gt;: The use of "ah" was noted in the transcript. Reducing or eliminating filler words can enhance clarity and professionalism.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structure&lt;/strong&gt;: While the content is inspirational, a clearer structure with an introduction, main points, and conclusion could improve overall coherence.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Summary Feedback
&lt;/h4&gt;

&lt;p&gt;The speaker delivers a powerful message with good use of pauses, allowing the audience to absorb the inspirational content. To enhance the speech:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Increase speaking speed slightly to reach the ideal range of 140-200 wpm.&lt;/li&gt;
&lt;li&gt;Eliminate filler words like "ah" to maintain a smooth flow of ideas.&lt;/li&gt;
&lt;li&gt;Consider structuring the speech more clearly, perhaps by grouping ideas into distinct sections.&lt;/li&gt;
&lt;li&gt;The personal touch at the end ("Sir, I just want to say thank you. You saved my life.") is impactful but seems abrupt. Consider a smoother transition or integration of this personal element.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By implementing these suggestions, the speaker can elevate an already powerful message to create an even more impactful and polished presentation.&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;
  Screenshot: Show's Transcript
  &lt;br&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%2Fweauwibr8ycqx128fsnw.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%2Fweauwibr8ycqx128fsnw.png" alt="Transcript" width="800" height="246"&gt;&lt;/a&gt;&lt;br&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  2. In-audio directives for Speech summary and sentiment Analysis.
&lt;/h3&gt;

&lt;p&gt;The first line of audio is always checked for any directives (Summary, Sentiment Analysis) before speech-&amp;gt;text transcript generation - see process details below. &lt;/p&gt;

&lt;p&gt;In the following video hear the first line direct the app to prepare for summary and sentiment analysis.&lt;/p&gt;

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

  Screenshot: Show's Realtime transcript with directives to parameter object
  &lt;br&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%2Fomxg0s3t0ydzvtq4zxuq.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%2Fomxg0s3t0ydzvtq4zxuq.png" alt="RT Transcript" width="800" height="553"&gt;&lt;/a&gt;&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  The various steps in the process Speech-&amp;gt;Transript-&amp;gt;Inference.
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## All lines except those with leading ##'s are from server logs
## Detection of directive from first line
f(getComnand) from first FinalTranscript: I would like you to generate a catchy summary and sentiment analysis of the following story. {
  summarization: true,
  summary_model: 'catchy',
  summary_type: 'gist',
  sentiment_analysis: true
}

## The streamed audio packets are then combined with .wav header and
## file object for the wave file is uploaded 

url : https://api.assemblyai.com/v2/upload

## we then have a URL to the uploaded audio
f(fileUpload) : Uploaded Successfully  {
  upload_url: 'https://cdn.assemblyai.com/upload/ebabc86a-0a1d-4988-a6f0-5dc06352921d'
}
f(fileUpload): 472.023ms
/api/upload fileUpload: 540.219ms

## NOTE: parameters for audioURL -&amp;gt; transcript
## disfluencies - so assemblyai can transcribing filler words
## Parameters below are computed for every speech and depend
## on first line - see below
## audio_start_from - ensure we don't include first line while asking 
/api/upload getTranscriptFromURL: 6.628s

f(getTranscriptFromURL) {
  audio: 'https://cdn.assemblyai.com/upload/ebabc86a-0a1d-4988-a6f0-5dc06352921d',
  disfluencies: true,
  summarization: true,
  summary_model: 'catchy',
  summary_type: 'gist',
  sentiment_analysis: true,
  audio_start_from: 10010
}

## Transcript id along with a CUSTOM PROMPT is submitted to leMUR for 
## specfic speech evaluation response.
## CUSTOM PROMPT contains:
## 1. Description of the Task evaluation details,
## 2. Required outline of the evaluation report
## 3. Acceptable standards of a good speech
## 4. App generated metrics (duration, words per min, pauses, etc)
## 5. Report format as markdown

/api/feedback  1129a02c-4a28-49ea-8fbf-cb55f89a0214
f(askLeMUR): 9.234s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;
  Screenshot: Show's Transcription and Sentiment Analysis
  &lt;br&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%2Fstpv95s1p7pq3xytlocv.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%2Fstpv95s1p7pq3xytlocv.png" alt="Sentiment" width="800" height="554"&gt;&lt;/a&gt;&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  CUSTOM PROMPT used with LeMUR
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are **SpeechEvaluator**, an expert in analyzing and 
providing constructive feedback on speech delivery. 
Your role is to assess the quality of a speaker's 
performance based on key metrics and provide 
actionable insights to help them improve. 
You will be given structured data from a speech analysis, 
including metrics like *Words per Minute (*wpm*)*, 
*Pauses per Minute (*ppm*)*, 
duration, and word count, along with a transcript. 

**Your Task**:  

1. **Analyze Metrics**: 
Evaluate the speaker's delivery based on provided quantitative 
data:  
- *wpm*: Assess speaking speed (ideal range: 140–200 wpm).
- *ppm*: Evaluate pause usage (ideal range: 5–10 ppm).    
- *duration*: Consider how metrics align with speech length.    
- *wc*: Check for verbosity or brevity based on context.  

2. **Assess Transcript**:   
- Identify clarity issues, such as filler words, redundancy, or lack of focus.     
- Highlight the effectiveness of pauses and transitions between topics.
- Comment on structure and coherence, ensuring ideas flow logically.  

3. **Provide Feedback**:     
- Highlight **strengths** (e.g., engaging delivery, appropriate speed).     
- Suggest **areas for improvement**, including specific and actionable tips.  

4. **Use Accessible Language**: 
- Ensure your feedback is clear and easy for the speaker to understand, 
even if they are new to public speaking or storytelling or presentations.  

### **Example Output**:  

#### **Strengths**  
- *Good Speaking Speed*: wpm is within the recommended range, making the delivery engaging and energetic.  
- *Use of Pauses*: Pauses are moderately frequent, allowing listeners time to process key ideas.  

#### **Areas for Improvement**  

- *Filler Words*: Repeated use of 'um', 'uh', 'like', 'you know', and 'I mean' distracts 
from the main message. Replace these with deliberate pauses.  
- *Structure and Clarity*: The speech lacks a clear structure and transitions, 
making it harder to follow. Organise thoughts into sections for better flow.  

#### **Summary Feedback**  

The speaker demonstrates confidence and an engaging pace but should focus on 
reducing filler words like 'uh', 'um', and structuring ideas more effectively. 
With these adjustments, the speech will feel more polished and impactful.  
Follow this format consistently to ensure feedback is constructive and actionable. 
DO NOT APOLOGIZE FOR INFORMATION NOT AVAILABLE FOR ABOVE ANALYSIS"

Below is the metrics from this Speech in JSON format. Use it to evaluate the speech.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy/voicetracker" rel="noopener noreferrer"&gt;Code Repository&lt;/a&gt;&lt;br&gt;
&lt;a href="//voicetracker-gt5vz8o79-murthy-udupas-projects.vercel.app"&gt;SpeechTrack&lt;/a&gt;&lt;br&gt;

  Application issues
  &lt;ol&gt;
&lt;li&gt;You get Error : &lt;code&gt;Not Authorized&lt;/code&gt;  inspite of providing an API key. Solution: Click &lt;code&gt;Next Speech&lt;/code&gt; to get a new token&lt;/li&gt;
&lt;li&gt;The Application is stuck with the Spinner on endlessly : This is a case of &lt;code&gt;http: 504 : Bad gateway&lt;/code&gt; Vercel.com times out serverless functions in 10secs. Most time leMUR task takes more time. Vercel serverless does not wait for long. Best is to run the application locally for big audio files. 
&lt;/li&gt;
&lt;/ol&gt;



&lt;/p&gt;
&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;





&lt;p&gt;The Assembly AI Hackathon immediately caught my attention. Exploring their &lt;strong&gt;Playground&lt;/strong&gt; gave me a basic understanding of their APIs, and soon I was diving deeper with &lt;code&gt;httpie&lt;/code&gt;, testing almost all REST APIs. The &lt;strong&gt;Speech-to-Text Streaming API&lt;/strong&gt; stood out as the most exciting, and I knew it would be the foundation of my project.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Building &lt;strong&gt;SpeechTrack&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the help of ChatGPT, I brainstormed ideas and finalised &lt;strong&gt;SpeechTrack&lt;/strong&gt;, a tool to provide &lt;strong&gt;real-time feedback&lt;/strong&gt; to speakers on:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clarity&lt;/strong&gt;, measured through confidence scores.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tempo&lt;/strong&gt;, tracked in words per minute.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The name was a nod to Assembly AI’s focus on unraveling speech, evolving from ChatGPT’s original suggestion of &lt;strong&gt;VoiceTrack&lt;/strong&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Steps in the Journey
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Exploring APIs&lt;/strong&gt;: I familiarised myself with Assembly AI’s tools using &lt;code&gt;httpie&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ideation&lt;/strong&gt;: Brainstormed (w/LLMs) and refined the concept for &lt;em&gt;SpeechTrack&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Used the &lt;strong&gt;Streaming API&lt;/strong&gt; for real-time speech insights.
&lt;/li&gt;
&lt;li&gt;Faced challenges with audio streaming and creating WAV files. Resources like the &lt;a href="https://github.com/AssemblyAI/realtime-transcription-browser-js-example" rel="noopener noreferrer"&gt;Assembly AI Realtime Transcription Example&lt;/a&gt; and &lt;a class="mentioned-user" href="https://dev.to/3kb-dev"&gt;@3kb-dev&lt;/a&gt;’s WAV file guide were lifesaver.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Coverage&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my opinion &lt;strong&gt;SpeechTrack&lt;/strong&gt; qualifies for all 3 challenge prompts as it ended up using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Streaming Speech-to-Text&lt;/em&gt; - to provide realtime cues (providing the audio and real-time transcript)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Speech-to-Text&lt;/em&gt; - Transcribe Audio (with in-audio parameter detection)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Speech Understanding&lt;/em&gt; (using transcript of (b) and LeMUR to provide analysis and feedback on Speech)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Feedback for Assembly AI
&lt;/h2&gt;

&lt;p&gt;The API's are excellent and can be better if the following were available (I hope I did not miss reading it in the documentation)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A way to download the audio file that was uploaded to Assembly AI&lt;/li&gt;
&lt;li&gt;A Streaming client for LeMUR. I noticed my app working locally but failing when hosted on &lt;code&gt;vercel.com&lt;/code&gt; with time outs or &lt;code&gt;http 504&lt;/code&gt;'s&lt;/li&gt;
&lt;li&gt;Lastly, For LeMUR tasks I would like have an API similar to what &lt;a href="https://openrouter.ai/" rel="noopener noreferrer"&gt;OpenRouter&lt;/a&gt; provides as that will expand access to models and allow good control over what we can instruct the model to do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, I see a lot of possibilities, keep up the good work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflections &amp;amp; Conclusion
&lt;/h2&gt;

&lt;p&gt;Though the journey had its hurdles, completing &lt;strong&gt;SpeechTrack&lt;/strong&gt; was immensely satisfying. Thanks to &lt;strong&gt;Assembly AI&lt;/strong&gt; for their fantastic APIs, great support (thanks to &lt;strong&gt;Lee Vaughn&lt;/strong&gt; of Support Engineering at Assembly AI) and the Dev community for their support. Here’s to more learning and creating in the future!  &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>assemblyaichallenge</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>Personas - an Ai Assistant</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Sun, 14 Apr 2024 16:37:05 +0000</pubDate>
      <link>https://dev.to/murthyug/personas-an-ai-assistant-50ec</link>
      <guid>https://dev.to/murthyug/personas-an-ai-assistant-50ec</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/devteam/join-us-for-the-cloudflare-ai-challenge-3000-in-prizes-5f99"&gt;Cloudflare AI Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built and What it does
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dictionary.cambridge.org/dictionary/english/persona" rel="noopener noreferrer"&gt;&lt;code&gt;Personas&lt;/code&gt;&lt;/a&gt; is a AI assistant - a Web app demonstrating the ease with which one can build app using Cloudflare Pages Cloudflare Worker combined with Cloudflare AI which provides plethora of AI models for a wide range of tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://main.cldflr-remix-app.pages.dev/" rel="noopener noreferrer"&gt;Try Persona&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=N1g5LcbIgV0" rel="noopener noreferrer"&gt;A 2 minute video demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PERSONAS&lt;/code&gt; Showcases 3 &lt;code&gt;personas&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Story Writer&lt;/code&gt; that is kidSafe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Coding Assistant&lt;/code&gt; that can help a developer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Sentiment Analysis &amp;amp; Reasoning&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above &lt;code&gt;personas&lt;/code&gt; can take &lt;strong&gt;voice&lt;/strong&gt; or &lt;strong&gt;text&lt;/strong&gt; as input and will respond based on &lt;strong&gt;Handrails&lt;/strong&gt; provided by the &lt;code&gt;system&lt;/code&gt; prompt for the respective models.&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%2Feir5r2pjpeh9e0uj7quf.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%2Feir5r2pjpeh9e0uj7quf.png" alt="Image description" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Story Writer&lt;/code&gt; generates stories appropriate for Kids under 10 years with the option of translating to German. One can also analyse sentiment of the input prompt and seek the reasoning behind the evaluation. [tasks: &lt;em&gt;Text Generation, Transation, Voice to text&lt;/em&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%2Fz7clt28t1vmfsoc9bldj.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%2Fz7clt28t1vmfsoc9bldj.png" alt="Image description" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Coding Assistant&lt;/code&gt; is a useful for generating small code snippets in most programming languages, including syntax highlighting. You can also ask it to explain how a particular piece of code works. I used it do some of the grunt work for this project including getting ideas for react components.[tasks: &lt;em&gt;Code Generation, and voice Voice to text&lt;/em&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%2F0ta7i8fjorvnso45q875.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%2F0ta7i8fjorvnso45q875.png" alt="Sentiment Analysis" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Sentiment Analysis &amp;amp; Reasoning&lt;/code&gt; This was to demonstrate a good &lt;code&gt;system&lt;/code&gt; prompt can be leverage an existing model and reduce reliance on specialist models for sentiment analysis. Here we see the the same text generation model used on &lt;code&gt;Story Writer&lt;/code&gt; producing structured output as a JSON - which will be pretty useful for decision making in a chain of tasks.[tasks: &lt;em&gt;Structured text Generation, Voice to text&lt;/em&gt;]&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://main.cldflr-remix-app.pages.dev/" rel="noopener noreferrer"&gt;Try Persona&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=N1g5LcbIgV0" rel="noopener noreferrer"&gt;A 2 minute video demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ugmurthy/cldflr-remix-app" rel="noopener noreferrer"&gt;Code on Github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;I came to know about the challenge on 4th April. Initially, I wasn't planning on doing much considering I was new to Cloudflare and learning about it seemed a daunting task. &lt;/p&gt;

&lt;p&gt;This introductory &lt;a href="https://www.youtube.com/watch?v=YoPwfd7AljE" rel="noopener noreferrer"&gt;video&lt;/a&gt; and the the &lt;a href="https://developers.cloudflare.com/workers-ai/" rel="noopener noreferrer"&gt;Cloufare Workers AI&lt;/a&gt; got me started in no time.&lt;/p&gt;

&lt;p&gt;Development process&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tested ideas for system prompt using &lt;a href="https://playground.ai.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare AI playground&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;User examples in AI tutortials to build end points&lt;/li&gt;
&lt;li&gt;tested the end points using &lt;a href="https://httpie.io/" rel="noopener noreferrer"&gt;httpie&lt;/a&gt; and sometime &lt;code&gt;curl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Built the frontend with &lt;a href="https://remix.run/docs/en/main/future/vite#cloudflare" rel="noopener noreferrer"&gt;REMIX-Cloudflare&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multiple Models and/or Triple Task Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Four Models were used to achieve many tasks Story Generation, Translation, Code Generation and Sentiment analysis:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@hf/mistral/mistral-7b-instruct-v0.2&lt;/code&gt; two tasks:&lt;/li&gt;
&lt;li&gt;Story Generation, &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sentiment Analysis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@cf/thebloke/discolm-german-7b-v1-awq&lt;/code&gt; for language translation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@hf/thebloke/codellama-7b-instruct-awq&lt;/code&gt; for Code Generation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@cf/openai/whisper&lt;/code&gt; for audio to text transcription.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some unsung heros (commands/tools/libraries) without which this would have been impossible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wrangler npx wrangler pages deployment tail &amp;lt;deployment id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;https&lt;/code&gt; from &lt;a href="https://httpie.io/" rel="noopener noreferrer"&gt;httpie&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zod&lt;/code&gt;, &lt;code&gt;zodix&lt;/code&gt; js modules to do validation and parsing&lt;/li&gt;
&lt;li&gt;and last but not the least &lt;code&gt;lodash&lt;/code&gt; my fav goto for anything that you think is impossible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Future Plans:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extend Story Writer to be hands free - voice commands for stories : &lt;em&gt;hey Monk, tell me a story a picture story&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Do Sentiment Analysis before generating stories.&lt;/li&gt;
&lt;li&gt;Create Custom Persona &lt;/li&gt;
&lt;li&gt;Extend the App to leverage Local open source LLMs from &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;ollama.ai&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Exploring Cloudflare LORA support for training to improve &lt;code&gt;Personas&lt;/code&gt; further&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Learning&lt;/strong&gt; Lots of things learnt over last 7/8 days. From not knowing what is Cloudflare to deploying - I am pretty happy with the outcome.  I was proud of two components I implement &lt;br&gt;
1) Component to catch streaming data &lt;br&gt;
2) the audio component. Both were challenging &lt;/p&gt;

&lt;p&gt;Many Thanks to &lt;a href="https://www.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt; and &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt; for giving us this opportunity.&lt;/p&gt;

</description>
      <category>cloudflarechallenge</category>
      <category>devchallenge</category>
      <category>ai</category>
    </item>
    <item>
      <title>A blogsite template using @11ty</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Wed, 29 Jul 2020 09:10:07 +0000</pubDate>
      <link>https://dev.to/murthyug/a-blogsite-template-using-11ty-1gc3</link>
      <guid>https://dev.to/murthyug/a-blogsite-template-using-11ty-1gc3</guid>
      <description>&lt;p&gt;I was reading an article on &lt;em&gt;Serverless&lt;/em&gt;, this lead me to few terms/technologies/concepts that I wasn't familiar ; &lt;em&gt;Jamstack&lt;/em&gt; and &lt;em&gt;static generators&lt;/em&gt;. Exploring this terms led me to an introductory video on &lt;a href="https://jamstack.training/courses/enrolled/693067" rel="noopener noreferrer"&gt;Creating a blog&lt;/a&gt;. This encouraged me to build a &lt;em&gt;customisable blogsite template&lt;/em&gt; with following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customisable blogsite ( &lt;code&gt;modify _data/site.js&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;Two column site - left column acting as navigator to blog posts&lt;/li&gt;
&lt;li&gt;uses @11ty to build&lt;/li&gt;
&lt;li&gt;uses bootstrap 4 for styles&lt;/li&gt;
&lt;li&gt;is responsive&lt;/li&gt;
&lt;li&gt;uses highlightjs for code blocks&lt;/li&gt;
&lt;li&gt;blog posts are markdown files (see samples: &lt;code&gt;/posts/*.md&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;search blog content (left navigator shows resulting posts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where can I try it out?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://blog11ty.netlify.app/index.html" rel="noopener noreferrer"&gt;the live site&lt;/a&gt; on netlify.com (images load a bit slowly - dont know why?)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I use this template?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork  a copy of &lt;a href="https://github.com/ugmurthy/blog" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; to your github account and clone to your local machine&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install and build locally&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; 
$ cd ~/blosite # change directory to you blogsite
$ npm install
$ npx @11ty/eleventy --serve
# Browse locally to check if you can access the blogsite
# check the search function too.
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Signup with &lt;a href="http://www.netlify.com" rel="noopener noreferrer"&gt;www.netlify.com&lt;/a&gt; using your github account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build this repo using netlify.com (when you signup - netlify.com will guide you - chose defaults and you are done)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the first 4 steps were successful i.e. you are able to see your site on netlify then proceed with customisation&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customise it by modifying contents of &lt;code&gt;_data/site.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modify index.njk, about.njk as needed&lt;/li&gt;
&lt;li&gt;Write you posts in markdown. All posts will reside ins &lt;code&gt;posts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ensure you update variables in frontmatter especially &lt;code&gt;date&lt;/code&gt; to date of posting (as YYYY-MM-DD )else it defaults to file creation date which will keep changing to build date and thus not preserving order of the blogs in left navigator.&lt;/li&gt;
&lt;li&gt;git commit the changes if any and push it to origin&lt;/li&gt;
&lt;li&gt;netlify.com will automatically build the external blogsite.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Your feedback will be most appreciated - thanks for taking the time to read&lt;/em&gt;&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;@11ty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ianfeather.co.uk/moving-this-blog-from-jekyll-to-11ty/" rel="noopener noreferrer"&gt;Ian Feather account of moving from jekyll to 11ty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://24ways.org/2018/turn-jekyll-up-to-eleventy/" rel="noopener noreferrer"&gt;Paul Robert Lloyd experience moving from jekyll to 11ty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://highlightjs.org/" rel="noopener noreferrer"&gt;Highlighting code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fullstacktraining/11ty-blog-jamstack-training/tree/module-1" rel="noopener noreferrer"&gt;starter code for this blogsite template&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jamstack.training/courses/enrolled/693067" rel="noopener noreferrer"&gt;Create a blog using Jamstack&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Attribution&lt;/strong&gt;&lt;br&gt;
Image in this post by: &lt;a href="https://www.freepik.com" rel="noopener noreferrer"&gt;Cookie_studio / Freepik&lt;/a&gt;&lt;/p&gt;

</description>
      <category>eleventy</category>
      <category>javascript</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>vim: Buffers, Windows, Tabs - Part 1</title>
      <dc:creator>U G Murthy</dc:creator>
      <pubDate>Tue, 09 Jun 2020 10:27:54 +0000</pubDate>
      <link>https://dev.to/murthyug/vim-buffers-windows-tabs-part-1-1h7b</link>
      <guid>https://dev.to/murthyug/vim-buffers-windows-tabs-part-1-1h7b</guid>
      <description>&lt;p&gt;Any developer involved in a large software developement project is actively editing multiple source files. There are multiple factors that makes such a developer efficient in the task of editing multiple files. Generally speaking such efficiency depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;navigating from one active file to another seamlessly&lt;/li&gt;
&lt;li&gt;and active viewing area&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;vim&lt;/strong&gt; provides way to do this using &lt;strong&gt;buffers, windows and tabs&lt;/strong&gt;. In this article we will focus on &lt;strong&gt;buffers and windows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we get to the details lets understand the terms &lt;strong&gt;buffers and windows&lt;/strong&gt; in &lt;strong&gt;vim&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;buffer&lt;/strong&gt; is the in-memory text of the file that was opened using vim. It may be visible or hidden. It is identified by a buffer number and has flags to indicate whether it is current, has been modified or not etc.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;window&lt;/strong&gt; is a view port on a buffer whereas&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;tab&lt;/strong&gt; is a collection of &lt;strong&gt;windows&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When vim opens a file, a buffer is associated with it. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;vi server.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Not every buffer is associated with a file. We will see an example later.&lt;/p&gt;

&lt;p&gt;Once in vim. Enter the following command in normal mode&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:ls&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;which will show buffer information as below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;1 %a   "server.js"                    line 1&lt;br&gt;
Press ENTER or type command to continue&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The integer &lt;code&gt;1&lt;/code&gt; refers to the buffer number&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;%a&lt;/code&gt; is a flag indicating that this is the active buffer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"server.js"&lt;/code&gt; the filename and &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;line 1&lt;/code&gt; indicate the current line on which the cursor is positioned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets now open two more buffers. While in vim you can open another file by:&lt;br&gt;
&lt;code&gt;:edit config.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets also create a buffer without any file associated with it:&lt;br&gt;
&lt;code&gt;:enew&lt;/code&gt;&lt;br&gt;
and list all the buffers using &lt;code&gt;:ls&lt;/code&gt; vim command. &lt;br&gt;
&lt;code&gt;1      "server.js"                    line 1&lt;br&gt;
  2 #    "config.json"                  line 1&lt;br&gt;
  3 %a   "[No Name]"                    line 1&lt;br&gt;
Press ENTER or type command to continue&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; buffer number 3 has "no name" and is active.&lt;/p&gt;

&lt;p&gt;Switching between buffers is easy. Use &lt;code&gt;:bn&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is buffer number &lt;code&gt;:b2&lt;/code&gt; will switch to buffer 2, makin it active. &lt;br&gt;
Switching between buffers will work if the changes to a buffer is saved.&lt;/p&gt;

&lt;p&gt;To view all buffers enter the following command in vim&lt;br&gt;
&lt;code&gt;:ball&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will now see three horizonal windows. You can switch from one to another by  followed by any of the arrow keys.&lt;/p&gt;

&lt;p&gt;Try &lt;code&gt;:ls&lt;/code&gt; to check all buffers are now active as they are all visible.&lt;/p&gt;

&lt;p&gt;You can close the the current window by  followed by 'c' or by entering &lt;code&gt;:q&lt;/code&gt; command. The window closes but the buffer is still there.&lt;/p&gt;

&lt;p&gt;for more information on vim buffers enter the following command in vim&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:help buffers&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next week look out for more on windows and tabs in Part-2 of this post.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>buffers</category>
      <category>windows</category>
      <category>tabs</category>
    </item>
  </channel>
</rss>
