All skills
agents365-ai avatar

/scholar-deep-research

@72ee04b

Use when the user asks for a literature review, academic deep dive, research report, state-of-the-art survey, topic scoping, comparative analysis of methods/papers, grant background, or any request that needs multi-source scholarly evidence with citations. Also trigger proactively when a user question clearly requires academic grounding (e.g. "what's known about X", "compare approach A vs B in the literature", "summarize the field of Y"). Runs an 8-phase (Phase 0..7), script-driven research workflow across 7 federated sources (OpenAlex, arXiv, Crossref, PubMed, DBLP, bioRxiv, Exa) with optional Semantic Scholar / Brave MCP enrichment, with deduplication, transparent ranking, dual-backend citation chasing (OpenAlex + Semantic Scholar), self-critique, and structured report output with verifiable citations.

Use this Skill: https://skilld.dev/gh/agents365-ai/365-skills/scholar-deep-research

This session only. Nothing lands on disk.

referencesagent_promptsphase3_deep_read.md

≈2.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Phase 3 — Parallel Deep-Read Agent Prompt Template

This file is loaded on demand by the host LLM during Phase 3, after skim_papers.py has assigned tiers. The host dispatches one agent per tier=deep paper, in parallel waves of 8–10 (see "Wave sizing" below). Each agent runs the prompt below in isolation and writes evidence back to research_state.json via the shared CLI — the host's main context only sees the one-line return.

Why parallel agents (and not a single async script)

Phase 3 is reasoning-heavy, not I/O-heavy: the agent has to read the paper, decide what counts as a finding vs. background, link claims to evidence, and judge limitations. Compressing that into a deterministic Python loop loses the reasoning. Compressing 50 papers' worth of full-text into the host's main context wastes tokens. Parallel agents put each paper's reasoning in its own ~200-token context bubble; only the structured evidence record returns.

Wave sizing

  • Default: waves of 8–10 agents per dispatch message.
  • Why batch: more than ~10 simultaneous tool_use blocks risk host-side rate limits and back-pressure. Smaller waves also let you abort cheaply if the first 1–2 results look wrong.
  • Total cost is roughly linear in deep-tier count, so trim aggressively at triage time (skim_papers.py --deep-ratio 0.3) when budget is tight.

Per-agent prompt (copy-paste; fill in the ${...} placeholders)

You are a Phase 3 deep-read agent for the scholar-deep-research skill.

## Your single paper

paper_id   : ${paper_id}        # e.g. "doi:10.1038/s41586-020-2649-2"
title      : ${title}
doi        : ${doi}             # may be null — fall back to pdf_url
pdf_url    : ${pdf_url}         # may be null
pdf_path   : ${pdf_path}        # may be null. If set AND file exists, use it
                                # directly — prefetch_pdfs.py already pulled
                                # the PDF, no network call needed.
abstract   : ${abstract}        # already in state; use as a fallback if PDF fetch fails

## Research question (Phase 0)

${question}

## What you must do

1. Get the full text. Try in this order, stopping at the first that yields >2000 chars:
   a. **If `pdf_path` is provided AND points at an existing file** (`prefetch_pdfs.py` ran):
      ```
      python scripts/extract_pdf.py --input '${pdf_path}' --output /tmp/${safe_id}.md
      ```
      No network call — fastest path. **Always prefer this when available.**
   b. `python scripts/extract_pdf.py --doi '${doi}' --output /tmp/${safe_id}.md`
      (uses the paper-fetch skill's 5-source OA chain when installed)
   c. `python scripts/extract_pdf.py --url '${pdf_url}' --output /tmp/${safe_id}.md`
   d. **Last resort — host-native web fetch.** If your host runtime has
      a `WebFetch` tool (Claude Code, OpenCode) or equivalent, try
      fetching the paper's landing page directly:
      `WebFetch(url=<pdf_url or doi.org/${doi}>)`. Publisher landing
      pages often expose the abstract and key findings in HTML even
      when the PDF is gated. Record evidence with `--depth shallow`
      and prefix `--method` with `webfetch_landing_page:` (same prefix
      convention as failure modes A/B below) so downstream consumers
      know the coverage is partial. Many publishers (IEEE Xplore,
      Elsevier) return 418/403 to WebFetch — when that happens, fall
      through to (e).
   e. If a..d all fail: write evidence_unavailable (see "Failure mode" below) and stop.

   If `pdf_path` is set but the file is missing (cache wiped between prefetch
   and dispatch), fall through to (b). Do **not** silently skip — that path
   is what `pdf_status='failed'` already records, and re-attempting via (b)
   gives the paper one more chance with a different transport.

   **Extraction engine.** `extract_pdf.py` defaults to `--engine auto`: pypdf
   first, auto-upgrading to docling when the pypdf result looks scanned/sparse
   (and docling is installed via `pip install docling`). Output is markdown
   when docling kicks in, plain text otherwise — both readable for evidence
   extraction. The response envelope reports `engine` and `format` so you
   know what you got. Force `--engine docling` for multi-column or
   table-heavy PDFs where pypdf interleaves columns.

2. Read the extracted text. Extract per-paper evidence covering:
   - method            : 1 sentence on the experimental/computational approach
   - findings          : 3–5 bullets, each with a section/page anchor where possible
                         (e.g. "ABE7.10 corrects 65% of dystrophin in mdx mice (Fig 3a)")
   - limitations       : what the paper itself acknowledges + what you noticed
   - relevance         : 1–2 sentences on how this moves the question forward

3. Write evidence back to state. **Prefer the JSON path** — it skips
   the multi-quote shell escape dance that bites when findings contain
   single quotes, unicode, or section headers:

   ```bash
   echo '${json_payload}' | python scripts/research_state.py \
     --state ${state_path} evidence --id '${paper_id}' --from-json -

Where ${json_payload} is {"method": "...", "findings": ["...", ...], "limitations": "...", "relevance": "...", "depth": "full"}. JSON's depth wins over the --depth flag.

Structured mode is still supported for short single invocations:

python scripts/research_state.py --state ${state_path} evidence \
  --id '${paper_id}' --depth full \
  --method '${method}' \
  --findings '${finding_1}' '${finding_2}' '${finding_3}' \
  --limitations '${limitations}' \
  --relevance '${relevance}'

The CLI is exclusive-locked — N agents writing concurrently are serialized automatically; no coordination needed.

  1. Return EXACTLY one JSON line to the host (no prose):
    {"paper_id": "${paper_id}", "status": "ok", "evidence_chars": <int>, "method_brevity": <int>}

Failure modes

There are two escape hatches that count as valid deep-tier coverage so a single bad paper does not block the whole workflow. Both keep depth='shallow' and prefix evidence.method with a magic string the gate recognises.

Failure mode A — full text unreachable

Paywall, exhausted OA chain, scanned PDF, dead link. The PDF was not read.

python scripts/research_state.py --state ${state_path} evidence \
  --id '${paper_id}' --depth shallow \
  --method 'evidence_unavailable: ${reason_code}' \
  --findings 'No full text available; abstract excerpt: ${abstract_excerpt}' \
  --limitations 'Marked evidence_unavailable; do not cite as sole source.' \
  --relevance 'Pending source recovery.'

Reason codes: paywall_no_oa, pdf_fetch_failed, scanned_no_ocr, dead_link.

Return:

{"paper_id": "${paper_id}", "status": "evidence_unavailable", "reason": "${reason_code}"}

Failure mode B — PDF read but topic mismatch

The PDF was extracted in full and you read it, but the paper turned out to be off-topic — Phase 2 ranking surfaced it on surface-token overlap (e.g. it shares words like "evaluation" or "LLM" with the question but is actually about a different problem). Record what little is usable and tag the mismatch so the synthesis can treat the paper as a contrast/baseline rather than a primary source. Do not silently mark it as depth='full' — the relevance flag matters for the report.

python scripts/research_state.py --state ${state_path} evidence \
  --id '${paper_id}' --depth shallow \
  --method 'topic_mismatch: ${one_sentence_what_paper_is_actually_about}' \
  --findings '${useful_observation_1}' '${useful_observation_2}' \
  --limitations 'Off-topic vs Phase 0 question; cite as contrast/baseline only, not primary evidence.' \
  --relevance '${one_sentence_what_the_paper_can_anchor_in_the_report}'

Return:

{"paper_id": "${paper_id}", "status": "topic_mismatch", "evidence_chars": <int>}

Constraints

  • DO NOT call MCP tools. Phase 3 must run offline-first.
  • DO NOT modify any state field other than papers[<id>].evidence and papers[<id>].depth. The CLI enforces this; do not try to work around it.
  • DO NOT chain into Phase 4 (citation chase) or Phase 5 (synthesis). One paper, one evidence record, one return.
  • Findings MUST be specific (numbers, conditions, comparisons), not generic ("the authors found that base editing works"). Generic findings are worse than no finding — they silently inflate G4's coverage count without contributing to the report.

## Host-side dispatch (single message, multiple Agent tool_use blocks)

After `skim_papers.py` reports `counts.deep`, the host LLM:

1. Loads this template once.
2. For each `paper_id` with `tier == "deep"`, instantiates the prompt with the per-paper substitutions.
3. Sends a **single message containing all N tool_use blocks** so they fan out in parallel. (In Claude Code: one assistant message with N `Agent` tool calls; subagent_type `general-purpose`.)
4. After the wave returns, runs:

```bash
python scripts/research_state.py --state ${state_path} advance --to 4 --check-only

If deep_tier_full_evidence is still failing, dispatch a second wave for the missing ids only.

Recovery after a partial wave

If 7/10 agents returned status:"ok" and 3 returned status:"evidence_unavailable" (or timed out), do not retry the failed three immediately. First inspect state.papers[<id>].evidence:

  • evidence.method starts with evidence_unavailable: → genuine OA chain failure. Either accept the shallow record or open the URL manually and feed it through extract_pdf.py --input <local.pdf>.
  • No evidence field at all → agent crashed before write. Re-dispatch one agent for that id.

The state CLI is idempotent on evidence (re-writing the same id overwrites the record), so re-dispatching is safe.

Source: SKILL.md on GitHub

1 warning4mo3 checks · Risk SAFE
  • Gen Agent Trust Hub4mo

    This skill is a robust academic research tool that automates literature reviews across multiple scholarly databases. It uses strict input validation for paper identifiers and handles sensitive API keys through environment variables. While the skill executes a local script from a companion 'paper-fetch' skill to download PDFs, this is a standard design pattern within the author's ecosystem. It also processes external PDF text, which carries a minor risk of indirect prompt injection common to all document-reading agents.

  • Socket4mo

    No alerts

  • Snyk4mo

    Risk: MEDIUM · 1 issue

Signed by skilld at 72ee04b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 11 hours ago.

Activeupdated 3 weeks ago
homepage
https://github.com/Agents365-ai/365-skills
platforms
[macos, linux, windows]
Other metadata
compatibility
Requires Python 3.9+ with httpx and pypdf (see requirements.txt). Optional: `pip install docling` to enable layout-aware markdown PDF extraction (`extract_pdf.py --engine docling`); auto-used as a fallback for scanned/sparse PDFs. Works offline-first (no MCP required) but enriches with Semantic Scholar / Brave MCP tools when available.
metadata
{
  "openclaw": {
    "requires": {
      "bins": [
        "python3"
      ]
    },
    "emoji": "🔬"
  },
  "hermes": {
    "tags": [
      "research",
      "literature-review",
      "academic",
      "papers",
      "citations",
      "survey"
    ],
    "category": "research"
  },
  "pimo": {
    "tags": [
      "research",
      "literature-review",
      "academic"
    ],
    "category": "research"
  },
  "author": "Agents365-ai",
  "version": "0.17.0"
}

README badge

README badge for agents365-ai/365-skills/scholar-deep-research