Skip to main content

PaperPrism Agent

Local HTTP service that receives archive events from the PaperPrism Chrome extension, mirrors arxiv PDFs into a hidden workspace vault (~/.paperprism/vault), enriches them with arxiv-API + PDF metadata, classifies them with the user's LLM, generates TL;DR summaries, auto-tags every new paper, and exposes a small REST API that the extension's Dashboard / Options / Topic pages talk to.

Stack

  • Python 3.10+
  • FastAPI + uvicorn
  • Pydantic v2
  • SQLite (with FTS5) for metadata, tags, topics, and jobs
  • PyPDF + arxiv API for enrichment
  • Pluggable LLM backends: OpenAI / Anthropic / Google Gemini / Qwen / DeepSeek / Moonshot / OpenRouter / Ollama (configured via ~/.paperprism/llm.yaml + secrets.env)

Quick start

The Agent ships on PyPI as paperprism-agent. Pick whichever install mode suits you.

Option A — uvx (zero-install, one-off)

Best for "just try it" or CI smoke tests. No venv to manage.

# Needs uv 0.4+ — see https://docs.astral.sh/uv/
uvx paperprism-agent serve

Each invocation runs in a throwaway environment, so this is not suitable for paperprism-agent install (launchd needs a stable path — see Option B).

Option B — uv tool install (recommended for daily use)

Installs a stable shim at ~/.local/bin/paperprism-agent that launchd can call into. Upgrades are uv tool upgrade.

uv tool install paperprism-agent
paperprism-agent serve            # foreground test
paperprism-agent install          # register launchd LaunchAgent (macOS)

Option C — pipx / pip in a venv

pipx install paperprism-agent
# or
python3 -m venv .venv && source .venv/bin/activate
pip install paperprism-agent
paperprism-agent serve

Option D — editable checkout (for contributors)

cd agent
python3 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
paperprism-agent serve
# or equivalently:
python -m paperprism_agent serve

Default bind: http://127.0.0.1:17321.

Smoke test

# Health
curl -s http://127.0.0.1:17321/api/health | jq .

# Fake an archive.completed event pointing at any local PDF
curl -s -X POST http://127.0.0.1:17321/api/ingest \
  -H 'Content-Type: application/json' \
  -d '{
    "event": "archive.completed",
    "arxivId": {"id":"2401.08281","fullId":"2401.08281v1","version":"v1","legacy":false},
    "sourceUrl": "https://arxiv.org/pdf/2401.08281v1.pdf",
    "absUrl": "https://arxiv.org/abs/2401.08281",
    "downloadPath": "/absolute/path/to/any.pdf",
    "triggerClassification": true,
    "emittedAt": "2026-04-27T10:00:00Z"
  }' | jq .

You should see the file mirrored under:

~/.paperprism/vault/YYYY/MM/2401.08281v1/
├── paper.pdf
└── meta.json

…and, if an LLM is configured and auto_tag_on_ingest is on (default), the paper will gain 2–5 tags visible via GET /api/tags within a few seconds.

HTTP API (summary)

All endpoints are rooted at http://127.0.0.1:17321. Auth header X-PaperPrism-Token required only if --token (or PAPERPRISM_TOKEN) is set.

Method Path Purpose
GET /api/health Liveness + version
POST /api/ingest Extension's archive.requested / archive.completed event sink
POST /api/ingest/upload Multipart PDF upload used by the Dashboard bulk-import
GET /api/papers Paginated paper list with filters (tag, topic, free text)
GET /api/papers/{id} Single paper detail (metadata + tags + topics)
DELETE /api/papers/{id} Remove a paper (and its vault files)
GET /api/papers/{id}/pdf Stream the archived PDF
GET /api/dimensions/values Distinct values for each LLM dimension (for Dashboard filters)
GET /api/tasks/stats Per-dimension counts (for Dashboard headline stats)
GET /api/tags List all tags + counts
GET /api/papers/{id}/tags Tags attached to a given paper
POST /api/papers/{id}/tags Edit tags: body {"add":[...],"remove":[...]}
POST /api/tags/auto Start a batch auto-tag + topic-synthesis job for the given paper ids
GET /api/tags/auto/{job_id} Poll status of an auto-tag job
DELETE /api/tags/auto/{job_id} Cancel a running auto-tag job
POST /api/tags/auto/{job_id}/retry Retry the failed papers of a finished job
GET /api/topics List topics (each with name, summary, all tags)
GET /api/topics/{slug} Topic detail + papers
DELETE /api/topics/{topic_id} Delete a topic (papers keep their tags)
GET /api/llm/config Read current LLM provider / model / toggles
PUT /api/llm/config Update LLM config (written to llm.yaml + secrets.env)
POST /api/llm/test Tiny chat request to verify the configured key

Concrete request/response schemas live in paperprism_agent/models.py and paperprism_agent/server.py, and the TypeScript client is extension/lib/agent.ts.

CLI

Command Purpose
paperprism-agent serve Run HTTP server in the foreground
paperprism-agent install macOS: install launchd LaunchAgent and start it
paperprism-agent uninstall macOS: stop and remove LaunchAgent
paperprism-agent status macOS: print launchctl state
paperprism-agent restart macOS: force launchd to (re)start the service
paperprism-agent logs Tail logs (--which out|err|launchd-out|launchd-err, --follow)
paperprism-agent version Print version

Flags for serve / install:

  • --host, --port, --token, --home
  • serve also: --log-level
  • Env fallbacks: PAPERPRISM_HOST, PAPERPRISM_PORT, PAPERPRISM_TOKEN, PAPERPRISM_HOME

Background autostart on macOS

paperprism-agent install     # writes ~/Library/LaunchAgents/com.paperprism.agent.plist
                             # and bootstraps it into gui/<uid>
paperprism-agent status      # shows launchctl state
paperprism-agent logs --follow
paperprism-agent uninstall   # stop + delete plist

The LaunchAgent:

  • starts at user login (RunAtLoad)
  • auto-restarts on crash (KeepAlive.Crashed), not on clean stops, so uninstall and graceful SIGTERM actually work
  • rate-limits respawns (ThrottleInterval=10) to avoid hot-looping
  • captures launchd-level stdout/stderr to logs/launchd.{out,err}.log while the app's structured log continues to flow into logs/agent.{out,err}.log
  • uses sys.executable from the venv you ran install from, so upgrading is just pip install -e . && paperprism-agent restart

Linux (future)

A systemd --user unit will be generated by install when the platform is Linux. For now, run paperprism-agent serve in a terminal or wire it into your own systemd user unit.

Filesystem layout

~/.paperprism/
├── runtime.json        # {port, pid, token, version}
├── llm.yaml            # provider, model, api_base, api_key_env, auto_tag_on_ingest, ...
├── secrets.env         # API keys (mode 600)
├── db.sqlite           # papers, tags, paper_tags, topics, jobs, FTS5
├── logs/
│   ├── agent.out.log
│   ├── agent.err.log
│   ├── launchd.out.log
│   └── launchd.err.log
└── vault/
    └── YYYY/MM/<arxivId>/
        ├── paper.pdf
        └── meta.json

db.sqlite is managed by numbered migrations under paperprism_agent/migrations/ and applied automatically on startup whenever the file's schema_version is behind the code.

LLM configuration

~/.paperprism/llm.yaml (also editable from the extension's Options page → LLM section) shape:

provider: qwen            # one of: openai, anthropic, google, qwen,
                          # deepseek, moonshot, openrouter, ollama
model: qwen-plus
api_base: https://dashscope.aliyuncs.com/compatible-mode/v1
api_key_env: QWEN_API_KEY  # name of the env var holding the key
enrichment_enabled: true   # pull arxiv API metadata + PDF abstract
classification_enabled: true
auto_tag_on_ingest: true   # LLM-tag every paper added via /api/ingest
pdf_full_char_limit: 8000 # max chars of PDF full text fed to LLM classifier

Secrets are never written into llm.yaml; they sit in ~/.paperprism/secrets.env at mode 600 and are loaded into the Agent's process environment on startup (and live-injected when the Options wizard saves a new key).

Contract with the extension

See extension/lib/agent.ts. The server validates incoming JSON with paperprism_agent.models. Breaking changes on either side must bump meta.schema_version and ship a matching SQLite migration.

Metadata

Release files for paperprism-agent 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for paperprism-agent 0.2.2
File Size Uploaded Provenance
paperprism_agent-0.2.2.tar.gz 95.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for paperprism-agent 0.2.2
File Interpreter ABI Platform
paperprism_agent-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 209.6 kB

Release files / paperprism_agent-0.2.2.tar.gz

Download URL paperprism_agent-0.2.2.tar.gz
Size 95.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f18292b3ac1b2b66880d8a957ce592a4913a19b507493e8e5e15f3821e97488f
BLAKE2b-256 checksum
How to use checksums
03c88f1e5f264b0ef43eed18583f44dd6e77411fb3fa8adcc9564e85b436b5cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Release files / paperprism_agent-0.2.2-py3-none-any.whl

Download URL paperprism_agent-0.2.2-py3-none-any.whl
Size 114.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
55aff3c57a20db400d0395312b4ba2bf5bd50473f5895276b46676d06b75c9da
BLAKE2b-256 checksum
How to use checksums
d46e51f0c12bf4e0c7cf5d72a1804c63eb2589207718c46c811561adbb52f357
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Security for paperprism-agent 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page