<?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: Blessed Josiah</title>
    <description>The latest articles on DEV Community by Blessed Josiah (@joxiahdev).</description>
    <link>https://dev.to/joxiahdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264588%2F0c86a935-e50c-4218-91db-02f193676739.jpeg</url>
      <title>DEV Community: Blessed Josiah</title>
      <link>https://dev.to/joxiahdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joxiahdev"/>
    <language>en</language>
    <item>
      <title>Building Modular AI Agent Features with Pydantic AI Capabilities</title>
      <dc:creator>Blessed Josiah</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:30:00 +0000</pubDate>
      <link>https://dev.to/joxiahdev/building-modular-ai-agent-features-with-pydantic-ai-capabilities-39d5</link>
      <guid>https://dev.to/joxiahdev/building-modular-ai-agent-features-with-pydantic-ai-capabilities-39d5</guid>
      <description>&lt;p&gt;If you're building AI Agents with Pydantic AI, understanding &lt;strong&gt;Capabilities&lt;/strong&gt; is invaluable - it's the recommended way to add modular, reusable features to your agents.&lt;/p&gt;

&lt;p&gt;This tutorial is part of my ongoing Pydantic AI series on &lt;a href="https://youtube.com/@joxiahdev" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, where I build a full no-code AI agent platform from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Capability?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A capability in Pydantic AI is a modular unit of behavior that can be passed to an AI agent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A capability can give your agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom toolsets&lt;/li&gt;
&lt;li&gt;Instructions&lt;/li&gt;
&lt;li&gt;Model settings&lt;/li&gt;
&lt;li&gt;Lifecycle hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it as a plug-and-play feature module - build it once, attach it to any agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Create a Capability
&lt;/h2&gt;

&lt;p&gt;Capabilities are created using the &lt;code&gt;Capability&lt;/code&gt; or &lt;code&gt;AbstractCapability&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic_ai.capabilities&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AbstractCapability&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;AbstractCapability&lt;/code&gt; gives you full control over instructions, tools, and behavior. It's Pydantic AI's recommended pattern if you're building a library or platform on top of the framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: A Research Capability
&lt;/h2&gt;

&lt;p&gt;In this tutorial, I build a &lt;strong&gt;Research Capability&lt;/strong&gt; powered by the Tavily Search API, and an &lt;strong&gt;Email Capability&lt;/strong&gt; powered by Resend.&lt;/p&gt;

&lt;p&gt;Here's the research capability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic_ai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FunctionToolset&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic_ai.capabilities&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AbstractCapability&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic_ai.common_tools.tavily&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tavily_search_tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResearchCapability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractCapability&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_instructions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You can use the Tavily search tool for research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_toolset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;toolset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FunctionToolset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;toolset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;tavily_search_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tavily_api_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;toolset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it - &lt;code&gt;get_instructions()&lt;/code&gt; tells the agent what it can do, and &lt;code&gt;get_toolset()&lt;/code&gt; gives it the tools to do it. Attach this to any agent, and it instantly gains web research abilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going Further: RAG + GraphRAG
&lt;/h2&gt;

&lt;p&gt;I also built a &lt;strong&gt;Company Knowledge Capability&lt;/strong&gt; that combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;pgvector&lt;/strong&gt; for semantic search over your own data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neo4j + Graphiti&lt;/strong&gt; for knowledge graph retrieval (GraphRAG)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets an agent answer questions from your company's documents, website content, or any knowledge base with both vector search and relationship-aware graph queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the Full Tutorial
&lt;/h2&gt;

&lt;p&gt;This post covers the concept — the full video walks through building both capabilities live, plus the RAG/GraphRAG ingestion pipeline, observability with Logfire, and wiring it all into a working agent.&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;&lt;a href="https://youtu.be/ILHtYme4O60" rel="noopener noreferrer"&gt;Watch on YouTube →&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://github.com/bjoxiah/pydantic-ai-series/tree/no-code-agent" rel="noopener noreferrer"&gt;Full source code →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While you're there, subscribe for more software and AI related content!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>pydanticai</category>
      <category>graphrag</category>
      <category>rag</category>
    </item>
  </channel>
</rss>
