<?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: Marcus ma</title>
    <description>The latest articles on DEV Community by Marcus ma (@cloudsway).</description>
    <link>https://dev.to/cloudsway</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%2F4063632%2Fd8e4a022-66ef-457e-8287-6bbca00de318.png</url>
      <title>DEV Community: Marcus ma</title>
      <link>https://dev.to/cloudsway</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cloudsway"/>
    <language>en</language>
    <item>
      <title>How to Add a Real-Time Search Layer to an Agent Graph</title>
      <dc:creator>Marcus ma</dc:creator>
      <pubDate>Thu, 06 Aug 2026 05:32:27 +0000</pubDate>
      <link>https://dev.to/cloudsway/-2j6c</link>
      <guid>https://dev.to/cloudsway/-2j6c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd" class="crayons-story__hidden-navigation-link"&gt;How to Add a Real-Time Search Layer to an Agent Graph&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/cloudsway" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F4063632%2Fd8e4a022-66ef-457e-8287-6bbca00de318.png" alt="cloudsway profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/cloudsway" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Marcus ma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Marcus ma
                
              
              &lt;div id="story-author-preview-content-4327931" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/cloudsway" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F4063632%2Fd8e4a022-66ef-457e-8287-6bbca00de318.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Marcus ma&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd" id="article-link-4327931"&gt;
          How to Add a Real-Time Search Layer to an Agent Graph
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agents&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>How I Built a Source-Backed Research Paper Search Workflow</title>
      <dc:creator>Marcus ma</dc:creator>
      <pubDate>Thu, 06 Aug 2026 05:27:26 +0000</pubDate>
      <link>https://dev.to/cloudsway/how-i-built-a-source-backed-research-paper-search-workflow-4e39</link>
      <guid>https://dev.to/cloudsway/how-i-built-a-source-backed-research-paper-search-workflow-4e39</guid>
      <description>&lt;h1&gt;
  
  
  How I Built a Source-Backed Research Paper Search Workflow
&lt;/h1&gt;

&lt;p&gt;Searching for research papers sounds straightforward when you already know the title, author, DOI, or exact academic terminology.&lt;/p&gt;

&lt;p&gt;The harder cases begin with incomplete information.&lt;/p&gt;

&lt;p&gt;You may only remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A research question&lt;/li&gt;
&lt;li&gt;An experimental result&lt;/li&gt;
&lt;li&gt;A rough description of the method&lt;/li&gt;
&lt;li&gt;The relationship between two variables&lt;/li&gt;
&lt;li&gt;A paper you saw months ago but cannot name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional keyword search can struggle in these situations. The paper may use terminology that differs from the words you remember, even when the underlying research question is highly relevant.&lt;/p&gt;

&lt;p&gt;I wanted to design a workflow that could start with an ordinary natural-language question, discover potentially relevant public research sources, read the original material, and keep every extracted finding connected to its source.&lt;/p&gt;

&lt;p&gt;The resulting workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Research Question
      ↓
Query Expansion
      ↓
Search API
      ↓
Result Filtering
      ↓
Original Source Reading
      ↓
Research Matrix
      ↓
Manual Verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; This article uses Cloudsway SmartSearch and Reader as one implementation example. The overall workflow is provider-agnostic and can be adapted to other search and document-processing APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem With Searching by Exact Keywords
&lt;/h2&gt;

&lt;p&gt;Academic concepts are often described using multiple terms.&lt;/p&gt;

&lt;p&gt;For example, a researcher studying communication between AI agents might search for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;multi-agent communication frequency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But related papers may use phrases such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent coordination
cooperative agents
decentralized collaboration
message passing
team communication
coordination overhead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single keyword query can miss relevant work simply because the authors used different vocabulary.&lt;/p&gt;

&lt;p&gt;Natural-language search provides another starting point.&lt;/p&gt;

&lt;p&gt;Instead of trying to predict the exact terminology, the researcher can describe the underlying problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find recent research investigating whether increasing communication between AI agents always improves collaborative task performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This query provides more context than a short keyword string.&lt;/p&gt;

&lt;p&gt;It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The research domain: multi-agent systems&lt;/li&gt;
&lt;li&gt;The independent variable: communication frequency&lt;/li&gt;
&lt;li&gt;The outcome: collaborative performance&lt;/li&gt;
&lt;li&gt;The suspected relationship: more communication may not always help&lt;/li&gt;
&lt;li&gt;A recency requirement: recent research&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A search-enabled research assistant can use these signals to create several narrower queries rather than depending on one exact phrase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Define the Research Question
&lt;/h2&gt;

&lt;p&gt;Before calling a search API, the workflow should structure the user's question.&lt;/p&gt;

&lt;p&gt;A useful research-question object might contain:&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="n"&gt;research_question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;topic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multi-agent coordination&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;independent_variable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;communication frequency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcome&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;collaborative task performance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research_interest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whether more communication always improves performance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date_range&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recent research&lt;/span&gt;&lt;span class="sh"&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;The fields will vary by discipline, but the general principle is consistent: extract the concepts that should guide retrieval.&lt;/p&gt;

&lt;p&gt;For empirical research, useful fields may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Population or system&lt;/li&gt;
&lt;li&gt;Intervention or independent variable&lt;/li&gt;
&lt;li&gt;Outcome&lt;/li&gt;
&lt;li&gt;Method&lt;/li&gt;
&lt;li&gt;Context&lt;/li&gt;
&lt;li&gt;Time range&lt;/li&gt;
&lt;li&gt;Language&lt;/li&gt;
&lt;li&gt;Publication type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow should preserve the original user question alongside this structured version. The structured fields help generate queries, while the original wording helps evaluate whether a result actually answers the user's question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Generate Query Variations
&lt;/h2&gt;

&lt;p&gt;The next stage expands the research question into multiple search formulations.&lt;/p&gt;

&lt;p&gt;For example:&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="n"&gt;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multi-agent communication frequency collaborative performance research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent communication overhead coordination experiments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;does more communication improve multi-agent cooperation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;decentralized agent coordination message frequency study&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limited communication multi-agent task performance paper&lt;/span&gt;&lt;span class="sh"&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;These queries cover different ways researchers might describe the same problem.&lt;/p&gt;

&lt;p&gt;A more advanced planner could generate separate query categories:&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="n"&gt;query_groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;direct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multi-agent communication frequency performance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alternative_terms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent message passing coordination quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cooperative agents communication overhead&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contradictory_evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;excessive communication reduces multi-agent performance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limited communication improves agent collaboration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source_specific&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site:arxiv.org multi-agent communication coordination&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site:acm.org multi-agent communication performance&lt;/span&gt;&lt;span class="sh"&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;Searching for contradictory evidence is especially useful.&lt;/p&gt;

&lt;p&gt;A research workflow should not only retrieve sources that appear to confirm the initial assumption. It should also look for papers reporting null effects, boundary conditions, trade-offs, or opposing findings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Search Across Public Research Sources
&lt;/h2&gt;

&lt;p&gt;A search API can act as the discovery layer.&lt;/p&gt;

&lt;p&gt;The goal at this stage is not to generate a literature review immediately. It is to identify potentially useful sources and preserve enough metadata to evaluate them.&lt;/p&gt;

&lt;p&gt;Possible destinations include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arXiv&lt;/li&gt;
&lt;li&gt;PubMed&lt;/li&gt;
&lt;li&gt;Semantic Scholar&lt;/li&gt;
&lt;li&gt;Conference websites&lt;/li&gt;
&lt;li&gt;University repositories&lt;/li&gt;
&lt;li&gt;Research-group websites&lt;/li&gt;
&lt;li&gt;Journal landing pages&lt;/li&gt;
&lt;li&gt;Publicly accessible PDFs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this workflow, I use &lt;a href="https://www.cloudsway.ai/docs/search/introduction" rel="noopener noreferrer"&gt;Cloudsway SmartSearch&lt;/a&gt; as the search layer.&lt;/p&gt;

&lt;p&gt;The search response should be normalized into a consistent format before other parts of the application process it.&lt;/p&gt;

&lt;p&gt;For example:&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SearchResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;source_domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provider-specific response can then be converted into this schema:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;normalize_search_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SearchResult&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source_domain&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query&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 keeps the rest of the workflow independent from the search provider's exact response format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Filter and Deduplicate the Results
&lt;/h2&gt;

&lt;p&gt;The same paper may appear in several places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A preprint platform&lt;/li&gt;
&lt;li&gt;A journal page&lt;/li&gt;
&lt;li&gt;A university repository&lt;/li&gt;
&lt;li&gt;An author's personal website&lt;/li&gt;
&lt;li&gt;A conference page&lt;/li&gt;
&lt;li&gt;A secondary article discussing the paper&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without deduplication, an application may mistakenly treat these pages as separate pieces of evidence.&lt;/p&gt;

&lt;p&gt;A basic deduplication process can compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normalized titles&lt;/li&gt;
&lt;li&gt;DOI values, when available&lt;/li&gt;
&lt;li&gt;Author names&lt;/li&gt;
&lt;li&gt;Publication year&lt;/li&gt;
&lt;li&gt;Canonical URLs&lt;/li&gt;
&lt;li&gt;Similarity between abstracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conceptually:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;normalize_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&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; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="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="sh"&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;replace&lt;/span&gt;&lt;span class="p"&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="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="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="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deduplicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SearchResult&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SearchResult&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;unique_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;seen_titles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalize_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen_titles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;seen_titles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;unique_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;unique_results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is deliberately simple. A production system would need stronger matching logic, especially when titles differ between preprint and published versions.&lt;/p&gt;

&lt;p&gt;After deduplication, results can be ranked using criteria such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Relevance to the research question
Publication date
Source authority
Availability of the original paper
Presence of an abstract or full text
Methodological relevance
Language
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow should also distinguish between source types.&lt;/p&gt;

&lt;p&gt;A journal landing page, preprint, university repository, and blog post may all be useful, but they do not provide the same level of evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Read the Original Source
&lt;/h2&gt;

&lt;p&gt;A title and search snippet are not enough for a literature review.&lt;/p&gt;

&lt;p&gt;They may help determine whether a paper is worth opening, but they rarely provide sufficient detail about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Research design&lt;/li&gt;
&lt;li&gt;Sample or dataset&lt;/li&gt;
&lt;li&gt;Experimental environment&lt;/li&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Evaluation metrics&lt;/li&gt;
&lt;li&gt;Main findings&lt;/li&gt;
&lt;li&gt;Limitations&lt;/li&gt;
&lt;li&gt;Boundary conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow therefore needs a separate reading stage.&lt;/p&gt;

&lt;p&gt;In this implementation, &lt;a href="https://www.cloudsway.ai/docs/search/introduction" rel="noopener noreferrer"&gt;Cloudsway Reader&lt;/a&gt; processes selected webpages and supported PDF content after SmartSearch discovers the sources.&lt;/p&gt;

&lt;p&gt;The separation is useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SmartSearch
  ↓
Find potentially relevant sources
  ↓
Reader
  ↓
Process selected original content
  ↓
Structured extraction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search is responsible for discovery.&lt;/p&gt;

&lt;p&gt;Reader is responsible for turning the selected source into usable context.&lt;/p&gt;

&lt;p&gt;The application can then ask the extraction model to return a structured record:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaperRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;source_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;research_question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;dataset_or_sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;main_findings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;limitations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;verification_notes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An extraction prompt might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read the provided research source and extract:

1. The research question
2. The proposed method
3. The dataset, sample, or experimental environment
4. The evaluation metrics
5. The main findings
6. The limitations explicitly reported by the authors
7. Statements that cannot be verified from the available content

Do not infer missing methodological details.
Keep every extracted statement connected to the source URL.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final instruction matters.&lt;/p&gt;

&lt;p&gt;A research assistant should distinguish between information that appears in the source and conclusions inferred by the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Build a Research Matrix
&lt;/h2&gt;

&lt;p&gt;The extracted paper records can be stored in a research matrix.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Paper&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Dataset or Setting&lt;/th&gt;
&lt;th&gt;Main Finding&lt;/th&gt;
&lt;th&gt;Limitations&lt;/th&gt;
&lt;th&gt;Verification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paper A&lt;/td&gt;
&lt;td&gt;Original URL&lt;/td&gt;
&lt;td&gt;Experimental study&lt;/td&gt;
&lt;td&gt;Multi-agent simulation&lt;/td&gt;
&lt;td&gt;Finding summary&lt;/td&gt;
&lt;td&gt;Reported limitations&lt;/td&gt;
&lt;td&gt;Needs full-text review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paper B&lt;/td&gt;
&lt;td&gt;Original URL&lt;/td&gt;
&lt;td&gt;Benchmark evaluation&lt;/td&gt;
&lt;td&gt;Collaborative task environment&lt;/td&gt;
&lt;td&gt;Finding summary&lt;/td&gt;
&lt;td&gt;Limited task diversity&lt;/td&gt;
&lt;td&gt;Abstract verified&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paper C&lt;/td&gt;
&lt;td&gt;Original URL&lt;/td&gt;
&lt;td&gt;Theoretical analysis&lt;/td&gt;
&lt;td&gt;Decentralized agents&lt;/td&gt;
&lt;td&gt;Finding summary&lt;/td&gt;
&lt;td&gt;No empirical test&lt;/td&gt;
&lt;td&gt;Full source reviewed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The research matrix makes it easier to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compare methods&lt;/li&gt;
&lt;li&gt;Identify conflicting findings&lt;/li&gt;
&lt;li&gt;Track missing information&lt;/li&gt;
&lt;li&gt;Detect repeated datasets&lt;/li&gt;
&lt;li&gt;Organize papers by theme&lt;/li&gt;
&lt;li&gt;Preserve source links&lt;/li&gt;
&lt;li&gt;Prepare a literature review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple data structure could look like:&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="n"&gt;research_matrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;paper&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;selected_papers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_and_extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paper&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;research_matrix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This matrix should not be treated as the final literature review.&lt;/p&gt;

&lt;p&gt;It is an intermediate research artifact that helps a human researcher understand and verify the source set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Keep Claims Connected to Sources
&lt;/h2&gt;

&lt;p&gt;One of the biggest risks in AI-assisted research is losing the connection between a generated statement and its original source.&lt;/p&gt;

&lt;p&gt;For example, the system might generate:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Increased communication improves coordination only up to a certain threshold.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That statement should not exist in the final output without metadata showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which paper reported it&lt;/li&gt;
&lt;li&gt;Where the paper was found&lt;/li&gt;
&lt;li&gt;Whether the full text was read&lt;/li&gt;
&lt;li&gt;Whether the finding came from the authors or was inferred&lt;/li&gt;
&lt;li&gt;Whether another source reported a conflicting result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A claim object can preserve this connection:&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="n"&gt;claim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Increased communication improved coordination only up to a threshold.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source_title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example Paper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.org/paper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reported finding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verification_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full text reviewed&lt;/span&gt;&lt;span class="sh"&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;The final synthesis stage should consume these claim objects rather than disconnected summaries.&lt;/p&gt;

&lt;p&gt;This reduces the likelihood of citations being added after the answer has already been generated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Handle Missing or Incomplete Evidence
&lt;/h2&gt;

&lt;p&gt;The workflow must be allowed to return incomplete results.&lt;/p&gt;

&lt;p&gt;A search API cannot guarantee that every important paper will be found. Some papers may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Behind paywalls&lt;/li&gt;
&lt;li&gt;Missing from public indexes&lt;/li&gt;
&lt;li&gt;Published under unexpected terminology&lt;/li&gt;
&lt;li&gt;Available only in a different language&lt;/li&gt;
&lt;li&gt;Incorrectly dated&lt;/li&gt;
&lt;li&gt;Poorly represented by search snippets&lt;/li&gt;
&lt;li&gt;Accessible only through metadata pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow should therefore support statuses such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source_found
full_text_available
abstract_only
metadata_only
requires_manual_access
insufficient_evidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A result with limited access might be stored as:&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="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example Research Paper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.org/paper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abstract_only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;extraction_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;partial&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manual_review_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&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 is more reliable than allowing the model to fill in missing information.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simplified End-to-End Workflow
&lt;/h2&gt;

&lt;p&gt;The complete process can be represented with provider-agnostic pseudocode:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_research_matrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reader_client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Structure the research question
&lt;/span&gt;    &lt;span class="n"&gt;research_scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_research_question&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Create several query variations
&lt;/span&gt;    &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_query_variations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;research_scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Search for public research sources
&lt;/span&gt;    &lt;span class="n"&gt;search_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;raw_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;search_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nf"&gt;normalize_search_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Remove likely duplicates
&lt;/span&gt;    &lt;span class="n"&gt;unique_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deduplicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Rank and select promising sources
&lt;/span&gt;    &lt;span class="n"&gt;selected_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rank_and_select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;unique_results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;research_scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;research_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 6. Read and extract information
&lt;/span&gt;    &lt;span class="n"&gt;research_matrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;selected_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;source_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_paper_record&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;source_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;source_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;research_matrix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 7. Mark records requiring human verification
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;add_verification_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;research_matrix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production version would also need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API error handling&lt;/li&gt;
&lt;li&gt;Rate-limit handling&lt;/li&gt;
&lt;li&gt;Search-result caching&lt;/li&gt;
&lt;li&gt;Maximum query budgets&lt;/li&gt;
&lt;li&gt;PDF-processing limits&lt;/li&gt;
&lt;li&gt;Source-domain filters&lt;/li&gt;
&lt;li&gt;Prompt-injection defenses&lt;/li&gt;
&lt;li&gt;DOI and author extraction&lt;/li&gt;
&lt;li&gt;Better duplicate detection&lt;/li&gt;
&lt;li&gt;Logging and tracing&lt;/li&gt;
&lt;li&gt;Manual approval steps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What This Workflow Can and Cannot Do
&lt;/h2&gt;

&lt;p&gt;This workflow can help with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starting from an incomplete description&lt;/li&gt;
&lt;li&gt;Expanding academic terminology&lt;/li&gt;
&lt;li&gt;Discovering public research sources&lt;/li&gt;
&lt;li&gt;Reading selected pages and supported PDFs&lt;/li&gt;
&lt;li&gt;Structuring methods and findings&lt;/li&gt;
&lt;li&gt;Building a source-linked research matrix&lt;/li&gt;
&lt;li&gt;Identifying records that require manual verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It cannot guarantee:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete literature coverage&lt;/li&gt;
&lt;li&gt;Access to every paywalled paper&lt;/li&gt;
&lt;li&gt;Correct interpretation of every method&lt;/li&gt;
&lt;li&gt;Accurate citation formatting&lt;/li&gt;
&lt;li&gt;Identification of every duplicate&lt;/li&gt;
&lt;li&gt;Elimination of hallucinated conclusions&lt;/li&gt;
&lt;li&gt;Replacement of expert academic judgment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Search and extraction APIs can reduce manual work, but the researcher still needs to evaluate inclusion criteria, methodological quality, theoretical relevance, and the accuracy of the final synthesis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Checks Before Using the Results
&lt;/h2&gt;

&lt;p&gt;Before using an AI-generated research matrix in a paper or report, I would check:&lt;/p&gt;

&lt;h3&gt;
  
  
  Source identity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is this the original paper?&lt;/li&gt;
&lt;li&gt;Is it a preprint, accepted manuscript, or final version?&lt;/li&gt;
&lt;li&gt;Are the title, authors, and publication year correct?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Methodology
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Was the method extracted from the full paper or only the abstract?&lt;/li&gt;
&lt;li&gt;Are the sample and dataset accurately described?&lt;/li&gt;
&lt;li&gt;Are causal claims supported by the research design?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Findings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does the generated summary match the authors' wording?&lt;/li&gt;
&lt;li&gt;Were limitations or boundary conditions omitted?&lt;/li&gt;
&lt;li&gt;Are statistically insignificant findings being overstated?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Coverage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Were several query variations used?&lt;/li&gt;
&lt;li&gt;Were references from key papers reviewed?&lt;/li&gt;
&lt;li&gt;Were different languages and source categories considered?&lt;/li&gt;
&lt;li&gt;Could terminology differences have excluded relevant papers?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Traceability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does every important claim include a source URL?&lt;/li&gt;
&lt;li&gt;Can the original passage be located?&lt;/li&gt;
&lt;li&gt;Is the distinction between source content and model inference visible?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;A useful AI research assistant needs more than a search box and a summarization prompt.&lt;/p&gt;

&lt;p&gt;It needs a workflow that separates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Question definition
Query expansion
Source discovery
Result filtering
Original-source reading
Structured extraction
Human verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my implementation, Cloudsway SmartSearch handles source discovery while Reader processes selected webpages and supported PDFs.&lt;/p&gt;

&lt;p&gt;The more important design principle is provider-independent: every extracted claim should remain traceable to an original source, and the system should clearly identify information that still requires manual review.&lt;/p&gt;

&lt;p&gt;Search can make literature discovery faster.&lt;/p&gt;

&lt;p&gt;A trustworthy research workflow still depends on careful source selection, original-text verification, and human academic judgment.&lt;/p&gt;

&lt;p&gt;How are you currently organizing source discovery and verification in your research workflows?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>research</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Add a Real-Time Search Layer to an Agent Graph</title>
      <dc:creator>Marcus ma</dc:creator>
      <pubDate>Thu, 06 Aug 2026 03:53:48 +0000</pubDate>
      <link>https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd</link>
      <guid>https://dev.to/cloudsway/how-to-add-a-real-time-search-layer-to-an-agent-graph-29jd</guid>
      <description>&lt;h1&gt;
  
  
  How to Add a Real-Time Search Layer to an Agent Graph
&lt;/h1&gt;

&lt;p&gt;Agent frameworks make it easier to build systems that can plan tasks, call tools, maintain state, and decide what to do next.&lt;/p&gt;

&lt;p&gt;But a well-designed workflow can still produce a confidently structured wrong answer.&lt;/p&gt;

&lt;p&gt;The graph may execute exactly as expected while relying on information that is outdated, incomplete, duplicated, or difficult to verify. This becomes especially noticeable when an agent handles recent news, product information, market research, academic research, or other knowledge-intensive tasks.&lt;/p&gt;

&lt;p&gt;One way to address this is to treat real-time search as a shared evidence layer inside the agent graph.&lt;/p&gt;

&lt;p&gt;In this article, I will break down a practical architecture for doing that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; This article uses Cloudsway SmartSearch as one implementation example. The overall architecture is provider-agnostic and can work with other search APIs that return structured results and source metadata.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Difference Between an Agent Loop and an Agent Graph
&lt;/h2&gt;

&lt;p&gt;A basic tool-using agent often follows a loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reason
  ↓
Choose a tool
  ↓
Observe the result
  ↓
Decide what to do next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern works well for relatively simple tasks.&lt;/p&gt;

&lt;p&gt;As the number of tools, branches, and stopping conditions grows, however, the system prompt may begin carrying too much responsibility. It must describe the tools, maintain context, control branching, evaluate results, and decide when the task is complete.&lt;/p&gt;

&lt;p&gt;An agent graph makes that control flow explicit.&lt;/p&gt;

&lt;p&gt;Instead of asking one model to manage the entire process, the workflow can be divided into nodes such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
  ↓
Router
  ↓
Query Planner
  ↓
Search
  ↓
Source Verification
  ↓
Answer Generation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each node has a narrower responsibility.&lt;/p&gt;

&lt;p&gt;The router decides whether external information is required. The planner creates focused search queries. The search node retrieves evidence. The verifier evaluates the quality of that evidence. The final node generates an answer from the verified sources.&lt;/p&gt;

&lt;p&gt;If the evidence is insufficient, the graph can return to the query planner and run another search round.&lt;/p&gt;

&lt;p&gt;This structure makes the workflow easier to test, observe, and improve.&lt;/p&gt;

&lt;p&gt;Anthropic makes a useful distinction between &lt;a href="https://www.anthropic.com/engineering/building-effective-agents" rel="noopener noreferrer"&gt;workflows and agents&lt;/a&gt;: workflows follow predefined code paths, while agents have more control over their own processes and tool usage.&lt;/p&gt;

&lt;p&gt;Many production systems combine both approaches. Code defines the available paths and safety boundaries, while the model makes decisions inside those boundaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Search Should Be a Shared Layer
&lt;/h2&gt;

&lt;p&gt;A straightforward approach is to give every node access to its own search tool.&lt;/p&gt;

&lt;p&gt;That works, but it can create several problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different nodes may search for the same information repeatedly.&lt;/li&gt;
&lt;li&gt;Search results may use inconsistent formats.&lt;/li&gt;
&lt;li&gt;Citation metadata may be lost between nodes.&lt;/li&gt;
&lt;li&gt;One node may use recent sources while another uses outdated pages.&lt;/li&gt;
&lt;li&gt;Verification becomes difficult because evidence is scattered across the workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A shared search layer provides a cleaner alternative.&lt;/p&gt;

&lt;p&gt;Instead of passing unstructured snippets between nodes, the workflow can normalize each result into a common evidence object.&lt;/p&gt;

&lt;p&gt;For example:&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Evidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;relevance_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The search node creates these evidence objects, and the rest of the graph consumes them.&lt;/p&gt;

&lt;p&gt;A simplified agent state might look like this:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;search_required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Evidence&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;verification_status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this structure, research, analysis, verification, and answer-generation nodes all work with the same evidence format.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Search-Enabled Agent Graph
&lt;/h2&gt;

&lt;p&gt;The architecture can be broken into five main stages.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Decide Whether Search Is Required
&lt;/h3&gt;

&lt;p&gt;Not every task needs web access.&lt;/p&gt;

&lt;p&gt;Requests such as rewriting text, changing formatting, translating content, or summarizing information already provided by the user can usually bypass the search branch.&lt;/p&gt;

&lt;p&gt;Search becomes useful when the request depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recent information&lt;/li&gt;
&lt;li&gt;External facts&lt;/li&gt;
&lt;li&gt;Multiple independent sources&lt;/li&gt;
&lt;li&gt;Product or market changes&lt;/li&gt;
&lt;li&gt;Publication dates&lt;/li&gt;
&lt;li&gt;Explicit citations&lt;/li&gt;
&lt;li&gt;Information outside the model's internal knowledge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The router can produce a simple decision:&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="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The request depends on recent external information.&lt;/span&gt;&lt;span class="sh"&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 reduces unnecessary API calls and keeps simple tasks fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Break the Request Into Focused Queries
&lt;/h3&gt;

&lt;p&gt;Complex questions should rarely be sent to a search API as one broad query.&lt;/p&gt;

&lt;p&gt;Consider this request:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compare three AI search APIs for building a multilingual research agent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A planner could decompose it into smaller queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- API A multilingual search documentation
- API B supported languages and freshness filters
- API C citation and source metadata support
- independent comparisons of AI search APIs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The planner can also create separate queries for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different entities&lt;/li&gt;
&lt;li&gt;Different time periods&lt;/li&gt;
&lt;li&gt;Supporting and opposing evidence&lt;/li&gt;
&lt;li&gt;Product documentation&lt;/li&gt;
&lt;li&gt;Independent third-party evaluations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Independent searches can run in parallel before their results are combined.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Normalize the Search Results
&lt;/h3&gt;

&lt;p&gt;Search providers return different response formats.&lt;/p&gt;

&lt;p&gt;One API may return snippets, another may return generated summaries, and another may return extracted page content. Downstream nodes should not need custom logic for every provider.&lt;/p&gt;

&lt;p&gt;The search node should convert provider-specific responses into the shared evidence schema.&lt;/p&gt;

&lt;p&gt;Conceptually:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;normalize_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Evidence&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;result&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;relevance_score&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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&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;The exact field names will depend on the API you use.&lt;/p&gt;

&lt;p&gt;The important part is that normalization happens once, at the boundary between the search provider and the agent graph.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Verify the Evidence
&lt;/h3&gt;

&lt;p&gt;Retrieval and verification should be separate steps.&lt;/p&gt;

&lt;p&gt;A search result can be relevant while still being outdated, duplicated, promotional, or unsupported by other sources.&lt;/p&gt;

&lt;p&gt;A verification node can evaluate several dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Relevance:
Does the source address the actual question?

Freshness:
Is the publication date appropriate for the request?

Authority:
Is the source official, primary, or otherwise credible?

Diversity:
Do the results come from independent sources?

Agreement:
Do multiple sources support the same important claim?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The verifier should also be allowed to return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;insufficient_evidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important.&lt;/p&gt;

&lt;p&gt;A workflow that must produce an answer after every search round will eventually produce unsupported conclusions. A safer graph can refine the search queries, perform another retrieval round, or clearly state that reliable evidence was not found.&lt;/p&gt;

&lt;p&gt;The feedback path could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query Planner
      ↓
Search API
      ↓
Source Verification
      │
      └── Insufficient evidence ──→ Query Planner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Generate the Answer From Evidence and Metadata
&lt;/h3&gt;

&lt;p&gt;The answer-generation node should receive both the extracted content and the original source metadata.&lt;/p&gt;

&lt;p&gt;For example:&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="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example documentation page&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/docs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Relevant extracted information...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-30&lt;/span&gt;&lt;span class="sh"&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;The model can then connect claims to the URLs that support them.&lt;/p&gt;

&lt;p&gt;Citations should come directly from the search results. They should not be reconstructed after the answer has already been written.&lt;/p&gt;

&lt;p&gt;That reduces the risk of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invented URLs&lt;/li&gt;
&lt;li&gt;Citations pointing to unrelated pages&lt;/li&gt;
&lt;li&gt;Claims that are not supported by the linked source&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Cloudsway SmartSearch as the Search Node
&lt;/h2&gt;

&lt;p&gt;One implementation option is &lt;a href="https://docs.cloudsway.net/Smart_Search/Cloudsway_Smart_Search/overview/" rel="noopener noreferrer"&gt;Cloudsway SmartSearch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is designed for AI-agent retrieval and can return original source URLs together with summaries and other structured result formats. It also supports multilingual search and freshness filters for recent results.&lt;/p&gt;

&lt;p&gt;Inside an agent graph, it can fill the search-node role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query Planner
      ↓
Cloudsway SmartSearch
      ↓
Normalized Evidence Objects
      ↓
Source Verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the workflow does not need to depend directly on the provider's response format. The search adapter converts the response into the graph's shared evidence schema.&lt;/p&gt;

&lt;p&gt;This also makes the architecture easier to change later. The search provider can be replaced without rewriting the router, verifier, or answer-generation nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Search Snippets Are Not Enough
&lt;/h2&gt;

&lt;p&gt;Search results often provide enough information to identify useful sources, but a short snippet may not contain the details required for deeper analysis.&lt;/p&gt;

&lt;p&gt;This is especially common with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long documentation pages&lt;/li&gt;
&lt;li&gt;JavaScript-rendered websites&lt;/li&gt;
&lt;li&gt;Research papers&lt;/li&gt;
&lt;li&gt;PDF reports&lt;/li&gt;
&lt;li&gt;Tables and structured pages&lt;/li&gt;
&lt;li&gt;Pages containing important information inside images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In that situation, the workflow can separate source discovery from content extraction.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SmartSearch
  ↓
Discover relevant URLs
  ↓
Reader
  ↓
Extract clean page content
  ↓
Verification and analysis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.cloudsway.net/Smart_Search/Reader/overview/" rel="noopener noreferrer"&gt;Cloudsway Reader&lt;/a&gt; can convert static or JavaScript-rendered pages into formats such as text, Markdown, or HTML. It also supports content from PDFs and images.&lt;/p&gt;

&lt;p&gt;This creates a useful division of responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search&lt;/strong&gt; finds the most relevant sources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reader&lt;/strong&gt; retrieves and structures the full content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifier&lt;/strong&gt; evaluates whether the evidence is reliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generator&lt;/strong&gt; produces the cited answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Provider-Agnostic Workflow Example
&lt;/h2&gt;

&lt;p&gt;The complete workflow can be represented as conceptual Python:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_request&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_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verification_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_started&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# 1. Route the request
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;route_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_without_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_request&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;state&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Plan focused queries
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;plan_queries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Search and normalize
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;raw_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;normalize_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Verify the collected evidence
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verification_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;verify_evidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Retry when the evidence is insufficient
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verification_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;insufficient_evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;refined_queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;refine_queries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;previous_queries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&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;for&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;refined_queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;raw_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;normalize_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verification_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;verify_evidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 6. Generate an answer grounded in the evidence
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_cited_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;verification_status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verification_status&lt;/span&gt;&lt;span class="sh"&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="n"&gt;state&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is intentionally simplified.&lt;/p&gt;

&lt;p&gt;A production system would also need to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timeouts&lt;/li&gt;
&lt;li&gt;Rate limits&lt;/li&gt;
&lt;li&gt;Duplicate URLs&lt;/li&gt;
&lt;li&gt;Query budgets&lt;/li&gt;
&lt;li&gt;Search result caching&lt;/li&gt;
&lt;li&gt;Unsafe or untrusted content&lt;/li&gt;
&lt;li&gt;Source-domain restrictions&lt;/li&gt;
&lt;li&gt;Maximum retry counts&lt;/li&gt;
&lt;li&gt;Logging and tracing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core architectural idea remains the same: search results should enter the graph as structured evidence rather than untracked text.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Check Before Shipping
&lt;/h2&gt;

&lt;p&gt;Before deploying a search-enabled agent, I would test the following cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Search routing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does the agent avoid search for simple rewriting tasks?&lt;/li&gt;
&lt;li&gt;Does it activate search for recent or citation-heavy questions?&lt;/li&gt;
&lt;li&gt;Can users explicitly request or disable search?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Query planning
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does the planner generate specific queries?&lt;/li&gt;
&lt;li&gt;Does it cover different aspects of a complex question?&lt;/li&gt;
&lt;li&gt;Does it avoid repeatedly searching for the same information?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Evidence quality
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Are duplicate pages removed?&lt;/li&gt;
&lt;li&gt;Are publication dates preserved?&lt;/li&gt;
&lt;li&gt;Are original URLs available to downstream nodes?&lt;/li&gt;
&lt;li&gt;Can the workflow distinguish official documentation from commentary?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verification
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Can the verifier reject weak evidence?&lt;/li&gt;
&lt;li&gt;Can it request another search round?&lt;/li&gt;
&lt;li&gt;Does it check important claims against independent sources?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Answer generation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Can each major claim be traced back to a source?&lt;/li&gt;
&lt;li&gt;Are citations attached to the correct statements?&lt;/li&gt;
&lt;li&gt;Does the answer acknowledge missing or conflicting evidence?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;Agent frameworks solve orchestration problems. They help models plan tasks, call tools, pass state between nodes, and control execution paths.&lt;/p&gt;

&lt;p&gt;Real-time search solves a different part of the system: access to current and verifiable evidence.&lt;/p&gt;

&lt;p&gt;Treating search as a shared layer gives every node access to consistent source objects, reduces duplicated retrieval, and makes verification easier to implement.&lt;/p&gt;

&lt;p&gt;The resulting graph looks less like a model with a search button and more like a research pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
  ↓
Route
  ↓
Plan
  ↓
Retrieve
  ↓
Verify
  ↓
Answer with citations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That pattern can be applied to research agents, enterprise copilots, market-analysis tools, technical-support systems, and other workflows where the quality of the answer depends on the quality of the evidence.&lt;/p&gt;

&lt;p&gt;How are you handling retrieval and source verification in your agent workflows?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>api</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
