DEV Community

Marcus ma
Marcus ma

Posted on • Originally published at cloudsway.ai

How I Built a Source-Backed Research Paper Search Workflow

How I Built a Source-Backed Research Paper Search Workflow

Searching for research papers sounds straightforward when you already know the title, author, DOI, or exact academic terminology.

The harder cases begin with incomplete information.

You may only remember:

  • A research question
  • An experimental result
  • A rough description of the method
  • The relationship between two variables
  • A paper you saw months ago but cannot name

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.

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.

The resulting workflow looks like this:

Research Question
      ↓
Query Expansion
      ↓
Search API
      ↓
Result Filtering
      ↓
Original Source Reading
      ↓
Research Matrix
      ↓
Manual Verification
Enter fullscreen mode Exit fullscreen mode

Disclosure: 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.

The Problem With Searching by Exact Keywords

Academic concepts are often described using multiple terms.

For example, a researcher studying communication between AI agents might search for:

multi-agent communication frequency
Enter fullscreen mode Exit fullscreen mode

But related papers may use phrases such as:

agent coordination
cooperative agents
decentralized collaboration
message passing
team communication
coordination overhead
Enter fullscreen mode Exit fullscreen mode

A single keyword query can miss relevant work simply because the authors used different vocabulary.

Natural-language search provides another starting point.

Instead of trying to predict the exact terminology, the researcher can describe the underlying problem:

Find recent research investigating whether increasing communication between AI agents always improves collaborative task performance.

This query provides more context than a short keyword string.

It contains:

  • The research domain: multi-agent systems
  • The independent variable: communication frequency
  • The outcome: collaborative performance
  • The suspected relationship: more communication may not always help
  • A recency requirement: recent research

A search-enabled research assistant can use these signals to create several narrower queries rather than depending on one exact phrase.

Step 1: Define the Research Question

Before calling a search API, the workflow should structure the user's question.

A useful research-question object might contain:

research_question = {
    "topic": "multi-agent coordination",
    "independent_variable": "communication frequency",
    "outcome": "collaborative task performance",
    "research_interest": "whether more communication always improves performance",
    "date_range": "recent research",
}
Enter fullscreen mode Exit fullscreen mode

The fields will vary by discipline, but the general principle is consistent: extract the concepts that should guide retrieval.

For empirical research, useful fields may include:

  • Population or system
  • Intervention or independent variable
  • Outcome
  • Method
  • Context
  • Time range
  • Language
  • Publication type

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.

Step 2: Generate Query Variations

The next stage expands the research question into multiple search formulations.

For example:

queries = [
    "multi-agent communication frequency collaborative performance research",
    "agent communication overhead coordination experiments",
    "does more communication improve multi-agent cooperation",
    "decentralized agent coordination message frequency study",
    "limited communication multi-agent task performance paper",
]
Enter fullscreen mode Exit fullscreen mode

These queries cover different ways researchers might describe the same problem.

A more advanced planner could generate separate query categories:

query_groups = {
    "direct": [
        "multi-agent communication frequency performance",
    ],
    "alternative_terms": [
        "agent message passing coordination quality",
        "cooperative agents communication overhead",
    ],
    "contradictory_evidence": [
        "excessive communication reduces multi-agent performance",
        "limited communication improves agent collaboration",
    ],
    "source_specific": [
        "site:arxiv.org multi-agent communication coordination",
        "site:acm.org multi-agent communication performance",
    ],
}
Enter fullscreen mode Exit fullscreen mode

Searching for contradictory evidence is especially useful.

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.

Step 3: Search Across Public Research Sources

A search API can act as the discovery layer.

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.

Possible destinations include:

  • arXiv
  • PubMed
  • Semantic Scholar
  • Conference websites
  • University repositories
  • Research-group websites
  • Journal landing pages
  • Publicly accessible PDFs

In this workflow, I use Cloudsway SmartSearch as the search layer.

The search response should be normalized into a consistent format before other parts of the application process it.

For example:

from typing import TypedDict


class SearchResult(TypedDict):
    title: str
    url: str
    summary: str
    published_at: str | None
    source_domain: str | None
    query: str
Enter fullscreen mode Exit fullscreen mode

The provider-specific response can then be converted into this schema:

def normalize_search_result(result: dict, query: str) -> SearchResult:
    return {
        "title": result.get("title", ""),
        "url": result.get("url", ""),
        "summary": result.get("summary", ""),
        "published_at": result.get("published_at"),
        "source_domain": result.get("source"),
        "query": query,
    }
Enter fullscreen mode Exit fullscreen mode

This keeps the rest of the workflow independent from the search provider's exact response format.

Step 4: Filter and Deduplicate the Results

The same paper may appear in several places:

  • A preprint platform
  • A journal page
  • A university repository
  • An author's personal website
  • A conference page
  • A secondary article discussing the paper

Without deduplication, an application may mistakenly treat these pages as separate pieces of evidence.

A basic deduplication process can compare:

  • Normalized titles
  • DOI values, when available
  • Author names
  • Publication year
  • Canonical URLs
  • Similarity between abstracts

Conceptually:

def normalize_title(title: str) -> str:
    return " ".join(
        title.lower()
        .replace(":", "")
        .replace("-", " ")
        .split()
    )


def deduplicate(results: list[SearchResult]) -> list[SearchResult]:
    unique_results = []
    seen_titles = set()

    for result in results:
        normalized = normalize_title(result["title"])

        if normalized and normalized not in seen_titles:
            seen_titles.add(normalized)
            unique_results.append(result)

    return unique_results
Enter fullscreen mode Exit fullscreen mode

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

After deduplication, results can be ranked using criteria such as:

Relevance to the research question
Publication date
Source authority
Availability of the original paper
Presence of an abstract or full text
Methodological relevance
Language
Enter fullscreen mode Exit fullscreen mode

The workflow should also distinguish between source types.

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

Step 5: Read the Original Source

A title and search snippet are not enough for a literature review.

They may help determine whether a paper is worth opening, but they rarely provide sufficient detail about:

  • Research design
  • Sample or dataset
  • Experimental environment
  • Variables
  • Evaluation metrics
  • Main findings
  • Limitations
  • Boundary conditions

The workflow therefore needs a separate reading stage.

In this implementation, Cloudsway Reader processes selected webpages and supported PDF content after SmartSearch discovers the sources.

The separation is useful:

SmartSearch
  ↓
Find potentially relevant sources
  ↓
Reader
  ↓
Process selected original content
  ↓
Structured extraction
Enter fullscreen mode Exit fullscreen mode

Search is responsible for discovery.

Reader is responsible for turning the selected source into usable context.

The application can then ask the extraction model to return a structured record:

class PaperRecord(TypedDict):
    title: str
    source_url: str
    research_question: str
    method: str
    dataset_or_sample: str
    metrics: list[str]
    main_findings: list[str]
    limitations: list[str]
    verification_notes: list[str]
Enter fullscreen mode Exit fullscreen mode

An extraction prompt might look like this:

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.
Enter fullscreen mode Exit fullscreen mode

The final instruction matters.

A research assistant should distinguish between information that appears in the source and conclusions inferred by the model.

Step 6: Build a Research Matrix

The extracted paper records can be stored in a research matrix.

For example:

Paper Source Method Dataset or Setting Main Finding Limitations Verification
Paper A Original URL Experimental study Multi-agent simulation Finding summary Reported limitations Needs full-text review
Paper B Original URL Benchmark evaluation Collaborative task environment Finding summary Limited task diversity Abstract verified
Paper C Original URL Theoretical analysis Decentralized agents Finding summary No empirical test Full source reviewed

The research matrix makes it easier to:

  • Compare methods
  • Identify conflicting findings
  • Track missing information
  • Detect repeated datasets
  • Organize papers by theme
  • Preserve source links
  • Prepare a literature review

A simple data structure could look like:

research_matrix = []

for paper in selected_papers:
    record = read_and_extract(paper)
    research_matrix.append(record)
Enter fullscreen mode Exit fullscreen mode

This matrix should not be treated as the final literature review.

It is an intermediate research artifact that helps a human researcher understand and verify the source set.

Step 7: Keep Claims Connected to Sources

One of the biggest risks in AI-assisted research is losing the connection between a generated statement and its original source.

For example, the system might generate:

Increased communication improves coordination only up to a certain threshold.

That statement should not exist in the final output without metadata showing:

  • Which paper reported it
  • Where the paper was found
  • Whether the full text was read
  • Whether the finding came from the authors or was inferred
  • Whether another source reported a conflicting result

A claim object can preserve this connection:

claim = {
    "text": "Increased communication improved coordination only up to a threshold.",
    "source_title": "Example Paper",
    "source_url": "https://example.org/paper",
    "evidence_type": "reported finding",
    "verification_status": "full text reviewed",
}
Enter fullscreen mode Exit fullscreen mode

The final synthesis stage should consume these claim objects rather than disconnected summaries.

This reduces the likelihood of citations being added after the answer has already been generated.

Step 8: Handle Missing or Incomplete Evidence

The workflow must be allowed to return incomplete results.

A search API cannot guarantee that every important paper will be found. Some papers may be:

  • Behind paywalls
  • Missing from public indexes
  • Published under unexpected terminology
  • Available only in a different language
  • Incorrectly dated
  • Poorly represented by search snippets
  • Accessible only through metadata pages

The workflow should therefore support statuses such as:

source_found
full_text_available
abstract_only
metadata_only
requires_manual_access
insufficient_evidence
Enter fullscreen mode Exit fullscreen mode

A result with limited access might be stored as:

{
    "title": "Example Research Paper",
    "url": "https://example.org/paper",
    "access_status": "abstract_only",
    "extraction_status": "partial",
    "manual_review_required": True,
}
Enter fullscreen mode Exit fullscreen mode

This is more reliable than allowing the model to fill in missing information.

A Simplified End-to-End Workflow

The complete process can be represented with provider-agnostic pseudocode:

def build_research_matrix(question: str, search_client, reader_client):
    # 1. Structure the research question
    research_scope = parse_research_question(question)

    # 2. Create several query variations
    queries = generate_query_variations(research_scope)

    # 3. Search for public research sources
    search_results = []

    for query in queries:
        raw_results = search_client.search(query=query)

        for result in raw_results:
            search_results.append(
                normalize_search_result(result, query)
            )

    # 4. Remove likely duplicates
    unique_results = deduplicate(search_results)

    # 5. Rank and select promising sources
    selected_results = rank_and_select(
        results=unique_results,
        research_scope=research_scope,
    )

    # 6. Read and extract information
    research_matrix = []

    for result in selected_results:
        source_content = reader_client.read(url=result["url"])

        record = extract_paper_record(
            content=source_content,
            source_url=result["url"],
        )

        research_matrix.append(record)

    # 7. Mark records requiring human verification
    return add_verification_status(research_matrix)
Enter fullscreen mode Exit fullscreen mode

A production version would also need:

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

What This Workflow Can and Cannot Do

This workflow can help with:

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

It cannot guarantee:

  • Complete literature coverage
  • Access to every paywalled paper
  • Correct interpretation of every method
  • Accurate citation formatting
  • Identification of every duplicate
  • Elimination of hallucinated conclusions
  • Replacement of expert academic judgment

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.

Practical Checks Before Using the Results

Before using an AI-generated research matrix in a paper or report, I would check:

Source identity

  • Is this the original paper?
  • Is it a preprint, accepted manuscript, or final version?
  • Are the title, authors, and publication year correct?

Methodology

  • Was the method extracted from the full paper or only the abstract?
  • Are the sample and dataset accurately described?
  • Are causal claims supported by the research design?

Findings

  • Does the generated summary match the authors' wording?
  • Were limitations or boundary conditions omitted?
  • Are statistically insignificant findings being overstated?

Coverage

  • Were several query variations used?
  • Were references from key papers reviewed?
  • Were different languages and source categories considered?
  • Could terminology differences have excluded relevant papers?

Traceability

  • Does every important claim include a source URL?
  • Can the original passage be located?
  • Is the distinction between source content and model inference visible?

Final Takeaway

A useful AI research assistant needs more than a search box and a summarization prompt.

It needs a workflow that separates:

Question definition
Query expansion
Source discovery
Result filtering
Original-source reading
Structured extraction
Human verification
Enter fullscreen mode Exit fullscreen mode

In my implementation, Cloudsway SmartSearch handles source discovery while Reader processes selected webpages and supported PDFs.

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.

Search can make literature discovery faster.

A trustworthy research workflow still depends on careful source selection, original-text verification, and human academic judgment.

How are you currently organizing source discovery and verification in your research workflows?

Top comments (0)