<?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: Nathan Tarbert</title>
    <description>The latest articles on DEV Community by Nathan Tarbert (@nathan_tarbert).</description>
    <link>https://dev.to/nathan_tarbert</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1031984%2Fe6629bb7-d446-4f40-b537-d2fa664bf5fd.jpg</url>
      <title>DEV Community: Nathan Tarbert</title>
      <link>https://dev.to/nathan_tarbert</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nathan_tarbert"/>
    <language>en</language>
    <item>
      <title>My open source project is brand new and already has contributors. Here's what I did.</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Fri, 30 Oct 2026 16:03:47 +0000</pubDate>
      <link>https://dev.to/nathan_tarbert/my-open-source-project-is-brand-new-and-already-has-contributors-heres-what-i-did-3fb4</link>
      <guid>https://dev.to/nathan_tarbert/my-open-source-project-is-brand-new-and-already-has-contributors-heres-what-i-did-3fb4</guid>
      <description>&lt;p&gt;In the spirit of Hacktoberfest, with it being the last day of October, I wanted to share my story about open source and building in public. &lt;/p&gt;

&lt;p&gt;I'm a DevRel. In my day job, I help people who've never contributed to open source get their first code shipped. So when I started building &lt;a href="https://github.com/answerLoops/answerLoops" rel="noopener noreferrer"&gt;answerLoops&lt;/a&gt;, an open source, self-hostable AI support tool, one thing bugged me. Was my own project actually easy to jump into?&lt;/p&gt;

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

&lt;p&gt;answerLoops turns your knowledge source into answers for your community. It's self-hostable, so you can run it on your own infrastructure with the AI provider you choose, or use the hosted app.&lt;/p&gt;

&lt;p&gt;Here's the workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A question comes in from a community channel like Discord, Slack, Discourse, GitHub, or website chat.&lt;/li&gt;
&lt;li&gt;answerLoops searches your knowledge: your docs, files, GitHub repos, and Notion pages.&lt;/li&gt;
&lt;li&gt;It drafts a reply with the sources attached.&lt;/li&gt;
&lt;li&gt;A second AI agent checks the draft against those sources.&lt;/li&gt;
&lt;li&gt;Your team approves the reply, or you turn on auto-reply for the questions that pass the check.&lt;/li&gt;
&lt;li&gt;Useful resolutions are saved as knowledge, and knowledge gaps show what your docs are missing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That workflow is why the labels below make sense. &lt;code&gt;frontend&lt;/code&gt; work touches the dashboard where a team reviews and approves replies. &lt;code&gt;backend&lt;/code&gt; work touches the pipeline and the channel integrations behind it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/answerLoops/answerLoops" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore answerLoops on ⭐️ GitHub&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The project is new, so the hard part right now is getting off the ground and getting people to find it. I posted about it on Reddit and X. It didn't bring in many stars. So I changed where I put my effort. Instead of trying to reach everyone, I focused on developers who want to build something and on making it easy for them to start.&lt;/p&gt;

&lt;p&gt;Over the last week, developers started showing up. They sent pull requests, and I merged them. Some built something from an open issue. Others found a problem on their own and fixed it.&lt;/p&gt;

&lt;p&gt;I can't prove any of this is cause and effect. I have a handful of data points, and some of them didn't pick up an issue at all. But I did set a few things up beforehand, and I think they're worth writing down for anyone starting out.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. I labeled issues by skill, not just by type
&lt;/h2&gt;

&lt;p&gt;At first my issues only had the usual labels: &lt;code&gt;enhancement&lt;/code&gt;, &lt;code&gt;bug&lt;/code&gt;, &lt;code&gt;documentation&lt;/code&gt;. That tells a contributor what kind of change it is, but not whether it's for them.&lt;/p&gt;

&lt;p&gt;I added two labels: &lt;code&gt;frontend&lt;/code&gt; and &lt;code&gt;backend&lt;/code&gt;. Right now I have &lt;a href="https://github.com/answerLoops/answerLoops/issues" rel="noopener noreferrer"&gt;58 open issues&lt;/a&gt;, 41 tagged &lt;code&gt;frontend&lt;/code&gt; and 33 tagged &lt;code&gt;backend&lt;/code&gt;. Someone can click one label and see only the work that matches their skills, without reading all 58.&lt;/p&gt;

&lt;p&gt;I also use &lt;code&gt;good first issue&lt;/code&gt; and &lt;code&gt;help wanted&lt;/code&gt;. &lt;code&gt;good first issue&lt;/code&gt; is the one most people already know. The skill labels are the new part.&lt;/p&gt;

&lt;p&gt;Most of the PRs I merged closed an issue with one of these labels, so they look like they're doing something. I'm still careful about how much I claim.&lt;/p&gt;

&lt;p&gt;One side effect: only 8 &lt;code&gt;good first issue&lt;/code&gt; tickets are open now. Labels only work while there's something behind them, so I'm writing more.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. I wrote issues like specs
&lt;/h2&gt;

&lt;p&gt;I'd have undersold this one if I'd only written about labels.&lt;/p&gt;

&lt;p&gt;The issue my first contributor picked up was tagged &lt;code&gt;frontend&lt;/code&gt;, &lt;code&gt;good first issue&lt;/code&gt;, and &lt;code&gt;help wanted&lt;/code&gt;. It was also written so that someone who had never seen the codebase could start. It had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Problem&lt;/strong&gt; section: the data was already being collected and stored, but nothing in the UI showed it.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Scope&lt;/strong&gt; section: exactly what to show, where to start looking in the code, and what the wording should be.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Not in this issue&lt;/strong&gt; section: what to leave alone, so nobody drifts into a bigger project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acceptance criteria&lt;/strong&gt; as a checklist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also said it was part of a larger tracking issue, so a contributor could see where it fit.&lt;/p&gt;

&lt;p&gt;A vague issue like "show usage on the article page" leaves a newcomer guessing about scope, wording, and what "done" means. A scoped one lets them start. If I had to pick one thing to copy, it's this.&lt;/p&gt;

&lt;p&gt;Every issue also ends with a link to the &lt;a href="https://github.com/answerLoops/answerLoops/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;contributing guide&lt;/a&gt;, and it's now built into the Issues template.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. I made the project easy to run
&lt;/h2&gt;

&lt;p&gt;You can't contribute to something you can't start. I rewrote the &lt;a href="https://github.com/answerLoops/answerLoops/blob/main/README.md" rel="noopener noreferrer"&gt;README&lt;/a&gt; to be a short overview, and added a &lt;a href="https://github.com/answerLoops/answerLoops/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING guide&lt;/a&gt; plus issue forms for bugs, features, integrations, and docs, so new reports come in with the details I need.&lt;/p&gt;

&lt;p&gt;The first version of the setup steps wasn't good enough. It ran the Docker path, then said "or run it natively," and I couldn't tell you which one to pick. If I was confused, a newcomer was too. I rewrote it as three steps: clone the app, set the values in one &lt;code&gt;.env&lt;/code&gt;, and run it. Then I ran the native steps myself against a fresh database to make sure they work.&lt;/p&gt;

&lt;p&gt;Contributors have already improved the docs from there, including a diagram of the install flow in the self-hosting quickstart.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Review was fast, and the PRs made it easy
&lt;/h2&gt;

&lt;p&gt;The PRs came with a clear description of what changed, why, and how to try it. That made them easy to review, and I could merge quickly.&lt;/p&gt;

&lt;p&gt;Fast feedback matters. A first-time contributor who waits two weeks for a reply rarely comes back.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. I said thank you in public
&lt;/h2&gt;

&lt;p&gt;The contributors are credited in the release notes and in the docs, and I thanked them publicly. Open source is mostly volunteers, so it's the least I can do. It also shows the next person what happens when they contribute.&lt;/p&gt;

&lt;p&gt;I also posted on &lt;a href="https://lnkd.in/p/e8FTWqBq" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://x.com/nathan_tarbert/status/2113983226062533116" rel="noopener noreferrer"&gt;X&lt;/a&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8zfwxintxejup9268sll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8zfwxintxejup9268sll.png" alt=" " width="800" height="686"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks Aaqibhafeez Khan for the kind words&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I got wrong, or am not sure of
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I don't know if the labels worked 100%.&lt;/strong&gt; Nothing else about the project changed much, but I also posted about it in a few places, which brings people in on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not everyone took a labeled issue.&lt;/strong&gt; Some contributors found a problem nobody had filed, and the labels can't explain that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return visits are the real test.&lt;/strong&gt; What matters is whether people come back for a second PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The supply runs out.&lt;/strong&gt; Contributors finish &lt;code&gt;good first issue&lt;/code&gt; tickets quickly. Writing good ones is now a regular chore for me.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If you want to try this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Label issues by the skill needed, not just the type of change.&lt;/li&gt;
&lt;li&gt;Write one issue as a spec: problem, scope, what's out of scope, and acceptance criteria.&lt;/li&gt;
&lt;li&gt;Make sure someone can run the project, and test those steps yourself.&lt;/li&gt;
&lt;li&gt;Review fast.&lt;/li&gt;
&lt;li&gt;Thank people in public.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're new to open source and want help with a first PR, leave a comment or message me. I'm happy to walk you through it. The open issues are here: &lt;a href="https://github.com/answerLoops/answerLoops/issues" rel="noopener noreferrer"&gt;https://github.com/answerLoops/answerLoops/issues&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you maintain a project: what got your first outside contributors to show up?&lt;/p&gt;

&lt;p&gt;P.S. If you're reading this, starring ⭐️ the &lt;a href="https://github.com/answerLoops/answerLoops" rel="noopener noreferrer"&gt;repo&lt;/a&gt; also really helps people find it :)&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building an Open-Source Support Tool That Turns Your Docs into Reusable Knowledge</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Tue, 20 Oct 2026 17:15:15 +0000</pubDate>
      <link>https://dev.to/nathan_tarbert/your-team-has-answered-this-before-im-building-a-tool-that-remembers-5604</link>
      <guid>https://dev.to/nathan_tarbert/your-team-has-answered-this-before-im-building-a-tool-that-remembers-5604</guid>
      <description>&lt;p&gt;I spend a good part of my day working with the community at CopilotKit, answering questions in Discord, GitHub, and Slack, helping people get unstuck, and pointing them to the right resources.&lt;/p&gt;

&lt;p&gt;I started building &lt;a href="https://github.com/answerLoops/answerLoops" rel="noopener noreferrer"&gt;answerLoops&lt;/a&gt; to help me with that work. As it took shape, I added integrations for more platforms so other teams could use it in their communities too.&lt;/p&gt;

&lt;p&gt;It’s open source, and I’m building it in public.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/answerLoops/answerLoops" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore answerLoops on ⭐️ GitHub&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;A big part of the work has been deciding how knowledge gets into the system. Some answers are in the docs. Others come out of a support conversation or are things someone on the team just knows.&lt;/p&gt;

&lt;p&gt;For an agent to use those answers, the team needs a straightforward way to save them, review them, and keep them current. That’s what I’ve been building into the knowledge base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Answering the question is only part of the work
&lt;/h2&gt;

&lt;p&gt;A question comes in. You find the relevant documentation or resource, figure out how it applies to that person’s setup, and write a reply.&lt;/p&gt;

&lt;p&gt;During that conversation, you might discover something the docs don’t cover. A missing setup step, a confusing default, or a workaround that deserves its own article.&lt;/p&gt;

&lt;p&gt;You resolve the question, but that useful detail stays buried in the conversation. When someone else asks, the team has to find it again.&lt;/p&gt;

&lt;p&gt;I want answerLoops to help with both parts: preparing a useful answer now and saving what the team learns for future questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What answerLoops does
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21k4d1099k5yfp24yke0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21k4d1099k5yfp24yke0.png" alt="Ticket and website chat workflows in answerLoops" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;answerLoops is an open-source AI support tool that brings questions from Discord, Slack, GitHub, Telegram, and other connected channels into one dashboard. It uses your knowledge base to help prepare answers.&lt;/p&gt;

&lt;p&gt;For knowledge-based replies in the ticket pipeline, a Mastra agent generates a draft and a separate agent scores its confidence and whether it fully answers the question. Automatic replies are off by default. When enabled, answers that meet the configured criteria can be sent automatically; other drafts remain available for human review.&lt;/p&gt;

&lt;p&gt;There’s also an embeddable website chat widget built with CopilotKit and connected to a Mastra support agent. Visitors can ask questions directly, with published knowledge-base articles supplied as reference material.&lt;/p&gt;

&lt;p&gt;The widget supports richer responses, including step-by-step guides, quick replies, callouts, link cards, and contact options.&lt;/p&gt;

&lt;p&gt;But the quality of those answers depends on the information available to the agent. That’s why much of the recent work has been on the knowledge base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the answer that isn’t in your docs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F905by9pwudz9d445bzj3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F905by9pwudz9d445bzj3.gif" alt="Entering a question and answer, then publishing it directly to the knowledge base" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you don’t need to import a documentation site. You just need to write down something the agent should know.&lt;/p&gt;

&lt;p&gt;An owner or admin can open &lt;strong&gt;Knowledge Base → Manage&lt;/strong&gt; and use &lt;strong&gt;Write an answer by hand&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter a question or title.&lt;/li&gt;
&lt;li&gt;Write the answer or context.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add to knowledge base&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, a customer might ask whether changing a configuration requires a restart. Someone on your team knows the answer, but it isn’t documented anywhere.&lt;/p&gt;

&lt;p&gt;The article is published and indexed when it’s saved, making it available for subsequent questions. There’s no draft step in this form, so the answer should be suitable for customers to read.&lt;/p&gt;

&lt;p&gt;Adding an article doesn’t retrain the model. It gives the agent another reference to retrieve when a relevant question comes in.&lt;/p&gt;

&lt;p&gt;Articles added this way appear under &lt;strong&gt;Added by hand&lt;/strong&gt; in the Knowledge coverage tab.&lt;/p&gt;

&lt;p&gt;It’s a small feature, but it gives the person with the answer a direct way to improve what the agent knows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bring in the knowledge you already have
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozmg8uwzn0d06kchipy2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozmg8uwzn0d06kchipy2.png" alt="Knowledge sources including documentation, files, GitHub, Notion, manual answers, and resolved tickets" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also populate the knowledge base from existing content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation URLs:&lt;/strong&gt; import a page or crawl a documentation site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Files:&lt;/strong&gt; upload PDF, DOCX, Markdown, text, or CSV files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; sync Markdown and MDX files, with optional syncs when changes are pushed to the default branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notion:&lt;/strong&gt; connect pages and databases your team wants to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notion content imports unpublished. Your team can inspect it before making it available for customer-facing answers, and that publishing choice is preserved across syncs.&lt;/p&gt;

&lt;p&gt;The manual-entry form sits alongside these sources. If an answer already exists in your docs, import it. If it only exists in someone’s head, write it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn a resolved ticket into reusable knowledge
&lt;/h2&gt;

&lt;p&gt;Closing a ticket helps the person who asked. Turning that resolution into a knowledge-base article makes the explanation available for future questions.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Promote to KB&lt;/strong&gt; action lets an owner or admin turn that ticket’s question and answer into a knowledge-base article.&lt;/p&gt;

&lt;p&gt;Before promoting it, check that the answer applies beyond the original conversation. Remove account-specific details and make the explanation useful to someone encountering the same problem later.&lt;/p&gt;

&lt;p&gt;This matters for the website widget in particular. Its retrieved reference material comes from published KB articles, rather than raw resolved tickets.&lt;/p&gt;

&lt;p&gt;Promoting an answer gives it a place in the shared knowledge base where the widget can find it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let customer questions help you decide what to write
&lt;/h2&gt;

&lt;p&gt;You won’t know every gap in your documentation ahead of time.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Review&lt;/strong&gt; tab captures questions that weren’t covered by the available knowledge. On hosted plans, this queue is available on Pro and above.&lt;/p&gt;

&lt;p&gt;A usable draft can come along as a starting point. If there isn’t one, the item is marked &lt;strong&gt;No usable answer&lt;/strong&gt;, and someone can write it.&lt;/p&gt;

&lt;p&gt;Owners and admins can edit the question and answer, then choose &lt;strong&gt;Approve and add to knowledge base&lt;/strong&gt;. If the item shouldn’t become an article, they can reject it instead.&lt;/p&gt;

&lt;p&gt;Nothing in the queue becomes searchable customer-facing knowledge until it’s approved.&lt;/p&gt;

&lt;p&gt;When the same question comes in again, its counter increases instead of creating another copy. The most-asked questions appear first.&lt;/p&gt;

&lt;p&gt;If several people ask about the same setup step, that’s a useful signal about what your knowledge base is missing. The queue gives your team a question to work from and a place to review the answer before publishing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go from a knowledge gap to a new article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fggvfo6g6ansyq0q7l859.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fggvfo6g6ansyq0q7l859.png" alt="The review queue and Knowledge Gaps provide separate paths to adding published articles" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Knowledge Gaps&lt;/strong&gt; page provides another view of where support needs attention.&lt;/p&gt;

&lt;p&gt;It surfaces tickets with low-confidence answers, tickets that need a person, and resolved questions without a covering KB article.&lt;/p&gt;

&lt;p&gt;Repeated questions are grouped with an &lt;strong&gt;Asked N times&lt;/strong&gt; badge, so you can see recurring topics without reading every ticket separately.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;+ KB&lt;/strong&gt; action opens the manual-entry form with the ticket’s question and any existing answer filled in. Review the text, add the article, and it’s linked back to the ticket to close that gap.&lt;/p&gt;

&lt;p&gt;You don’t have to leave the question behind and start a blank document somewhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check what the agent can actually find
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2nlrd9a0mbmweozc4hr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2nlrd9a0mbmweozc4hr9.png" alt="Knowledge coverage shows article availability and lets you test the widget’s retrieval" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Importing a document doesn’t tell you whether it will help with a particular question.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Knowledge coverage&lt;/strong&gt; tab shows articles grouped by source, including whether they’re live, unpublished, or not searchable.&lt;/p&gt;

&lt;p&gt;There’s also a &lt;strong&gt;Try a customer question&lt;/strong&gt; field. It runs the same lookup the website widget uses and shows which articles match—or that nothing covers the question.&lt;/p&gt;

&lt;p&gt;After adding an answer, try the original customer question and a few variations. Does the lookup find the article you just wrote? If it doesn’t, you have something concrete to investigate before judging the generated reply.&lt;/p&gt;

&lt;p&gt;This checks retrieval, not whether every generated reply will be correct. You still need to review the answers themselves. But it gives you a way to investigate whether the intended information is being found.&lt;/p&gt;

&lt;p&gt;The KB is the source of product knowledge your team maintains for the agent. If no article matches, the assistant can fall back to general knowledge, which may not fit your product. Finding those gaps and adding the right material is part of maintaining it.&lt;/p&gt;

&lt;h2&gt;
  
  
  See which articles are being used
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2i86xfl1031fo3ougx44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2i86xfl1031fo3ougx44.png" alt="Article usage tracks references supplied for generated answers, excluding searches and simulations" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;answerLoops also tracks article usage.&lt;/p&gt;

&lt;p&gt;It counts when an article is supplied as context for an answer that is actually produced, including website replies and ticket drafts.&lt;/p&gt;

&lt;p&gt;The distinction matters: this means the article was given to the agent, not necessarily that the final reply quoted it.&lt;/p&gt;

&lt;p&gt;Searches and simulations don’t increase the count.&lt;/p&gt;

&lt;p&gt;Together with the coverage view and repeated-question counts, this helps you understand what information is being retrieved and where more work might be useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where CopilotKit and Mastra fit
&lt;/h2&gt;

&lt;p&gt;I work in DevRel at CopilotKit, so part of building answerLoops is putting the tools I work with into a product and sharing what I learn.&lt;/p&gt;

&lt;p&gt;Mastra runs the agents behind the support drafts and website conversation, including the chat agent’s thread memory.&lt;/p&gt;

&lt;p&gt;CopilotKit provides the foundation for the custom widget interface. The application connects that interface to the agent and supplies the relevant knowledge-base context.&lt;/p&gt;

&lt;p&gt;The product also has its own workflows around those pieces: importing sources, reviewing unanswered questions, publishing articles, and handling staff actions on tickets.&lt;/p&gt;

&lt;p&gt;Those workflows are where the team gets to improve the information the agent uses. Someone can spot a missing answer, write it, publish it, and check whether a future question retrieves it.&lt;/p&gt;

&lt;p&gt;That’s become a much bigger part of answerLoops as I’ve kept building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, I would love your feedback
&lt;/h2&gt;

&lt;p&gt;I started this to help with my own community work. I’m sharing it so other developers and support teams can try it in theirs.&lt;/p&gt;

&lt;p&gt;The code and setup instructions are on &lt;a href="https://github.com/answerLoops/answerLoops" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. You can explore how retrieval, the review queue, and the integrations work, or run answerLoops yourself. The &lt;a href="https://answerloops.com/docs/product/knowledge-base" rel="noopener noreferrer"&gt;knowledge-base documentation&lt;/a&gt; walks through the workflows in this article.&lt;/p&gt;

&lt;p&gt;If it looks useful, give the repo a ⭐️. If you try it, tell me what worked and what got in your way.&lt;/p&gt;

&lt;p&gt;New to contributing to open source? Reach out—I’d be happy to help you find a place to start.&lt;/p&gt;

&lt;p&gt;Where does your team keep the useful answers that haven’t made it into the docs yet?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How Microsoft Agent Framework + AG-UI Enable Agentic UX &amp; Generative UI</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Thu, 20 Nov 2025 15:13:16 +0000</pubDate>
      <link>https://dev.to/copilotkit/how-microsoft-agent-framework-ag-ui-enable-agentic-ux-generative-ui-eci</link>
      <guid>https://dev.to/copilotkit/how-microsoft-agent-framework-ag-ui-enable-agentic-ux-generative-ui-eci</guid>
      <description>&lt;p&gt;&lt;strong&gt;Building with the Microsoft Agent Framework + AG-UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Microsoft’s Agent Framework (MAF) is an open-source agent framework that has recently emerged, offering exceptional ways to build agents and multi-step workflows in .NET or Python. Paired with AG-UI, the frontend/runtime layer that enables those agents to appear in your app with a clean UI, streaming responses, and shared state, etc., delivers a seamless agentic experience.&lt;/p&gt;

&lt;p&gt;The integration between the two is simple but powerful: MAF handles the reasoning and tool-use, and AG-UI bridges the interactions between the agent and the users.&lt;/p&gt;

&lt;p&gt;Microsoft Agent Framework (MAF) and AG-UI together offer a clean separation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MAF&lt;/strong&gt; handles the agent’s intelligence, workflows, memory, and tool use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AG-UI&lt;/strong&gt; is the open protocol that standardizes how agents communicate with user interfaces.&lt;/li&gt;
&lt;/ul&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%2Fo10wxzaekl8n2im2ah8i.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%2Fo10wxzaekl8n2im2ah8i.png" alt="Diagram1" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once an agent speaks AG-UI, it becomes immediately compatible with any AG-UI-aware frontend, including Microsoft’s own Blazor client and CopilotKit.&lt;/p&gt;

&lt;p&gt;This combination is what turns MAF agents from “backend processes” into interactive, stateful, user-facing agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Microsoft Agent Framework Provides
&lt;/h2&gt;

&lt;p&gt;MAF provides the core building blocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents&lt;/strong&gt; that call models, use tools, and keep state across turns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflows&lt;/strong&gt; for multi-step or multi-agent processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model and memory providers&lt;/strong&gt; so your agents can store data or thread context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/agent-framework" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out MAF GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;It’s practical if you want to move past “chat completion” and give the model structure, state, and the ability to act.&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%2Foos7xuzdrb08sl267wb9.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%2Foos7xuzdrb08sl267wb9.png" alt="graph" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What AG-UI Adds to the Picture
&lt;/h2&gt;

&lt;p&gt;AG-UI is the open protocol that defines &lt;strong&gt;how an agent communicates with a user interface.&lt;/strong&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%2F4wx9jz5cnfqgi5w0lbzd.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%2F4wx9jz5cnfqgi5w0lbzd.png" alt="diagram" width="799" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It standardizes things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Streaming messages&lt;/li&gt;
&lt;li&gt;State updates&lt;/li&gt;
&lt;li&gt;Tool invocations&lt;/li&gt;
&lt;li&gt;UI events&lt;/li&gt;
&lt;li&gt;Multi-agent routing&lt;/li&gt;
&lt;li&gt;Interruptions / tool-progress events&lt;/li&gt;
&lt;li&gt;Frontend → agent actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This removes the need to design your own transport, your own formatting, your own event system, or your own UI message schema.&lt;/p&gt;

&lt;p&gt;Instead of every framework inventing its own UI contract, AG-UI is the shared layer they converge on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/ag-ui-github" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out AG-UI's GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Microsoft Agent Framework + AG-UI
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/OuIxE6mVtpM"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. MAF agents become UI-ready out of the box&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No additional custom wiring.&lt;/li&gt;
&lt;li&gt;No custom WebSockets.&lt;/li&gt;
&lt;li&gt;No bespoke JSON formats.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent &lt;em&gt;speaks&lt;/em&gt; AG-UI, which removes any additional complexities.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Multi-step workflows can surface naturally in UI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Because AG-UI supports state sync and streaming, a MAF workflow can show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;intermediate states&lt;/li&gt;
&lt;li&gt;partial outputs&lt;/li&gt;
&lt;li&gt;tool progress&lt;/li&gt;
&lt;li&gt;agent-to-agent handoffs&lt;/li&gt;
&lt;li&gt;moments where the agent needs user input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is critical for user trust and usability.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Typed state becomes visible to the user&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;MAF agents often maintain a structured state (objects, lists, workflow context).&lt;/p&gt;

&lt;p&gt;AG-UI transports this state to the frontend, where it can drive live UI components.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Use of tools&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;AG-UI can show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a tool was invoked&lt;/li&gt;
&lt;li&gt;What parameters were used&lt;/li&gt;
&lt;li&gt;What the tool returned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a major improvement over hidden function-calling flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Use any AG-UI-compatible frontend&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once your MAF agent speaks AG-UI, you can plug it into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CopilotKit&lt;/li&gt;
&lt;li&gt;Microsoft Blazor&lt;/li&gt;
&lt;li&gt;Terminal Client&lt;/li&gt;
&lt;li&gt;Kotlin SDK (mobile, JVM)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives the agent a &lt;strong&gt;portable, future-proof interface layer&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters for Developers
&lt;/h2&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%2F8llatha9t6yirb2w6jjc.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%2F8llatha9t6yirb2w6jjc.png" alt="Blog cover" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A complete agent loop&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Agent → protocol → frontend → user → agent&lt;/p&gt;

&lt;p&gt;No custom engineering required.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A more interpretable agent&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With streaming, intermediate states, and exposed tool use, you can debug and trust the agent in a way plain chat completions don’t allow.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;This allows a path to build real applications&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SaaS copilots&lt;/li&gt;
&lt;li&gt;Co-creation copilots&lt;/li&gt;
&lt;li&gt;automation agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All while retaining clear structure and maintainability.&lt;/p&gt;

&lt;p&gt;Additionally, the developer doesn't need to reinvent the wheel.&lt;/p&gt;

&lt;p&gt;--&amp;gt; MAF handles reasoning + tools.&lt;/p&gt;

&lt;p&gt;--&amp;gt; AG-UI handles communication + events.&lt;/p&gt;

&lt;p&gt;--&amp;gt; The user is now able to collaborate with the agent in real time.&lt;/p&gt;

&lt;p&gt;The stack is clean.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Microsoft Agent Framework gives you an agent with: tools, workflows, state, orchestration, and model thinking.&lt;/p&gt;

&lt;p&gt;AG-UI gives that agent a standardized way to interact with the user, whether on mobile or desktop.&lt;/p&gt;

&lt;p&gt;Together, they let you build agents that aren’t constrained to the backend, but usable, visible, and connected to real applications.&lt;/p&gt;

&lt;p&gt;To stay up to date, please follow CopilotKit on&amp;nbsp;&lt;a href="https://go.copilotkit.ai/socials-twitter" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&amp;nbsp;and join the&amp;nbsp;&lt;a href="https://go.copilotkit.ai/discord-community" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;&amp;nbsp;community.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Vibe Code an Agentic App in Under 7 Minutes</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Tue, 26 Aug 2025 11:13:18 +0000</pubDate>
      <link>https://dev.to/copilotkit/vibe-code-an-agentic-app-in-under-7-minutes-1dce</link>
      <guid>https://dev.to/copilotkit/vibe-code-an-agentic-app-in-under-7-minutes-1dce</guid>
      <description>&lt;p&gt;Building agentic applications is powerful-but the complexity level starts to rise.&lt;/p&gt;

&lt;p&gt;Things like managing context, wiring actions, and giving agents reliable access to documentation can eat up time before you even get to shipping features.&lt;/p&gt;

&lt;p&gt;Not to worry, that's where the new Vibe-Coding Server comes in.&lt;/p&gt;

&lt;p&gt;What is the &lt;a href="https://docs.copilotkit.ai/mcp" rel="noopener noreferrer"&gt;Vibe-Coding Server&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;The Vibe-Coding Server, built on MCP (Model Context Protocol), gives coding agents structured access to both &lt;a href="https://github.com/CopilotKit/CopilotKit" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt; documentation and actual code examples from the repos.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/E-8kQzlxyY0"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Instead of dumping entire pages or manually tagging docs every time, the server automatically fetches only the relevant snippets. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Faster responses, more efficient development&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lower token usage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better context for your agents&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the Vibe-Coding Server in place, you can layer in agentic features&lt;/p&gt;

&lt;p&gt;Together, they move your agent from being &lt;strong&gt;conversational → operational&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;See it in action here and for better video quality, on YouTube:   &lt;iframe src="https://www.youtube.com/embed/lD9fKMKS1bo"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I recorded a walkthrough of the Vibe-Coding Server in action- including generated code examples, actions, readables, and the drop-in chat component, so you can see how everything fits together.&lt;/p&gt;

&lt;p&gt;Would love to hear what you're connecting MCP to!&lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool, join our &lt;a href="https://go.copilotkit.ai/AG-UI-Discord" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Two New Ways to Build with AG-UI: LlamaIndex and Agno</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Thu, 19 Jun 2025 14:07:18 +0000</pubDate>
      <link>https://dev.to/copilotkit/two-new-ways-to-build-with-ag-ui-llamaindex-and-agno-226d</link>
      <guid>https://dev.to/copilotkit/two-new-ways-to-build-with-ag-ui-llamaindex-and-agno-226d</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;It’s been a huge month for &lt;strong&gt;AG-UI&lt;/strong&gt;, the open protocol for interactive AI agents. Today, we’re expanding support with &lt;strong&gt;two new frameworks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LlamaIndex&lt;/strong&gt; — enabling retrieval-augmented agents to connect with users in real-time
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agno&lt;/strong&gt; — bringing intuitive multi-agent workflows into the AG-UI ecosystem
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers now have even more power to build rich, interactive agent experiences.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 AG-UI Hits a Major Milestone
&lt;/h2&gt;

&lt;p&gt;One month after launch, &lt;strong&gt;AG-UI&lt;/strong&gt; continues to grow and evolve. Today’s update brings two new integrations that expand what's possible with agentic interfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agno&lt;/strong&gt;: A modular agent orchestration framework now compatible with AG-UI, so you can expose your Agno agents to users through real-time interfaces.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LlamaIndex&lt;/strong&gt;: Build production agents that can find information, synthesize insights, generate reports, and take actions over the most complex enterprise data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These additions make it easier than ever to build &lt;strong&gt;high-quality user-facing AI&lt;/strong&gt; with your favorite agent frameworks.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is AG-UI?
&lt;/h2&gt;

&lt;p&gt;AG-UI (Agent-User Interaction Protocol) is a lightweight spec that connects backend AI agents with frontend applications. It turns agents into live, interactive participants inside your UI, not just silent executors behind an API.&lt;/p&gt;

&lt;p&gt;It’s the difference between a black box backend and a fully visible, controllable copilot.&lt;/p&gt;

&lt;p&gt;Think: &lt;strong&gt;Cursor&lt;/strong&gt; vs. &lt;strong&gt;Devin&lt;/strong&gt;.&lt;/p&gt;




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

&lt;p&gt;Today’s agents are often disconnected from the user. If you want real-time interaction, you’re left wiring up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Streaming outputs
&lt;/li&gt;
&lt;li&gt;Tool invocation feedback
&lt;/li&gt;
&lt;li&gt;Shared session state
&lt;/li&gt;
&lt;li&gt;UI rendering logic
&lt;/li&gt;
&lt;li&gt;Messaging pipelines
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AG-UI solves this by giving agents and apps a &lt;strong&gt;shared event protocol&lt;/strong&gt;, so they can speak the same language out of the box.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;AG-UI defines 16+ event types that power live agent behavior, from tool calls to token streaming to UI state updates.&lt;/p&gt;

&lt;p&gt;Agents can either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emit AG-UI events directly
&lt;/li&gt;
&lt;li&gt;Or use an adapter to convert outputs into AG-UI format
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clients subscribe to an event stream (via SSE or WebSockets), render the events live, and send back user input or control signals.&lt;/p&gt;

&lt;p&gt;This unlocks dynamic, real-time interaction between agents and users.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adoption &amp;amp; Growth
&lt;/h2&gt;

&lt;p&gt;In less than 30 days, AG-UI has gained serious traction:&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%2Fia9ilm5ka8rvo2gu4n16.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%2Fia9ilm5ka8rvo2gu4n16.png" alt="Twitter Image" width="800" height="1037"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrated with: &lt;strong&gt;LangChain, CrewAI, Mastra, AG2, Agno, LlamaIndex&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In progress: &lt;strong&gt;AWS, A2A, ADK, AgentOps, Human Layer (Slack)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3,700+ GitHub stars&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Thousands of developers are building interactive agents
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Build with AG-UI
&lt;/h2&gt;

&lt;p&gt;Getting started is fast:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-ag-ui-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me know what you are building! &lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and join our active &lt;a href="https://go.copilotkit.ai/discord-community" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; Community!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>Introducing AG-UI: The Protocol Where Agents Meet Users</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Tue, 13 May 2025 14:44:13 +0000</pubDate>
      <link>https://dev.to/copilotkit/introducing-ag-ui-the-protocol-where-agents-meet-users-10gp</link>
      <guid>https://dev.to/copilotkit/introducing-ag-ui-the-protocol-where-agents-meet-users-10gp</guid>
      <description>&lt;p&gt;I'm thrilled to announce &lt;a href="https://go.copilotkit.ai/ag-ui-github" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt;, the Agent-User Interaction Protocol, a streamlined bridge connecting AI agents to real-world applications.&lt;/p&gt;

&lt;p&gt;This brand new protocol is brought to you by &lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&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%2F1zogy4uze78qaa6w1cs1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zogy4uze78qaa6w1cs1.gif" alt="ag-ui1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/ag-ui-github" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out AG-UI's GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AG-UI?
&lt;/h2&gt;

&lt;p&gt;AG-UI is an open, lightweight protocol that streams a &lt;strong&gt;single sequence of JSON events&lt;/strong&gt; over standard HTTP or an optional binary channel. These events—messages, tool calls, state patches, lifecycle signals—flow seamlessly between your agent backend and front-end interface, maintaining perfect real-time synchronization.&lt;/p&gt;

&lt;p&gt;Get started in minutes using our TypeScript or Python SDK with any agent backend (OpenAI, Ollama, LangGraph, or custom code). Visit &lt;a href="https://docs.ag-ui.com/introduction" rel="noopener noreferrer"&gt;docs.ag-ui.com&lt;/a&gt; for the specification, quick-start guide, and interactive playground.&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%2Fh0sqewk0rueyeqskj2ii.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%2Fh0sqewk0rueyeqskj2ii.png" alt="ag-ui2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent-User Interaction
&lt;/h2&gt;

&lt;p&gt;Today’s AI Agent ecosystem is maturing. Agents are going from interesting viral demos to actual production use, including by some of the biggest enterprises in the world.&lt;/p&gt;

&lt;p&gt;However, the ecosystem has largely focused on backend automation, processes that run independently with limited user interaction. Workflows that are set off, or happen automatically, whose output is then used.&lt;/p&gt;

&lt;p&gt;Common use-cases include data migration, research and summarization, form-filling, etc.&lt;/p&gt;

&lt;p&gt;Repeatable and simple workflows, where accuracy can be ensured, or where 80% accuracy is good enough.&lt;/p&gt;

&lt;p&gt;These have already been big productivity boosters. Automating time-consuming and tedious tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Agents Meet Users
&lt;/h2&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%2Fryzc3q0hjkpbn8nvxn7w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryzc3q0hjkpbn8nvxn7w.gif" alt="ag-ui3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Coding tools (Devin vs. Cursor)&lt;/p&gt;

&lt;p&gt;Throughout the adoption of generative AI, coding tools have been canneries in the coal mine, and Cursor is the best example of a user-interactive agent. An AI agent that works alongside users, in a shared workspace.&lt;/p&gt;

&lt;p&gt;This contrasts with Devin, which was the promise of a fully autonomous agent that automates high-level work.&lt;/p&gt;

&lt;p&gt;For many of the most important use-cases, Agents are helpful if they can work alongside users. This means users can see what the agent is doing, can co-work on the same output, and easily iterate together in a shared workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenges of Building a User-Interactive Agent
&lt;/h2&gt;

&lt;p&gt;Creating these collaborative experiences presents significant technical challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-time streaming:&lt;/strong&gt; LLMs produce tokens incrementally; UIs need them instantly without blocking on the full response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tool orchestration:&lt;/strong&gt; Modern agents call functions, run code, hit APIs. The UI must show progress and results, sometimes ask for human approval, and then resume the run—all without losing context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared mutable state:&lt;/strong&gt; Agents often generate plans, tables, or code folders that evolve step-by-step. Shipping entire blobs each time wastes bandwidth; sending diffs demands a clear schema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrency &amp;amp; cancellation:&lt;/strong&gt; A user might fire off multiple queries, stop one mid-flight, or switch threads. The backend and front-end need thread IDs, run IDs, and an orderly shutdown path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security boundaries:&lt;/strong&gt; Streaming arbitrary data over WebSockets is easy until you need CORS, auth tokens, and audit logs that an enterprise will sign off on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Framework sprawl:&lt;/strong&gt; LangChain, CrewAI, Mastra, AG2, home-grown scripts—all speak slightly different dialects. Without a standard, every UI must reinvent adapters and edge-case handling.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The AG-UI Solution
&lt;/h2&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%2F6e52ptzk1bbgqyzr67zz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6e52ptzk1bbgqyzr67zz.gif" alt="Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AG-UI addresses these challenges through a simple yet powerful approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your client makes a single POST to the agent endpoint, then listens to a &lt;strong&gt;unified event stream&lt;/strong&gt;. Each event has a type(e.g., &lt;strong&gt;TEXT_MESSAGE_CONTENT&lt;/strong&gt;, &lt;strong&gt;TOOL_CALL_START&lt;/strong&gt;, &lt;strong&gt;STATE_DELTA&lt;/strong&gt;), and minimal payload. Agents emit events as they occur, and UIs respond appropriately—displaying partial text, rendering visualizations when tools complete, or updating interfaces when state changes.&lt;/p&gt;

&lt;p&gt;Built on standard HTTP, AG-UI integrates smoothly with existing infrastructure while offering an optional binary serializer for performance-critical applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Enables
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/ag-ui-announcement" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h6hrm69pp41y8xlv695.png" alt="Tweet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/ag-ui-announcement" rel="noopener noreferrer"&gt;Please like and follow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AG-UI establishes a &lt;strong&gt;consistent contract&lt;/strong&gt; between agents and interfaces, eliminating custom WebSocket formats and text parsing hacks. With this unified protocol:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Components become interchangeable:&lt;/strong&gt; Use CopilotKit's React components with any AG-UI source&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backend flexibility:&lt;/strong&gt; Switch between cloud and local models without UI changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-agent coordination:&lt;/strong&gt; Orchestrate specialized agents through a single interface&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced development:&lt;/strong&gt; Build faster with richer experiences and zero vendor lock-in&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AG-UI&lt;/strong&gt; isn't just a technical specification—it's the foundation for the next generation of AI-enhanced applications where humans and agents seamlessly collaborate.&lt;/p&gt;

&lt;p&gt;Please check out the &lt;a href="https://go.copilotkit.ai/ag-ui-getting-started" rel="noopener noreferrer"&gt;Getting Started &lt;/a&gt;docs, and I look forward to you trying it out.&lt;/p&gt;

&lt;p&gt;Interested in connecting with other AI developers? &lt;br&gt;
Join the AG-UI Discord and join the AI developer community: &lt;a href="https://go.copilotkit.ai/AG-UI-Discord" rel="noopener noreferrer"&gt;https://go.copilotkit.ai/AG-UI-Discord&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://go.copilotkit.ai/socials-twitter" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Turn Your React App Into an MCP Client in Minutes</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Tue, 06 May 2025 15:45:43 +0000</pubDate>
      <link>https://dev.to/copilotkit/turn-your-react-app-into-an-mcp-client-in-minutes-269n</link>
      <guid>https://dev.to/copilotkit/turn-your-react-app-into-an-mcp-client-in-minutes-269n</guid>
      <description>&lt;p&gt;I'm on the CopilotKit team, and I'm excited to announce we've just added built-in support for MCP. The update went live today.&lt;/p&gt;

&lt;p&gt;For those unfamiliar, CopilotKit is a self-hostable, full-stack framework for building user interactive agents and copilots.. Our focus is on allowing your agents to take control of your application (by human approval), communicate what it's doing, and generate a completely custom UI for the user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/copilotkit" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out CopilotKit's GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s an MCP Client?
&lt;/h2&gt;

&lt;p&gt;It’s a web-based, client (React in this case) that lets you chat with any MCP server in your own app. All you need is a URL from Composio to get started.&lt;/p&gt;

&lt;p&gt;MCP lets you connect LLMs to external tools in a standardized way. Now you can use a chat interface to talk to any MCP-compatible server, right from your React app, with no agent framework required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quickstart:
&lt;/h3&gt;

&lt;p&gt;With one command, you can start talking to MCP servers locally, from your own Next.js app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; copilotkit@latest init &lt;span class="nt"&gt;-m&lt;/span&gt; MCP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What we built:
&lt;/h3&gt;

&lt;p&gt;To show it off, I connected a simple self-hosted ToDo app to two platforms using MCP:&lt;/p&gt;

&lt;p&gt;Asana – Send blog ideas as tasks, assign them to myself, and set due dates.&lt;/p&gt;

&lt;p&gt;Typefully – Pull blog titles and save them as draft tweets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; CopilotKit&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP servers:&lt;/strong&gt; Composio&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Framework:&lt;/strong&gt; Next.js&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic framework:&lt;/strong&gt; None&lt;/p&gt;

&lt;p&gt;The code is open source, and contributions are welcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/CopilotKit/copilotkit-mcp-demo" rel="noopener noreferrer"&gt;https://github.com/CopilotKit/copilotkit-mcp-demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.copilotkit.ai/guides/model-context-protocol" rel="noopener noreferrer"&gt;https://docs.copilotkit.ai/guides/model-context-protocol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video demo:&lt;/strong&gt; &lt;a href="https://x.com/CopilotKit/status/1917976289547522074" rel="noopener noreferrer"&gt;https://x.com/CopilotKit/status/1917976289547522074&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Twitter Announcement:&lt;/strong&gt; &lt;a href="https://x.com/CopilotKit/status/1917976289547522074" rel="noopener noreferrer"&gt;https://x.com/CopilotKit/status/1917976289547522074&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear what you're connecting MCP to!&lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool, join our &lt;a href="https://go.copilotkit.ai/AG-UI-Discord" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How To Use an MCP React Client with Multiple AI Agents</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Tue, 22 Apr 2025 15:13:34 +0000</pubDate>
      <link>https://dev.to/copilotkit/how-to-use-an-mcp-client-with-multiple-ai-agents-47d8</link>
      <guid>https://dev.to/copilotkit/how-to-use-an-mcp-client-with-multiple-ai-agents-47d8</guid>
      <description>&lt;p&gt;Hey everyone👋&lt;/p&gt;

&lt;p&gt;I run the community at &lt;a href="https://go.copilotkit.ai/copilotkit" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt;, a free and open-source framework for building intelligent companions and in-app infrastructure.🤔&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think about it this way:&lt;/strong&gt;🧐 &lt;/p&gt;

&lt;p&gt;CopilotKit allows your agents to control your application, communicate what its doing, and generate completely custom UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/copilotkit" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out CopilotKit's GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

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

&lt;p&gt;I recorded &lt;a href="https://www.youtube.com/watch?v=GRo432ZFIyU" rel="noopener noreferrer"&gt;this quick demo&lt;/a&gt; to show just one example of what you can build with the (&lt;a href="https://github.com/CopilotKit/open-multi-agent-canvas" rel="noopener noreferrer"&gt;Open Multi-Agent Canvas with MCP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It looks like a sandbox, but it's so much more. With MCP, agents can work together and take real actions, like sending messages to Slack, triggering APIs, or updating your app—all in one interface. Before, doing this kind of multi-agent coordination was messy. Now it’s much simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool, join our &lt;a href="https://go.copilotkit.ai/discord-community" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Build Full-Stack AI Agents with Custom React Components (CopilotKit + CrewAI)</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Fri, 28 Mar 2025 14:35:02 +0000</pubDate>
      <link>https://dev.to/copilotkit/build-full-stack-ai-agents-with-custom-react-components-4n1o</link>
      <guid>https://dev.to/copilotkit/build-full-stack-ai-agents-with-custom-react-components-4n1o</guid>
      <description>&lt;p&gt;Hey everyone👋&lt;/p&gt;

&lt;p&gt;I manage the community at CopilotKit, a free and open-source framework for building intelligent companions and, in-app infrastructure.🤔&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think about it like this:&lt;/strong&gt;🧐 CopilotKit allows your agents to take control of your application, communicate what its doing, and generate completely custom UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/copilotkit" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out CopilotKit's GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Full-Stack Agents
&lt;/h2&gt;

&lt;p&gt;Atai, the Co-Founder and CEO of CopilotKit produced this video to showcase how simple it is to build agents using CrewAI and bring them into your app in easy-to-understand steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Apps
&lt;/h2&gt;

&lt;p&gt;A new wave of Agent-Native apps has emerged - such as Replit's AI Agent, Vercel's new v0, and ChatGPT's Canvas. &lt;/p&gt;

&lt;p&gt;These apps deeply integrate an AI agent into a native application, allowing for deep human/AI collaboration and human-in-the-loop flows.&lt;/p&gt;

&lt;p&gt;In this video, we will show you how to add an agent to your app in just a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool, join our &lt;a href="https://go.copilotkit.ai/discord-community" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timestamps if you want to jump around:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;00:00&lt;/strong&gt; CoAgents intro with CrewAI&lt;br&gt;
&lt;strong&gt;00:22&lt;/strong&gt; Use the new CLI tool to add Crews to your React app&lt;br&gt;
&lt;strong&gt;02:09&lt;/strong&gt; Created App with Shared agent state&lt;br&gt;
&lt;strong&gt;03:50&lt;/strong&gt; React component to render the agent streaming&lt;br&gt;
&lt;strong&gt;06:04&lt;/strong&gt; Agentic Generative UI&lt;br&gt;
&lt;strong&gt;06:25&lt;/strong&gt; The CrewAI feature viewer demo&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Build a Full Stack Agentic Researcher in 5 Minutes ⚡️⚡️</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Wed, 26 Feb 2025 18:59:07 +0000</pubDate>
      <link>https://dev.to/copilotkit/how-to-build-a-full-stack-agentic-researcher-in-5-minutes-19dp</link>
      <guid>https://dev.to/copilotkit/how-to-build-a-full-stack-agentic-researcher-in-5-minutes-19dp</guid>
      <description>&lt;p&gt;Hey everyone👋 &lt;/p&gt;

&lt;p&gt;I'm a DevRel and manage our community at &lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt;, a free and open-source framework for building intelligent companions and, in-app infrastructure.🤔&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think about it like this:&lt;/strong&gt;🧐 you can embed a chat interface similar to ChatGPT that doesn't just respond but actively takes actions within your app's frontend functions (Client Side) based on LLM outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Apps
&lt;/h2&gt;

&lt;p&gt;A new wave of Agent-Native apps has emerged - such as Replit's AI Agent, Vercel's new v0, and ChatGPT's Canvas. &lt;/p&gt;

&lt;p&gt;These apps deeply integrate an AI agent into a native application, allowing for deep human/AI collaboration and human-in-the-loop flows.&lt;/p&gt;

&lt;p&gt;In this video, we will show you how to add an agent to your app in just a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool, join our &lt;a href="https://go.copilotkit.ai/discord-community" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timestamps if you want to jump around:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;00:00&lt;/strong&gt; CoAgents intro&lt;br&gt;
&lt;strong&gt;01:51&lt;/strong&gt; Add agent chat to the app&lt;br&gt;
&lt;strong&gt;03:35&lt;/strong&gt; Share State between the Agent&amp;lt;&amp;gt;App&lt;br&gt;
&lt;strong&gt;05:20&lt;/strong&gt; Stream agent state&lt;br&gt;
&lt;strong&gt;07:04&lt;/strong&gt; Agentic GenUI&lt;br&gt;
&lt;strong&gt;08:25&lt;/strong&gt; Human-in-the-Loop&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Bringing a DeepSeek R1 LangGraph Agent Into The Real World Using CopilotKit</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Wed, 05 Feb 2025 21:52:00 +0000</pubDate>
      <link>https://dev.to/copilotkit/bringing-a-deepseek-r1-langgraph-agent-into-the-real-world-using-copilotkit-3oia</link>
      <guid>https://dev.to/copilotkit/bringing-a-deepseek-r1-langgraph-agent-into-the-real-world-using-copilotkit-3oia</guid>
      <description>&lt;p&gt;Hey everyone! &lt;/p&gt;

&lt;p&gt;I'm a DevRel at &lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt;, an open-source framework for agentic UI and in-app agents. &lt;/p&gt;

&lt;p&gt;I wanted to share a video we produced to show how easy it is to give your app AI superpowers in just minutes.&lt;/p&gt;

&lt;p&gt;The DeepSeek R1 LangGraph agent demo is powered by one simple hook, the &lt;code&gt;useCoAgent&lt;/code&gt; hook (&lt;a href="https://docs.copilotkit.ai/reference/" rel="noopener noreferrer"&gt;https://docs.copilotkit.ai/reference/&lt;/a&gt;....&lt;br&gt;
Then, viola, you are cooking with gas so to speak! &lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://git.new/copilotkit-github" rel="noopener noreferrer"&gt;CopilotKit GitHub Repo&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://go.copilotkit.ai/deep-researcher" rel="noopener noreferrer"&gt;Ollama Deep Researcher source code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow CopilotKit on &lt;a href="https://x.com/CopilotKit" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and say hi, and if you'd like to build something cool, join our &lt;a href="https://go.copilotkit.ai/discord-community" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Build Your Own RAG Copilot with Anthropic, Pinecone, &amp; CopilotKit</title>
      <dc:creator>Nathan Tarbert</dc:creator>
      <pubDate>Wed, 29 Jan 2025 15:09:59 +0000</pubDate>
      <link>https://dev.to/copilotkit/build-a-rag-copilot-on-your-own-knowledge-base-with-copilotkit-pinecone-anthropic-21m9</link>
      <guid>https://dev.to/copilotkit/build-a-rag-copilot-on-your-own-knowledge-base-with-copilotkit-pinecone-anthropic-21m9</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we’ll walk you through building an AI-powered RAG Copilot step by step for your product Knowledge Base using the &lt;a href="https://www.anthropic.com/api" rel="noopener noreferrer"&gt;Anthropic AI API&lt;/a&gt;, &lt;a href="https://www.pinecone.io/" rel="noopener noreferrer"&gt;Pinecone API&lt;/a&gt;, and &lt;a href="https://go.copilotkit.ai/copilotkit" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt;🪁.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Building a simple product knowledge base using Next.js&lt;/li&gt;
&lt;li&gt;Adding CopilotKit UI components to your app client along with CopilotKit’s API endpoint.&lt;/li&gt;
&lt;li&gt;Integrating Pinecone API to create searchable indexes for your knowledge base articles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a fully functioning RAG Knowledge Base application using CopilotKit:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/3T_ekLVGGFI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is CopilotKit&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://go.copilotkit.ai/copilotkit" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt;&amp;nbsp;is the leading open-source framework for integrating production-ready AI-powered copilots into your applications.  It provides a &lt;a href="https://docs.copilotkit.ai/reference/sdk/js/LangGraph" rel="noopener noreferrer"&gt;feature-rich SDK&lt;/a&gt; that supports various AI copilot use cases, including &lt;a href="https://docs.copilotkit.ai/reference/hooks/useCopilotReadable" rel="noopener noreferrer"&gt;context awareness&lt;/a&gt;, &lt;a href="https://docs.copilotkit.ai/reference/hooks/useCopilotAction" rel="noopener noreferrer"&gt;copilot actions&lt;/a&gt;, and &lt;a href="https://docs.copilotkit.ai/guides/generative-ui" rel="noopener noreferrer"&gt;generative UIs&lt;/a&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%2Fqmfp439ghzdckf3u2e9e.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%2Fqmfp439ghzdckf3u2e9e.png" alt="copilotkit homepage" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means you can focus on defining your copilot's role, rather than getting bogged down in the technicalities of building one from scratch or dealing with complex integrations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CopilotKit/CopilotKit" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out  CopilotKit's GitHub ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we get started, here are a few things you’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with building web apps using&amp;nbsp;&lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React.js&lt;/a&gt;. A quick note—you’ll also need some knowledge of TypeScript, as we’ll be using it for this project.&lt;/li&gt;
&lt;li&gt;Ensure Node.js &amp;gt;20 is installed on your system. If not, you can download and install it from the&amp;nbsp;&lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;official Node.js website&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you’ve covered these, we’ll set up the development environment we’ll be working in.&lt;/p&gt;

&lt;p&gt;Here’s a quick preview of what we’ll be building:&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%2F4o5nhdmcu1ppjh71dbi3.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%2F4o5nhdmcu1ppjh71dbi3.png" alt="app preview" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up the Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To get started, run these commands to create a new directory for the project, and scaffold the Next.js application boilerplate source files and folders:&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;product-knowledge-base &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;product-knowledge-base
npx create-next-app product-knowledge-base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the setup prompts. You can select as shown below (adjust based on your project requirements).&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%2Fipgud8z65u3ytiv28058.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%2Fipgud8z65u3ytiv28058.png" alt="project setup" width="798" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the project is created, navigate to the project directory, and verify everything works by running the development server:&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;cd &lt;/span&gt;product-knowledge-base
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, your app should be running locally at &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, let’s install the necessary dependencies for this project. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mantine UI.&lt;/li&gt;
&lt;li&gt;CopilotKit Packages.&lt;/li&gt;
&lt;li&gt;Pinecone SDK.&lt;/li&gt;
&lt;li&gt;Anthropic AI SDK.&lt;/li&gt;
&lt;li&gt;Axios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the following command to install them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @anthropic-ai/sdk @mantine/core @mantine/hooks @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime lucide-react axios @pinecone-database/pinecone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s set up the file structure for the project. Here is an overview of the main files and directories we’ll create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/app/ui/service/index.ts&lt;/code&gt;: To handle API calls to the backend to fetch dummy posts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/app/ui/components/KnowledgeBase.tsx&lt;/code&gt;: The main UI component for the knowledge base.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/app/lib/types/post.ts&lt;/code&gt;:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/app/lib/data/data.ts&lt;/code&gt;:  dummy post data for the knowledge base.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/app/api/copilotkit/route.ts&lt;/code&gt;: CopilotKit API endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/app/api/posts/route.ts&lt;/code&gt;: dummy posts API endpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how your project structure will look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;product-knowledge-base/
├── src/
│   ├── app/
│   │   ├── ui/
│   │   │   ├── service/
│   │   │   │   └── index.ts
│   │   │   ├── components/
│   │   │   │   └── KnowledgeBase.tsx
│   │   ├── lib/
│   │   │   ├── types/
│   │   │   │   └── post.ts
│   │   │   ├── data/
│   │   │   │   └── data.ts
│   │   ├── api/
│   │   │   ├── copilotkit/
│   │   │   │   └── route.ts
│   │   │   ├── posts/
│   │   │   │   └── route.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;With this setup, you now have a working development environment for this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Building the Knowledge Base Frontend&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First, import the CopilotKit and Mantine UI providers, then wrap your entire app with them so they're available globally. Here's how you can update your &lt;code&gt;layout.tsx&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MantineProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mantine/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mantine/core/styles.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/react-ui/styles.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CopilotKit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/react-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CopilotKit&lt;/span&gt; &lt;span class="na"&gt;runtimeUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/api/copilotkit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MantineProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MantineProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CopilotKit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;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;When wrapping the app with these providers, remember to pass the&amp;nbsp;&lt;code&gt;runtimeUrl="&amp;lt;endpoint-url&amp;gt;"&lt;/code&gt;&amp;nbsp;prop to the CopilotKit provider. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Designing the Knowledge Base Component&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll go over the code you need to build the&amp;nbsp;knowledge base&amp;nbsp;component. Let's start by defining the&amp;nbsp;&lt;code&gt;Post&lt;/code&gt;&amp;nbsp;interface. Add the following code in your &lt;code&gt;src/app/lib/types/post.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, navigate to the&amp;nbsp;&lt;code&gt;src/app/ui/service/index.ts&lt;/code&gt;&amp;nbsp;file, and add the following code to handle API requests to fetch posts from the app’s backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/app/lib/types/post&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;API_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_API_BASE_URL&lt;/span&gt; 

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;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;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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api/posts`&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;data&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 create a&amp;nbsp;&lt;code&gt;.env&lt;/code&gt;&amp;nbsp;file in the root directory of your project, and add the following base URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT_PUBLIC_API_BASE_URL='http://localhost:3000'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s create the Knowledge Base UI component. Inside&amp;nbsp;the &lt;code&gt;src/app/ui/components/KnowledgeBase.tsx&lt;/code&gt;, start by adding the following imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Modal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mantine/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BookOpen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lucide-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/lib/types/post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/ui/service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, define the&amp;nbsp;&lt;code&gt;KnowledgeBase&lt;/code&gt;&amp;nbsp;functional component and initialize the following states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;KnowledgeBase&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;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPosts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;selectedPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSelectedPost&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;loading&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt; &lt;span class="na"&gt;py&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xl"&lt;/span&gt; &lt;span class="na"&gt;ml&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xl"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xl"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt; &lt;span class="na"&gt;justify&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt; &lt;span class="na"&gt;align&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookOpen&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;CopilotKit Product Knowledge Base&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Now, let’s define a function to fetch the list of posts from the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&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;loadPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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;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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;setPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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 loading posts:&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="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="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;loadPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To display the posts fetched from the app’s backend, add the following code. We will render the list of posts in a grid layout with cards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Display posts */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&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;post&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Col&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;span&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Card&lt;/span&gt;
        &lt;span class="na"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sm"&lt;/span&gt;
        &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
        &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
        &lt;span class="na"&gt;withBorder&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSelectedPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pointer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Badge&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sm"&lt;/span&gt; &lt;span class="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dimmed"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xs"&lt;/span&gt; &lt;span class="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dimmed"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Posted on: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Col&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To show the content of a single post, in this case, we’ll keep things straightforward by displaying dummy content in a modal component when an article card is clicked. To do that, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Modal for displaying selected post */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedPost&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Modal&lt;/span&gt;
    &lt;span class="na"&gt;opened&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;selectedPost&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;onClose&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSelectedPost&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="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;centered&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xl"&lt;/span&gt;
  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedPost&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;split&lt;/span&gt;&lt;span class="p"&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="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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;item&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="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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Modal&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, define the following function to update the selected post state when users click on the post’s card.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePostClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Post&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="nf"&gt;setSelectedPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&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;Finally, to render this component in the browser, import it in your&amp;nbsp;&lt;code&gt;src/app/page.tsx&lt;/code&gt;&amp;nbsp;file with the following code (make sure to delete all the boilerplate Next.js code):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;KnowledgeBase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/ui/components/KnowledgeBase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;KnowledgeBase&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Adding CopilotKit UI Components&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The next step involves adding CopilotKit UI components into the knowledge base interface. CopilotKit’s React SDK provides neatly designed and easily customizable UI components. These include sidebars, pop-ups, text areas, and a headless UI component. For this example, we will use the&amp;nbsp;&lt;strong&gt;`CopilotSidebar&lt;/strong&gt;`&amp;nbsp;component to render an in-app chatbot interface.&lt;/p&gt;

&lt;p&gt;To add CopilotKit’s UI sidebar component, in your &lt;code&gt;src/app/ui/components/KnowledgeBase.tsx&lt;/code&gt;, add the following import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CopilotSidebar&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/react-ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once imported, add the component&amp;nbsp;in the JSX return statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt; &lt;span class="na"&gt;justify&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;flex&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="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;350px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CopilotSidebar&lt;/span&gt;
      &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Help the user get the right knowledge base articles for their query"&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome! Describe the query you need assistance with.&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="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;defaultOpen&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;clickOutsideToClose&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component accepts various props, including&amp;nbsp;&lt;code&gt;instructions&lt;/code&gt;,&amp;nbsp;&lt;code&gt;labels&lt;/code&gt;,&amp;nbsp;&lt;code&gt;defaultOpen&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;clickOutsideToClose&lt;/code&gt;. Importantly, the&amp;nbsp;&lt;code&gt;instructions&lt;/code&gt;&amp;nbsp;prop allows you to provide additional context to help the underlying Copilot AI LLM better understand and respond to user queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Using CopilotKit Hooks for AI Actions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The React CopilotKit  SDK also provides a set of useful hooks that enable you to define custom actions for your app’s AI Copilot. For this example, we will use the&amp;nbsp;&lt;code&gt;useCopilotAction&lt;/code&gt;&amp;nbsp;hook to define the intended action, that is, to retrieve knowledge base articles based on a user query.&lt;/p&gt;

&lt;p&gt;To do that, start by importing the&amp;nbsp;&lt;code&gt;useCopilotAction&lt;/code&gt;&amp;nbsp;hook in your&amp;nbsp;&lt;code&gt;KnowledgeBase&lt;/code&gt;&amp;nbsp;component file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCopilotAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/react-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After importing, you can initialize the hook, and specify the action you want the copilot to perform. In this case, we’ll define an action named “FetchKnowledgebaseArticles” to retrieve relevant articles based on the supplied user query. Let's write the code for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useCopilotAction&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;FetchKnowledgebaseArticles&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;Fetch relevant knowledge base articles based on a user query&lt;/span&gt;&lt;span class="dl"&gt;"&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="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;query&lt;/span&gt;&lt;span class="dl"&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;User query for the knowledge base&lt;/span&gt;&lt;span class="dl"&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="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="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Getting relevant answers to your query...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This action setup includes several important elements. The&amp;nbsp;&lt;code&gt;name&lt;/code&gt;&amp;nbsp;attribute provides a unique identifier for the action, while the&amp;nbsp;&lt;code&gt;description&lt;/code&gt;&amp;nbsp;explains its purpose and when it should be used. &lt;/p&gt;

&lt;p&gt;Additionally, the&amp;nbsp;&lt;code&gt;parameters&lt;/code&gt;&amp;nbsp;array defines the inputs required for the action, such as the user’s query in this case. And lastly, the&amp;nbsp;&lt;code&gt;render&lt;/code&gt;&amp;nbsp;property allows you to specify what will be displayed while the action is being executed. For this example, we’ll display a simple status message to keep the user informed about the ongoing process. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Integrating the App’s Backend&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To complete the entire app’s workflow, let’s build the backend by adding endpoints for fetching posts, integrating CopilotKit functionality, and the Pinecone API to create searchable indexes for the knowledge base articles.&lt;/p&gt;

&lt;p&gt;To do that, first, go to this &lt;a href="https://github.com/ItsWachira/Next-Anthropic-AI-Copilot-Product-Knowledge-base/blob/main/src/app/lib/data/data.ts" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; file containing the dummy posts data, copy, and paste it into your local &lt;code&gt;src/app/lib/data/data.ts&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Next, in the &lt;code&gt;src/app/api/posts/route.ts&lt;/code&gt; file, add the following code to set up the dummy posts API endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/app/lib/data/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&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;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&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;At this point, start your dev server and head over to your app’s localhost URL. You should see the list of posts displayed, along with the CopilotKit sidebar component.&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%2F21af3nvijyjhk88oe3pp.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%2F21af3nvijyjhk88oe3pp.png" alt="app demo" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going back to the main intent of the guide, which is, integrating an AI Copilot for product knowledge bases. Typically, most product knowledge bases are loaded with all sorts of content—blog articles, FAQs, internal SOPs, API documentation, and more. That’s a lot more than the three dummy posts we’re working with in this example.&lt;/p&gt;

&lt;p&gt;Normally, these knowledge bases have integrated Algolia Search API to let users quickly search through resources. Now for the AI copilot, we want to go beyond just “search-show”.Essentially, we want to take advantage of LLMs’ ability to understand natural language to implement “conversational-like” search functionality for knowledge bases’ resources.&lt;/p&gt;

&lt;p&gt;Instead of simply returning static search results, the Copilot will allow users to “chat” about the resources, ask follow-up questions, and get answers in a much more user-friendly way.  This is arguably more intuitive.   &lt;/p&gt;

&lt;p&gt;To make this happen, we need to create LLM-searchable indexes—essentially, data sources that the AI can query to fetch the right information. For this, we’ll use Pinecone's vector database API to create a searchable index for the dummy data.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating Searchable Indexes using Pinecone API SDK&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.pinecone.io/" rel="noopener noreferrer"&gt;Pinecone&lt;/a&gt; is a vector database service designed for fast, scalable, and accurate intelligent search capabilities in applications. It allows you to store and retrieve vector representations of data efficiently, making it ideal for tasks like semantic search and recommendation systems.&lt;/p&gt;

&lt;p&gt;What this means is that instead of relying solely on Anthropic AI LLM powering the Copilot to generate responses based on preexisting training knowledge, you can customize and contextualize the LLM so that your Copilot can address user queries and generate responses based on your app’s data. Ideally, this is why Pinecone becomes useful—it allows you to create vector databases for your data that are easily searchable with large language models.&lt;/p&gt;

&lt;p&gt;Essentially, in this example, we are simply integrating Pinecone to create indexes for our knowledge base data. This way,  the Copilot can first search through the data and generate more relevant, contextualized responses, along with accurately addressing follow-up questions based on the same knowledge base data.&lt;/p&gt;

&lt;p&gt;Here’s a quick overview of what we’ll do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up Pinecone.&lt;/li&gt;
&lt;li&gt;Generating knowledge base content embeddings for the sample articles.&lt;/li&gt;
&lt;li&gt;Indexing and querying the knowledge base data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the &lt;code&gt;src/app/api/copilotkit/route.ts&lt;/code&gt; file, let’s start by making the following imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pinecone&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@pinecone-database/pinecone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/lib/data/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, define your environment variables for the Pinecone and Anthropic API keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ANTHROPIC_API_KEY&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;NEXT_PUBLIC_ANTHROPIC_API_KEY&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;PINECONE_API_KEY&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;NEXT_PUBLIC_PINECONE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a good practice to add a check to ensure these keys are provided Don’t worry—we’ll cover the steps for getting the Anthropic API key later on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&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;ANTHROPIC_API_KEY&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;PINECONE_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="s1"&gt;Missing required API keys. &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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, initialize the Pinecone SDK, and set up the necessary configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pinecone&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;Pinecone&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;PINECONE_API_KEY&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;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multilingual-e5-large&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;indexName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knowledge-base-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create the Pinecone index. An index is essentially a structured storage(numerical representations of data), that allows you to efficiently search and retrieve data based on vector similarity. &lt;/p&gt;

&lt;p&gt;Ideally, for a production app, you would typically make API calls to retrieve your posts’ data dynamically. However, in this case, we will use the dummy data to simulate this process. &lt;/p&gt;

&lt;p&gt;To create a vector database for our knowledge base data, we need to initialize a Pinecone index for the data.&lt;/p&gt;

&lt;p&gt;Here’s the function to achieve this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Function to create the Pinecone index&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initializePinecone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;retryDelay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="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;indexList&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;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listIndexes&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;indexList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;index&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;indexName&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;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&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;indexName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;dimension&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="na"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cosine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;serverless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&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="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;await&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="mi"&gt;5000&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;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;indexName&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Retrying Pinecone initialization... (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;maxRetries&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;await&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="nx"&gt;retryDelay&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;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once it’s set up, you can use it to store and retrieve your knowledge base data.&lt;/p&gt;

&lt;p&gt;Next, we need to generate embeddings for your knowledge base. This step is crucial for enabling your application to efficiently store and search through large volumes of data using vector embeddings.&lt;/p&gt;

&lt;p&gt;Embedding your knowledge base content is simply converting the raw data—typically text—into vectors that represent the semantic meaning of that data. Pinecone then stores these vectors in the index.&lt;/p&gt;

&lt;p&gt;With the index in place, your application can perform operations like similarity search, allowing it to retrieve the most relevant data quickly based on the vector similarity between your queries and stored content.&lt;/p&gt;

&lt;p&gt;To do that, add the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initialize Pinecone and prepare the index&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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;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;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;initializePinecone&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;index&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;embeddings&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;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;posts&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;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;inputType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;END&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;posts&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;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;d&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="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
          &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;d&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="p"&gt;}));&lt;/span&gt;  
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knowledge-base-data-namespace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;records&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;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&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="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="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="s1"&gt;Error initializing Pinecone:&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;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="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few things we need to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embeddings: These are vector representations of content, such as text or articles, that capture the semantic meaning of the data. In this case, embeddings are generated using Pinecone’s model, &lt;strong&gt;multilingual-e5-large&lt;/strong&gt;, which processes the content and converts it into vectors. Note that you can also use other models, such as OpenAI, which provides an embedding API for this task.&lt;/li&gt;
&lt;li&gt;Namespace: A namespace in Pinecone is a logical partitioning of your index. It allows you to organize data within the index and perform operations within specific segments of your data. In this case, the namespace is set to ‘knowledge-base-data-namespace’, which groups the knowledge base content together.&lt;/li&gt;
&lt;li&gt;Records: These represent the data being inserted into Pinecone. Each record consists of an id, values (the embedding), and metadata (e.g., the text of the article). The values are what Pinecone uses to perform similarity searches, while the metadata provides additional context for each record.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, for setup this to work, you will need to get the Pinecone API key.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How to Get Your Pinecone API Key:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To get your Pinecone AI API Key, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the&amp;nbsp;&lt;a href="https://app.pinecone.io/" rel="noopener noreferrer"&gt;Pinecone Developer Console&lt;/a&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhdckyamj3o3lpcyyws8z.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%2Fhdckyamj3o3lpcyyws8z.png" alt="pinecone dashboard" width="798" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the&amp;nbsp;&lt;strong&gt;API Keys&lt;/strong&gt;&amp;nbsp;tab, then click&amp;nbsp;&lt;strong&gt;Create API Key&lt;/strong&gt;. You can either use the default key or create a new one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmxz9kn161tw0x1r71uq.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%2Fhmxz9kn161tw0x1r71uq.png" alt="pinecone key tab" width="799" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Specify the name of the key and click&amp;nbsp;&lt;strong&gt;Create key&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xb6uzjustxg8vl95lyg.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%2F3xb6uzjustxg8vl95lyg.png" alt="create API key" width="585" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’ve completed these steps, return to your .env file, and paste the key:&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="nv"&gt;NEXT_PUBLIC_PINECONE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-api-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Integrating the CopiloKit Node.js Endpoint&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The final step is to add the CopilotKit Node.js endpoint to handle requests from the frontend.&lt;/p&gt;

&lt;p&gt;Before proceeding, you’ll need to set up the Anthropic API to make requests to their service. To do that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an Anthropic Account by visiting the&amp;nbsp;&lt;a href="https://docs.anthropic.com/en/api/getting-started#accessing-the-api" rel="noopener noreferrer"&gt;Anthropic AI documentation&lt;/a&gt;&amp;nbsp;to create an account and set up billing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevfxogioo1g1dbfd02un.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%2Fevfxogioo1g1dbfd02un.png" alt="anthropic" width="790" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After logging into the Anthropic API console, generate your API key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3akukmi07bgtdsr9d9jg.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%2F3akukmi07bgtdsr9d9jg.png" alt="anthropic2" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once you have the API key, add it to your .env file in the root of your project:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Be sure to set up billing and quotas to enable your app to make API requests.&lt;/p&gt;

&lt;p&gt;Remember, we added the CopilotKit API URL in the app’s client to allow it to forward requests to the CopilotKit backend for processing. To make this work, we need to define the CopilotKit API endpoint to manage and handle those requests. Let’s start by importing the following in the &lt;code&gt;src/app/api/copilotkit/route.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CopilotRuntime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AnthropicAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;copilotRuntimeNextJSAppRouterEndpoint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Copilot Runtime is the backend engine of CopilotKit, allowing apps to interact with LLMs. With it, you can define backend action for your copilots. And there are a ton of tasks you could specify, including executing internal database calls and managing different processes and workflows. However, for this specific example, we’ll define an action to query the Pinecone index for relevant articles based on the user query.&lt;/p&gt;

&lt;p&gt;To do that, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runtime&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;CopilotRuntime&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;FetchKnowledgebaseArticles&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;Fetch relevant knowledge base articles based on a user query&lt;/span&gt;&lt;span class="dl"&gt;'&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="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;query&lt;/span&gt;&lt;span class="dl"&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 User query for the knowledge base index search to perform&lt;/span&gt;&lt;span class="dl"&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="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="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;queryEmbedding&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;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;inputType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryResponse&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;pinecone&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;indexName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knowledge-base-data-namespace&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="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
              &lt;span class="na"&gt;topK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queryEmbedding&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;values&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
              &lt;span class="na"&gt;includeValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;includeMetadata&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queryResponse&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;matches&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="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="s1"&gt;Error fetching knowledge base articles:&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="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;Failed to fetch knowledge base articles.&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="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;Let’s break down this action handler. Ideally, this handle is the core engine for this entire integration. This action handler receives the query parameter passed from the Copilot client.&lt;/p&gt;

&lt;p&gt;Using Pinecone’s query operation, the query is converted into a vector representation, which is then compared to the indexed vectors stored in Pinecone to identify the top three most relevant articles in the index. The result includes the vector values and metadata, which contain the actual matching data for the query.&lt;/p&gt;

&lt;p&gt;Since most product knowledge bases have a ton of article posts, some even cover similar ideas, while others are totally different. It’s therefore practical to return multiple relevant pieces of data matching the query. (You can adjust the &lt;code&gt;topK&lt;/code&gt; value to return the number of matching data objects based on your intended use case). &lt;/p&gt;

&lt;p&gt;Finally, go ahead, and add the following code to define the CopilotKit endpoint as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anthropic&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;Anthropic&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;ANTHROPIC_API_KEY&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;serviceAdapter&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;AnthropicAdapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handleRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;copilotRuntimeNextJSAppRouterEndpoint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;serviceAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/copilotkit&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;return&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;Make sure that the same URL you include in the CopilotKit API endpoint (/api/copilotkit) is specified in your frontend.&lt;/p&gt;

&lt;p&gt;To test the entire app, navigate to your main project directory in the terminal and run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, head over to &lt;code&gt;localhost:3000&lt;/code&gt; in your browser and ask a question like “What features does CopilotKit offer?” in the Sidebar input field. &lt;/p&gt;

&lt;p&gt;The result, is a fully functioning RAG Knowledge Base application using CopilotKit:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/3T_ekLVGGFI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Users can continue asking additional questions; if you have a multitude of articles, instead of sifting through different pages, having the Copilot retrieve the information users need makes the process a whole lot easier.&lt;/p&gt;

&lt;p&gt;For reference, or if you want to build on top of what we’ve covered in this article, you can clone this project’s source code from the&amp;nbsp;&lt;a href="https://github.com/ItsWachira/Next-Anthropic-AI-Copilot-Product-Knowledge-base" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this guide, we have walked through the steps of building an Anthropic-powered Copilot using&amp;nbsp;&lt;a href="https://copilotkit.ai/" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt;, Anthropic AI API, and Pinecone API  for product knowledge bases.&lt;/p&gt;

&lt;p&gt;While we’ve explored a couple of features, we have barely scratched the surface of CopilotKit's countless use cases, which range from building interactive AI chatbots to building agentic solutions. In essence, CopilotKit lets you add a ton of useful AI capabilities to your products in minutes.&lt;/p&gt;

&lt;p&gt;If you’re looking to integrate AI-powered Copilots into your existing application, consider&amp;nbsp;&lt;a href="https://www.copilotkit.ai/contact-us" rel="noopener noreferrer"&gt;scheduling a demo&lt;/a&gt;, join the &lt;a href="https://go.copilotkit.ai/discord" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt; of developers, and&amp;nbsp;&lt;a href="https://docs.copilotkit.ai/" rel="noopener noreferrer"&gt;get started with the docs&lt;/a&gt;&amp;nbsp;to try it out yourself!&lt;/p&gt;

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