<?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: Sam Kennard</title>
    <description>The latest articles on DEV Community by Sam Kennard (@sam_kennard_8d1969bb).</description>
    <link>https://dev.to/sam_kennard_8d1969bb</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%2F3593008%2F74d29c11-0423-45f4-886b-4e35d5b520c3.png</url>
      <title>DEV Community: Sam Kennard</title>
      <link>https://dev.to/sam_kennard_8d1969bb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sam_kennard_8d1969bb"/>
    <language>en</language>
    <item>
      <title>The Claude skill that knows your pipeline</title>
      <dc:creator>Sam Kennard</dc:creator>
      <pubDate>Thu, 30 Apr 2026 11:47:04 +0000</pubDate>
      <link>https://dev.to/sam_kennard_8d1969bb/the-claude-skill-that-knows-your-pipeline-nlm</link>
      <guid>https://dev.to/sam_kennard_8d1969bb/the-claude-skill-that-knows-your-pipeline-nlm</guid>
      <description>&lt;p&gt;&lt;em&gt;Your CRM is the clean version of every deal. Your inbox is what actually happened. Six pre-built reasoning blocks that pull the second one into Claude via iGPT.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Your CRM says what someone remembered to log. The actual deal lives somewhere messier: the objection that never made it into Salesforce, the proposal revision sitting in Drive, the follow-up question buried in a forwarded thread, the competitor mention that appeared once three weeks before the deal stalled.&lt;/p&gt;

&lt;p&gt;That's the sales context AI usually doesn't see.&lt;/p&gt;

&lt;p&gt;The iGPT Sales Workflow Pack is a Claude plugin that pulls it into the conversation.&lt;/p&gt;

&lt;p&gt;Two parts. The plugin is six pre-built reasoning blocks that know which questions to ask for each part of your sales week. iGPT is the API doing the work underneath, indexing your inbox and Drive so Claude can actually read your customer conversations. Without iGPT, the plugin is clever questions pointed at nothing. Without the plugin, iGPT is an API you'd have to learn before it becomes useful.&lt;/p&gt;

&lt;p&gt;Together: sales reasoning that runs on your real data. About ten minutes of setup, then it's there every time you open Claude.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this looks like in your actual week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monday morning.&lt;/strong&gt; You ask Claude what to focus on. It tells you which three deals went quiet last week, which two are sitting on an unanswered question from the prospect, and which one has an open commitment from your side that's now four days overdue. With the threads linked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before a call at 10am.&lt;/strong&gt; You ask for a brief on the contact. Every commitment they made, every commitment you made, every objection they raised, the tone shift in the last reply, what's still open. You walk into the call with the version of yourself who actually re-read every email this morning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mid-week deal review.&lt;/strong&gt; Your manager asks "what's stuck on the [account] deal?" Instead of scanning the thread for ten minutes, you ask Claude. It comes back with the specific objection that's gone unaddressed since the last call, the price hesitation buried in a quoted reply two weeks ago, and the security question their IT person asked that nobody answered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thursday afternoon.&lt;/strong&gt; You ask which existing customers have shown expansion signals lately. Three accounts come back with the exact moments — a customer mentioning a problem your premium tier solves, a side comment about wanting to bring on more seats, a buying signal in a forwarded thread. None of these were in the CRM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Friday before logging off.&lt;/strong&gt; You run friction detection across every open deal in one query. Whatever needed your attention is sitting in front of you Monday morning, ranked.&lt;/p&gt;

&lt;p&gt;The skills cover the rest of the week too: catching follow-ups you dropped, surfacing every time a competitor came up in your threads (with what they were compared on), finding past customer problems you already solved that map to what a new prospect is asking about.&lt;/p&gt;

&lt;p&gt;You can run any of them on a single deal, a named contact, a named account, or your full book.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you actually get
&lt;/h2&gt;

&lt;p&gt;A 30-second answer to questions that used to take 30 minutes of digging.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;What used to happen&lt;/th&gt;
&lt;th&gt;What happens now&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"What did we agree on with the prospect last Tuesday?"&lt;/td&gt;
&lt;td&gt;Re-read three threads to reconstruct it&lt;/td&gt;
&lt;td&gt;Open items, owner, dates raised, sources cited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Which deals went quiet this week?"&lt;/td&gt;
&lt;td&gt;Scan your inbox guessing at what's stale&lt;/td&gt;
&lt;td&gt;Stale threads, last-touch dates, last unanswered question&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Why is the prospect not responding?"&lt;/td&gt;
&lt;td&gt;Stare at the thread, theorize&lt;/td&gt;
&lt;td&gt;Friction signals, unresolved objections, the moment momentum dropped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"What did we promise customers and never deliver on?"&lt;/td&gt;
&lt;td&gt;You forget about it until they remind you&lt;/td&gt;
&lt;td&gt;Commitments living in old threads that never made it to the CRM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run the friction detector across every open deal on Friday afternoon, and you have your Monday pipeline review on the way out the door.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this works (the iGPT part)
&lt;/h2&gt;

&lt;p&gt;iGPT is the email context API doing the work underneath. It indexes your inbox and Google Drive in the background, reconstructs threads, links email attachments to their conversations, and returns structured intelligence with full source attribution in a single call. Per-user scoping. Read-only. The same infrastructure serious teams are using to build production sales agents right now.&lt;/p&gt;

&lt;p&gt;The plugin is the sales-shaped layer on top. It knows what to ask iGPT for, in what shape, for each moment in the sales week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup, about ten minutes total
&lt;/h2&gt;

&lt;p&gt;Three things to do, once.&lt;/p&gt;

&lt;p&gt;Before you start: this works on Claude Pro, Max, Team, or Enterprise plans. If you're on free, you'll need to upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Connect iGPT to your inbox
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://igpt.ai/hub/playground/" rel="noopener noreferrer"&gt;igpt.ai/hub/playground&lt;/a&gt; and sign in with your work email. From the dashboard, click &lt;strong&gt;Add data source&lt;/strong&gt; to connect Gmail or Outlook, and Google Drive if you use one. iGPT starts indexing in the background.&lt;/p&gt;

&lt;p&gt;First index takes a few minutes for a normal inbox, longer if you've got years of mail in there. You don't need to wait — the rest of setup happens in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Add iGPT as a connector in Claude
&lt;/h3&gt;

&lt;p&gt;Open Claude (the desktop app or &lt;a href="https://claude.ai" rel="noopener noreferrer"&gt;claude.ai&lt;/a&gt; in your browser).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click your profile picture in the bottom-left, then &lt;strong&gt;Settings → Connectors&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Scroll down, click &lt;strong&gt;Add custom connector&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Paste &lt;code&gt;https://mcp.igpt.ai&lt;/code&gt; in the URL field. Save.&lt;/li&gt;
&lt;li&gt;You'll see a new entry called &lt;strong&gt;igpt&lt;/strong&gt; in your connector list. Click &lt;strong&gt;Connect&lt;/strong&gt; on it.&lt;/li&gt;
&lt;li&gt;Claude redirects you to authorize iGPT (same flow as authorizing Google or Slack). Approve, and you're back in Claude.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is what lets Claude actually read your indexed inbox when the plugin asks for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Install the sales plugin
&lt;/h3&gt;

&lt;p&gt;In Claude:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Customize → Plugins&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Browse plugins&lt;/strong&gt;, then switch to the &lt;strong&gt;Personal&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;+&lt;/strong&gt; button to &lt;strong&gt;Add marketplace&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Paste &lt;code&gt;https://github.com/igptai/skills&lt;/code&gt; in the URL field. Hit &lt;strong&gt;Sync&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll see all the iGPT plugins show up — sales, customer success, finance, marketing, and the rest. They're listed but not installed yet.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find &lt;strong&gt;igpt sales&lt;/strong&gt; and click &lt;strong&gt;Install&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll get a confirmation: &lt;em&gt;"igpt sales is installed and ready to use."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's it. The skill is available in every Claude chat you open, not just in one Project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Now use it
&lt;/h2&gt;

&lt;p&gt;Open a new chat. Ask in your own words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Prep me for my call with [contact] tomorrow."&lt;/li&gt;
&lt;li&gt;"What follow-ups did I drop this week?"&lt;/li&gt;
&lt;li&gt;"What's stuck on the [account] deal?"&lt;/li&gt;
&lt;li&gt;"Find every time [prospect] mentioned a competitor in our threads."&lt;/li&gt;
&lt;li&gt;"Which customers have shown expansion signals lately?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude recognizes what you're asking for, runs the right reasoning block against your real inbox via iGPT, and returns the answer with source emails linked. First run, you'll see a confirmation that the iGPT connector is being used. After that, it's invisible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Grab it
&lt;/h2&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/igptai/skills" rel="noopener noreferrer"&gt;github.com/igptai/skills&lt;/a&gt; (the marketplace URL you paste in step 3)&lt;/p&gt;

&lt;p&gt;This is the install for any team where the deal context actually lives across email threads, SOWs in Drive, and forwarded chains. If your sales motion runs mostly on calls and Slack, with a CRM that's somehow always up to date, the plugin will be quieter for you.&lt;/p&gt;

&lt;p&gt;For everyone else: reps get the upside without writing a line of code. If you build sales infrastructure for a living, the same API is right there to build your own plugins against.&lt;/p&gt;

&lt;p&gt;Either way, your week just got 90 minutes shorter.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>llm</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Context Engineering Has a Blind Spot</title>
      <dc:creator>Sam Kennard</dc:creator>
      <pubDate>Wed, 18 Mar 2026 10:27:57 +0000</pubDate>
      <link>https://dev.to/sam_kennard_8d1969bb/context-engineering-has-a-blind-spot-1jl6</link>
      <guid>https://dev.to/sam_kennard_8d1969bb/context-engineering-has-a-blind-spot-1jl6</guid>
      <description>&lt;p&gt;The biggest shift in agent design over the past year has been context engineering rather than improved models. Most of the published guidance focuses on codebases, documentation, and structured knowledge bases, and it's good guidance.&lt;/p&gt;

&lt;p&gt;But there's a category of enterprise data that breaks every standard &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;context engineering&lt;/a&gt; pattern, and almost nobody is writing about it: email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why email is different from everything else
&lt;/h2&gt;

&lt;p&gt;When &lt;a href="https://developers.googleblog.com/architecting-efficient-context-aware-multi-agent-framework-for-production/" rel="noopener noreferrer"&gt;Google's ADK team writes about context engineering&lt;/a&gt;, they describe a pipeline: ingest data, compile a view, serve it to the model. &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;When Anthropic describes it&lt;/a&gt;, they talk about curating tokens for maximum utility. &lt;/p&gt;

&lt;p&gt;Both assume the source data has some structural integrity to work with, because a codebase has files, functions, and imports, a knowledge base has documents with authors and dates, and even Slack has channels and timestamps.&lt;/p&gt;

&lt;p&gt;Email has none of that. A 20-reply business thread contains the same quoted text duplicated up to 20 times, every email client quoting differently (Gmail uses &amp;gt; prefixes, Outlook uses indentation, Apple Mail wraps in blockquote HTML). &lt;/p&gt;

&lt;p&gt;Forwarded chains collapse three separate conversations into a single message body with no structural separator. Inline replies break every deduplication pattern because someone typed new content between quoted blocks. &lt;/p&gt;

&lt;p&gt;And the most critical information, the PDF with the actual contract terms or the invoice that needs reconciling, is sitting in an attachment that most context pipelines never touch.&lt;/p&gt;

&lt;p&gt;This is where a huge amount of enterprise context actually lives, not in the CRM fields or the wiki, but in the messy, unstructured communication data where business actually happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  What breaks at enterprise scale
&lt;/h2&gt;

&lt;p&gt;The reason this matters isn't that one agent can't parse one email thread. It's what happens when you try to run context engineering across an organization's entire communication history. &lt;/p&gt;

&lt;p&gt;A finance team closing the books at month-end needs to reconcile invoices against purchase order approvals across hundreds of vendors. The invoices arrive as PDF attachments and the approvals live in email threads scattered across 15 people's inboxes, often buried in a reply that says "approved, go ahead" with no formal record in any system. &lt;/p&gt;

&lt;p&gt;An agent running multi-hop search over this data makes one retrieval call, gets a fragment, reformulates, searches again, and by hop 5 it's burning 40,000 tokens on a single vendor reconciliation. &lt;/p&gt;

&lt;p&gt;Multiply that by 300 vendors and you've spent more on token costs than the finance team's monthly payroll, with accuracy degrading on every query because each hop compounds the noise from the previous one.&lt;/p&gt;

&lt;p&gt;A compliance team monitoring regulatory commitments has to scan 50,000 threads per month for obligations that were agreed to in email and never entered into a tracking system. The commitments aren't labeled, they're buried in sentences like "we can do that by Q3" from someone in a 30-reply thread where the first 20 messages were about something else entirely. &lt;/p&gt;

&lt;p&gt;A multi-hop agent searching for "regulatory commitments" returns threads that mention regulations, not threads that contain actual commitments. The semantic gap between what the agent searches for and what the data looks like structurally is exactly where context engineering is supposed to help, and where standard approaches fail on email.&lt;/p&gt;

&lt;p&gt;A sales organization running deal risk scoring across 200 active opportunities needs to detect signals that only exist in email patterns: the champion going quiet over two weeks, procurement entering a thread where they weren't before, reply latency increasing, tone shifting from collaborative to transactional. &lt;/p&gt;

&lt;p&gt;None of this shows up in the CRM, which says the deal is "Stage 3, on track" while the email thread says the deal is dying. An agent that can't reason over the full communication history with participant attribution, temporal ordering, and cross-thread awareness will miss every one of these signals, and miss them confidently.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architectural gap
&lt;/h2&gt;

&lt;p&gt;Standard context engineering assumes you can compile a useful view of your data at query time. For email at enterprise scale, this doesn't hold because the preprocessing required to make email useful is too expensive and too complex to do per-query.&lt;/p&gt;

&lt;p&gt;Thread reconstruction, quoted text deduplication, participant attribution, attachment extraction, temporal ordering across threads that reference each other: this work needs to happen once at index time, not repeatedly inside an agent loop. &lt;/p&gt;

&lt;p&gt;When you do it at index time, the agent gets pre-assembled context in a single retrieval call where latency is predictable, cost is fixed, and the same query returns the same result every time, which is the only way downstream automation actually works.&lt;/p&gt;

&lt;p&gt;When you try to do it at query time through multi-hop search, you get variable latency (10-60 seconds depending on thread complexity), variable cost (scales with how messy the data is, which means your hardest queries are your most expensive), and variable accuracy (each hop builds on the previous hop's interpretation, and the error compounds). &lt;/p&gt;

&lt;p&gt;The agent is simultaneously trying to reconstruct the conversation, figure out who said what, determine what's current versus what's quoted history, and answer the actual question. That's four jobs where each one is hard enough on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What index-time context engineering looks like
&lt;/h2&gt;

&lt;p&gt;The work that makes email usable for agents comes down to a few things that need to happen once, not per-query: reconstruct threads, strip quoted text, attribute who said what, and actually read attachments. &lt;/p&gt;

&lt;p&gt;Then index all of it with semantic and structural metadata, scoped per-user so one person's agent can't surface another person's data.&lt;/p&gt;

&lt;p&gt;Most teams skip this and go straight to multi-hop search, which works in demos and breaks in production at exactly the scale where the business case justifies the investment.&lt;/p&gt;

&lt;p&gt;We build this infrastructure at iGPT, where a developer sends one API call and gets back structured, reasoning-ready context with source citations, with no loops or retries or per-query preprocessing.&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;igptai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IGPT&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IGPT&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reconcile Q1 invoices from Apex Logistics, flag PO mismatches&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cef-1-normal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Structured JSON: vendor, invoice amounts, PO deltas, source email citations
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The industry is right to focus on context, but most implementations assume the data is already usable, and email isn't. &lt;/p&gt;

&lt;p&gt;If your agent is reasoning over email without fixing that first, it's not failing because the model is weak, it's failing because the context never made sense in the first place.&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://docs.igpt.ai" rel="noopener noreferrer"&gt;docs.igpt.ai&lt;/a&gt;&lt;br&gt;
SDK: &lt;code&gt;pip install igptai&lt;/code&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>Why email breaks every RAG pipeline</title>
      <dc:creator>Sam Kennard</dc:creator>
      <pubDate>Thu, 12 Feb 2026 13:45:14 +0000</pubDate>
      <link>https://dev.to/sam_kennard_8d1969bb/why-email-breaks-every-rag-pipeline-4i9g</link>
      <guid>https://dev.to/sam_kennard_8d1969bb/why-email-breaks-every-rag-pipeline-4i9g</guid>
      <description>&lt;p&gt;If you've built RAG over email, you know the feeling: everything works on PDFs and wiki pages, and then you point the same pipeline at someone's inbox and the whole thing quietly falls apart. Not with errors, but with bad retrieval you keep trying to fix with better chunking and bigger context windows until you realize the problem was never the retrieval.&lt;/p&gt;

&lt;p&gt;Email threads aren't documents. Every standard RAG approach treats them like they are.&lt;/p&gt;

&lt;h2&gt;
  
  
  The standard approach
&lt;/h2&gt;

&lt;p&gt;Connect to Gmail API, pull messages, chunk, embed, retrieve top-k.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service = build("gmail", "v1", credentials=creds)
results = service.users().messages().list(userId="me", maxResults=50).execute()

raw_emails = []
for msg in results.get("messages", []):
    full = service.users().messages().get(
        userId="me", id=msg["id"], format="full"
    ).execute()
    raw_emails.append({
        "id": msg["id"],
        "threadId": full.get("threadId"),
        "body": get_body_text(full.get("payload", {})),
        "headers": {
            h["name"]: h["value"]
            for h in full.get("payload", {}).get("headers", [])
        }
    })

splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = []
for email in raw_emails:
    for split in splitter.split_text(email["body"]):
        chunks.append({"text": split, "metadata": {"thread_id": email["threadId"]}})

vectorstore = Chroma.from_texts(
    [c["text"] for c in chunks],
    OpenAIEmbeddings(),
    metadatas=[c["metadata"] for c in chunks]
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works on static documents because each chunk is self-contained and relationships between chunks are semantic. Email has neither property.&lt;/p&gt;

&lt;h2&gt;
  
  
  6 ways email breaks this
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. Quoted text duplication
&lt;/h2&gt;

&lt;p&gt;In a 12-message thread, the Gmail API returns every reply with the full quoted chain below it. The original message appears 12 times. When you embed this, the oldest messages and signature blocks dominate the embedding space because they're repeated in every chunk, and the model reads repetition as reinforcement. Your most recent, most relevant messages get buried.&lt;/p&gt;

&lt;p&gt;The fix isn't regex because people reply inline, edit quotes, and forward with additions mid-quote.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Thread structure vanishes
&lt;/h2&gt;

&lt;p&gt;Email threads are conversation trees, not linear sequences. Message 7 might reply to message 3, not message 6. When you embed, that structure disappears. Ask "who approved this" and retrieval surfaces someone saying "looks good" when they were actually being quoted by someone disagreeing with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. CC vs. authorship confusion
&lt;/h2&gt;

&lt;p&gt;Your model sees "David" in the CC line and "David's proposal" in the body and has no structural way to distinguish "David was informed" from "David authored this." Extraction pipelines end up confidently attributing work to people who never wrote a single reply because their names appeared in CC fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Forwarded thread forks
&lt;/h2&gt;

&lt;p&gt;Someone forwards a thread to a new group. Now you have two conversations that share history but diverged, and Gmail treats them as separate threads with no link between them. Ask "what did the team decide" and retrieval pulls from either branch without knowing they're contradictory.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Signatures and boilerplate at scale
&lt;/h2&gt;

&lt;p&gt;Across a real organization: 30+ signature formats, compliance disclaimers in multiple languages, confidentiality notices longer than the actual messages. A meaningful portion of your token budget goes to this noise while the model treats it as content worth reasoning over.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Cross-thread temporal reasoning
&lt;/h2&gt;

&lt;p&gt;"Let's revisit this next quarter" in January. "The timeline we discussed" in March. Completely different words for the same thing. The connection is temporal, not semantic, so vector similarity can't find it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the usual fixes don't work
&lt;/h2&gt;

&lt;p&gt;All six failures happen upstream of the model. Better models reason more confidently over the same broken input. Bigger context windows stuff in more duplicated text you're paying for. &lt;/p&gt;

&lt;p&gt;Better prompts ask the model to reconstruct thread structure, deduplicate quotes, resolve attribution, and track temporal references on every single query. You're pushing infrastructure problems into the prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: treat email as a graph, not a document
&lt;/h2&gt;

&lt;p&gt;Email threads are conversational graphs. Each message is a node, replies create edges, participants have roles that change over time, and decisions create cross-thread edges. The pipeline needs six layers between raw email and your model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│                   YOUR APPLICATION                   │
├─────────────────────────────────────────────────────┤
│  Layer 6: Hybrid Retrieval                           │
│  semantic search + metadata filters + graph traversal│
├─────────────────────────────────────────────────────┤
│  Layer 5: Cross-Thread Linking                       │
│  participant overlap, topic refs, temporal proximity │
├─────────────────────────────────────────────────────┤
│  Layer 4: Structured Metadata Extraction             │
│  decisions, tasks, owners, deadlines, sentiment      │
├─────────────────────────────────────────────────────┤
│  Layer 3: Participant &amp;amp; Role Tracking                │
│  From vs To vs CC, role changes across thread        │
├─────────────────────────────────────────────────────┤
│  Layer 2: Content Deduplication                      │
│  quoted text removal, inline edit preservation       │
├─────────────────────────────────────────────────────┤
│  Layer 1: Thread Reconstruction                      │
│  In-Reply-To / References headers → conversation tree│
├─────────────────────────────────────────────────────┤
│                  RAW EMAIL (Gmail API / IMAP)         │
└─────────────────────────────────────────────────────┘

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

&lt;/div&gt;



&lt;p&gt;Layer 1 is where most people start and stop. Map In-Reply-To headers to build the conversation tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from collections import defaultdict

def build_thread_tree(messages):
    by_message_id = {}
    children = defaultdict(list)
    roots = []

    for msg in messages:
        msg_id = msg["headers"].get("Message-ID", "")
        reply_to = msg["headers"].get("In-Reply-To", "")
        by_message_id[msg_id] = msg

        if reply_to and reply_to in by_message_id:
            children[reply_to].append(msg_id)
        else:
            roots.append(msg_id)

    return roots, children, by_message_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Layers 2-3 handle deduplication and participant roles. Both are straightforward in concept but brutal in practice because email clients format quotes differently, people edit them without marking changes, and the distinction between "David authored this" and "David was CC'd" needs to be structured data, not something the model infers from flattened text.&lt;/p&gt;

&lt;p&gt;Layers 4-6 extract structured metadata (decisions, tasks, owners, deadlines), build cross-thread connections, and combine semantic search with metadata filtering and graph traversal so you can say "find messages from Sarah about Q2 budget where a decision was made" and have the retrieval handle filtering before semantic matching.&lt;/p&gt;

&lt;p&gt;This is what we built &lt;a href="https://www.igpt.ai/" rel="noopener noreferrer"&gt;iGPT&lt;/a&gt; to handle. All six layers, one API call. &lt;a href="https://docs.igpt.ai/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; here.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the difference looks like
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Standard RAG:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;results = vectorstore.similarity_search("What are the open action items?", k=5)
# - 2 chunks dominated by signature blocks
# - 1 chunk from a quoted reply (wrong attribution)
# - 1 relevant chunk buried in noise
# - 1 chunk from an unrelated thread (similar keywords)

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Through iGPT:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from igptai import IGPT

client = IGPT(api_key="your-api-key", user="user-123")
response = client.recall.ask(
    input="What are the open action items from this week?",
    quality="cef-1-normal"
)

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

&lt;/div&gt;



&lt;p&gt;Seven source documents referenced, structured data with owners, dates, and attribution. No signatures, no duplicated quotes, no misattributed CC recipients. The infrastructure handled it before the model saw anything.&lt;/p&gt;

&lt;p&gt;Streaming shows the pipeline stages in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for event in client.recall.ask(
    input="Who committed to what in the last 7 days?",
    stream=True,
    quality="cef-1-normal"
):
    if "delta" in event:
        print(event["delta"]["output"], end="", flush=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sources referenced: 22
Here is a summary of commitments made in the last 7 days...

| Date       | Person       | Commitment                                     |
|------------|-------------|------------------------------------------------|
| 2026-02-09 | Jane Doe | Proposed new campaign, requested alignment sync |
| 2026-02-10 | John Doe  | Reviewing blog and one-pager, final versions    |

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

&lt;/div&gt;



&lt;p&gt;Works the same in &lt;a href="https://www.npmjs.com/package/igptai" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import IGPT from "igptai" and the API is identical.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install igptai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from igptai import IGPT

client = IGPT(api_key="your-key", user="your-user-id")

auth = client.connectors.authorize(
    service="google",
    scope="email",
    redirect_uri="https://your-app.com/callback"
)

datasources = client.datasources.list()

response = client.recall.ask(
    input="What decisions were made this week and who owns next steps?"
)

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

&lt;/div&gt;



&lt;p&gt;Don't want to set up OAuth just to see it work? The playground lets you connect your inbox and run queries in about five minutes, no code required.&lt;br&gt;
Links:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.igpt.ai/" rel="noopener noreferrer"&gt;iGPT Website&lt;/a&gt;&lt;br&gt;
📖 &lt;a href="https://docs.igpt.ai/" rel="noopener noreferrer"&gt;API Documentation&lt;/a&gt;&lt;br&gt;
🐍 &lt;a href="https://github.com/igptai/igptai-python" rel="noopener noreferrer"&gt;Python SDK (PyPI)&lt;/a&gt;&lt;br&gt;
📦 &lt;a href="https://github.com/igptai/igptai-node" rel="noopener noreferrer"&gt;Node.js SDK (npm)&lt;/a&gt;&lt;br&gt;
🛝 &lt;a href="https://igpt.ai/hub/playground/" rel="noopener noreferrer"&gt;Playground&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>api</category>
      <category>email</category>
    </item>
  </channel>
</rss>
