Skip to main content

scholar-sidekick-python

Resolve scholarly identifiers (DOI including shortDOI aliases, PMID, PMCID, ISBN, arXiv, ISSN, ADS bibcode, WHO IRIS URL) into formatted citations (10,000+ CSL styles) and bibliography exports (BibTeX, RIS, EndNote, CSV…), verify a claimed citation against the record its identifier actually resolves to, and audit a reference list of any length for fabricated and retracted entries — from Python via the `scholar-sidekick` package. Wraps the public REST API; needs Python ≥3.9 but no API key for the free tier. Use when the agent runs Python (a script, a notebook, a data pipeline) and the user wants to cite, export, verify, or audit references by DOI, PMID, PMCID, ISBN, arXiv ID, ISSN, ADS bibcode, or WHO IRIS URL — especially a bibliography longer than 25 entries, which this client chunks and paces automatically.

معلومات المصدر

المستودع
mlava/scholar-sidekick-skills
آخر نشاط في المصدر
١ سبتمبر ٢٠٢٦ في ٢٣:٣١
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
scholar-sidekick-python
description
Resolve scholarly identifiers (DOI including shortDOI aliases, PMID, PMCID, ISBN, arXiv, ISSN, ADS bibcode, WHO IRIS URL) into formatted citations (10,000+ CSL styles) and bibliography exports (BibTeX, RIS, EndNote, CSV…), verify a claimed citation against the record its identifier actually resolves to, and audit a reference list of any length for fabricated and retracted entries — from Python via the `scholar-sidekick` package. Wraps the public REST API; needs Python ≥3.9 but no API key for the free tier. Use when the agent runs Python (a script, a notebook, a data pipeline) and the user wants to cite, export, verify, or audit references by DOI, PMID, PMCID, ISBN, arXiv ID, ISSN, ADS bibcode, or WHO IRIS URL — especially a bibliography longer than 25 entries, which this client chunks and paces automatically.
version
1.0.0
author
Scholar Sidekick
license
MIT
metadata
{"tags":["citations","bibliography","doi","pmid","arxiv","csl","bibtex","ris","retraction","citation-verification","research","python","pandas","notebook","systematic-review"],"related_skills":["scholar-sidekick-api","scholar-sidekick-cli","scholar-sidekick-mcp"],"openclaw":{"emoji":"🐍","homepage":"https://scholar-sidekick.com","requires":{"bins":"[Truncated]"}}}
# Scholar Sidekick (Python) — Cite, verify and audit citations from Python Turn a scholarly identifier into a formatted citation, a bibliography file, or a fabrication check, using the `scholar-sidekick` package. It is a thin, typed client over the public Scholar Sidekick REST API. **No API key required** for the free, rate-limited tier. Results come back as objects, so you never parse text output. > Sibling skills, same API underneath: use **`scholar-sidekick-api`** when the agent only has > `curl`, **`scholar-sidekick-cli`** for a Node ≥20 terminal, or **`scholar-sidekick-mcp`** when an > MCP host is connected. This skill is the Python path. ## When to Use - The agent runs Python — a script, a notebook, or a data pipeline — and the user has an identifier (DOI, PMID, PMCID, ISBN, arXiv, ISSN, ADS bibcode, WHO IRIS URL; shortDOI aliases like `10/aabbe` accepted). - "Is this citation real / did you make it up?" — `verify()` compares the claimed title against the record the identifier resolves to. - "Check every reference in this list" — **especially a list longer than 25 entries.** `audit_bibliography()` chunks and paces itself; hand-rolled loops hit the rate limit. - The result feeds further Python work: a DataFrame, a report, a CI gate. - Do NOT use this to *search* for papers by topic. That is discovery; this assumes you already have an identifier. **This client does not cover everything the REST API does.** There is no standalone retraction check, no open-access check, no style search, and no bare identifier resolution. For those, use the `scholar-sidekick-api` or `scholar-sidekick-cli` skill. Retraction screening *is* available, but only inside an audit. ## Install Published on PyPI as `scholar-sidekick` (import name `scholar_sidekick`). Requires Python ≥ 3.9. ```bash pip install scholar-sidekick pip install 'scholar-sidekick[pandas]' # adds report.to_dataframe() ``` ## API surface | Method | Purpose | Returns | |---|---|---| | `format()` | Resolve identifiers and format them | `FormatResult` (`.text`, `.html`) | | `format_items()` | Format already-resolved CSL-JSON items | `FormatItemsResult` (`.output`) | | `export()` | Export to a bibliography file format | `str` — the file body | | `verify()` | Check one claimed citation against the resolved record | `VerifyResult` | | `audit()` | Audit up to 25 references in one call | `AuditReport` | | `audit_bibliography()` | Audit any number, chunked and paced | `AuditReport` | | `health()` | Service liveness | `dict` | `AsyncScholarSidekick` mirrors every method; only the awaiting differs. ## Procedure ### Verify one citation (catch fabrication) ```python from scholar_sidekick import ScholarSidekick client = ScholarSidekick() result = client.verify( title="Quantum entanglement in biological systems", doi="10.1038/nphys1170", ) print(result.verdict, result.confidence) ``` `title` is required, plus at least one identifier keyword (`doi`, `pmid`, `pmcid`, `isbn`, `arxiv`, `issn`, `ads`, `who_iris_url`). Optional: `authors`, `year`, `container`. | verdict | meaning | |---|---| | `matched` | the claimed citation agrees with the resolved record | | `mismatch` | the identifier resolves to a **different** work — the dominant fabrication pattern (real DOI, invented title; Topaz et al., Lancet 2026) | | `ambiguous` | a discrepancy a human should read; not an accusation | | `not_found` | no record found in the registries searched | Two rules that matter: - A `mismatch` is **returned as a value, never raised.** It is the expected outcome for a fabricated citation, and the reason this method exists. - `not_found` is **not** proof of fabrication. Standards documents, software repositories, model cards and institutional reports are often real but absent from scholarly registries. Report it as "could not confirm". Do not use `format()` to answer "is this real?". A fabricated citation carries a real, resolvable DOI, so formatting it succeeds and proves nothing. Only `verify()` compares the claimed title. ### Audit a whole bibliography ```python claims = [ {"title": "Attention is all you need", "arxiv": "1706.03762"}, {"title": "Ileal-lymphoid-nodular hyperplasia…", "doi": "10.1016/S0140-6736(97)11096-0"}, # …any number of entries ] report = client.audit_bibliography( claims, progress=lambda done, total: print(f"{done}/{total} chunks"), ) print(report.summary) # total / matched / mismatch / ambiguous / not_found / errored / retracted for entry in report.needs_review: print(entry.input_index, entry.verdict, entry.claimed_title, entry.resolved_title) ``` - **`entry.input_index` is the 0-based position in the list you passed in**, whatever the chunking did. Use it to point at the right reference. - Each entry also carries `retracted`, `has_concern`, `has_corrections`, and `notices` — retraction screening is **on by default**. Pass `checks=[]` to skip it. `"retraction"` is the only accepted check value. - A failed chunk is recorded, not raised, so one transient upstream error does not discard several minutes of completed work: ```python if not report.complete: for failure in report.errors: print(f"entries {failure.start_index}-{failure.end_index} failed: {failure.error}") ``` Pass `stop_on_error=True` to raise on the first failed chunk instead. **Claim dicts are strict — the server rejects unknown keys.** Allowed: `title`, `authors` (`[{"family": …, "given": …}]`, max 50), `year` (int), `container`, and the identifiers `doi`, `pmid`, `pmcid`, `isbn`, `arxiv`, `issn`, `ads`, `whoIrisUrl` (note the camelCase). Strip anything else before sending. **Two input kinds, and the wrong one fails.** Default `kind="claims"` expects dicts. For raw prose reference strings — a pasted reference list with no parsed title — pass `kind="references"`, which verifies by containment instead of title comparison: ```python report = client.audit_bibliography(reference_strings, kind="references") ``` With pandas installed: `report.to_dataframe()`. Use `audit()` instead of `audit_bibliography()` only when you have 25 entries or fewer *and* want a single call. `audit()` also accepts a raw `bibliography=` string (BibTeX / RIS / CSL-JSON) which the server parses; pass `format=` to override auto-detection. This audits citation **identity**. It does not check whether a source supports the claim it is cited for. ### Format and export ```python print(client.format(text="10.1038/nphys1170", style="vancouver").text) with open("refs.bib", "w") as fh: fh.write(client.export(text="10.1038/nphys1170 PMID:30049270", format="bibtex")) ``` - `format()` takes exactly one of `text=` (a blob the API detects identifiers in) or `lines=` (a sequence). Passing both, or neither, raises `ValueError`. - `style`: `vancouver` (default), `ama`, `apa`, `ieee`, `cse`, or any CSL style ID (`chicago-author-date`, `nature`, `the-lancet`, …). - `export()` formats: `bibtex`, `ris`, `csv`, `csl`, `endnote-xml`, `endnote-refer`, `refworks`, `medline`, `zotero-rdf`, `txt`. It returns the file body as a string — write it yourself. ## Errors Exceptions are chosen by the API's stable error `code`, not by HTTP status. ```python from scholar_sidekick import APIError, RateLimitError, UpstreamError try: client.format(text="10.1038/nphys1170") except RateLimitError as exc: print("retry after", exc.retry_after) except UpstreamError as exc: print("a data source failed:", exc.code) except APIError as exc: print(exc.code, exc.message, exc.request_id) ``` | Exception | When | |---|---| | `ValidationError` | the request was malformed or invalid | | `AuthError` | authentication or entitlement was refused | | `RateLimitError` | rate limit exceeded; carries `.retry_after` | | `UpstreamError` | a data source failed after the API's own retries | | `TransportError` | connection failure or timeout; no HTTP response | Every `APIError` carries `.request_id`. Include it when reporting a problem. **On any exception, report the failure.** Never invent a citation, a retraction status, or a `matched` verdict the client did not return. ## Authentication and limits Works **anonymously** at the free, rate-limited tier — fine for normal agent use. A key raises the limit about fivefold but is never required: ```python client = ScholarSidekick(api_key="ssk_…") ``` Precedence: the explicit argument, then `SCHOLAR_SIDEKICK_API_KEY`, then anonymous. Free keys come from <https://scholar-sidekick.com/account>. Other constructor options: `base_url`, `timeout` (30 s), `connect_timeout` (10 s), `max_retries` (2). `SCHOLAR_SIDEKICK_BASE_URL` overrides the host. Both clients close cleanly as context managers: ```python with ScholarSidekick() as client: ... async with AsyncScholarSidekick() as client: result = await client.verify(title="…", doi="10.1038/nphys1170") ``` ## Pitfalls - **No `resolve()`, no retraction method, no open-access method, no style search.** Only the seven methods above exist. Use the `scholar-sidekick-api` or `-cli` skill for the rest. - `format()` returns **whole-batch** `.text`/`.html` covering every input, newline-joined — not one string per item. Do not split it to synthesise per-item citations; styles put newlines inside entries. `format_items()` names the same string `.output`, deliberately. - `AuditEntry` has **`claimed_title` and `resolved_title`**, not `.title`. - `kind="claims"` needs dicts; raw strings need `kind="references"`. - `audit()` requires exactly one of `bibliography=`, `claims=`, or `references=` — it raises `ValueError` locally rather than spending a round trip. - `audit_bibliography()` sends chunks **serially even in the async client**. That is deliberate: the constraint is the server's upstream budget, not local concurrency. Do not parallelise it. - Pass identifiers verbatim. `PMID:`, `arXiv:`, ISBN hyphens and `https://doi.org/…` are all tolerated. ## Verification ```python from scholar_sidekick import ScholarSidekick client = ScholarSidekick() assert client.health().get("ok") is True # A real DOI with a deliberately wrong title must come back `mismatch`. print(client.verify(title="A title this paper does not have", doi="10.1038/nphys1170").verdict) ```
عرض على GitHub