| name | easypaper |
| description | Generate academic papers from metadata using EasyPaper Python SDK. Use when user wants to create structured LaTeX papers programmatically. References the EasyPaper repository, especially plugins/easypaper/ directory for detailed workflows, commands, and skills. |
EasyPaper Skill
Generate structured academic papers from metadata using the EasyPaper multi-agent system via Python SDK.
Repository
Source: https://github.com/PinkGranite/EasyPaper
Primary Reference Directory: plugins/easypaper/
This directory contains comprehensive guidance for OpenClaw agents:
- Commands: Workflow execution contracts in
plugins/easypaper/commands/
- Skills: Domain-specific skills in
plugins/easypaper/skills/
- Plugin Documentation: Setup and usage in
plugins/easypaper/.claude-plugin/README.md
Installation
Python Package
Important: Install EasyPaper in an isolated environment (recommended for dependency management).
Using venv:
python -m venv easypaper-env
source easypaper-env/bin/activate
pip install easypaper
Using conda:
conda create -n easypaper python=3.11
conda activate easypaper
pip install easypaper
Direct install (not recommended):
pip install easypaper
LaTeX Toolchain
EasyPaper requires LaTeX toolchain (pdflatex + bibtex) for PDF compilation. Install based on your system:
macOS:
brew install --cask mactex
brew install basictex
sudo tlmgr update --self
sudo tlmgr install collection-basic collection-latex collection-bibtexextra
Linux (Ubuntu/Debian):
sudo apt-get update
sudo apt-get install texlive-latex-base texlive-bibtex-extra texlive-latex-extra
Linux (Fedora/RHEL):
sudo dnf install texlive-scheme-basic texlive-bibtex texlive-latex
Windows:
- Download and install MiKTeX (full installer recommended)
- Or use TeX Live
- Ensure
pdflatex and bibtex are in your PATH
Poppler (for PDF-to-image conversion)
macOS:
brew install poppler
Linux (Ubuntu/Debian):
sudo apt-get install poppler-utils
Linux (Fedora/RHEL):
sudo dnf install poppler-utils
Windows:
- Download from Poppler for Windows
- Extract and add
bin directory to PATH
- Or use conda:
conda install -c conda-forge poppler
Quick Start
Recommended workflow: Prepare a metadata.json (see examples/meta.json for schema shape), load it as PaperGenerationRequest.model_validate(json.loads(...)), then extract metadata = request.to_metadata() and build the EasyPaper.generate(...) keyword options from request fields.
Typesetter behavior (SDK + Server): PDF compilation prefers in-process Typesetter when available (SDK self-contained). If no local peer is available, EasyPaper falls back to the HTTP Typesetter endpoint (AGENTSYS_SELF_URL).
Load from file and generate
import asyncio
import json
from pathlib import Path
from easypaper import EasyPaper, PaperGenerationRequest
async def main():
ep = EasyPaper(config_path=str(Path("configs/dev.yaml").resolve()))
metadata_path = Path("metadata.json").resolve()
raw = json.loads(metadata_path.read_text(encoding="utf-8"))
def metadata_relative_path(value: str) -> str:
candidate = Path(value).expanduser()
if candidate.is_absolute():
return str(candidate)
return str((metadata_path.parent / candidate).resolve())
if not raw.get("materials_root"):
raw["materials_root"] = str(metadata_path.parent)
if raw.get("template_path"):
raw["template_path"] = metadata_relative_path(raw["template_path"])
if (
isinstance(raw.get("code_repository"), dict)
and raw["code_repository"].get("type") == "local_dir"
and raw["code_repository"].get("path")
):
raw["code_repository"]["path"] = metadata_relative_path(raw["code_repository"]["path"])
request = PaperGenerationRequest.model_validate(raw)
metadata = request.to_metadata()
options = {
"compile_pdf": request.compile_pdf,
"enable_review": request.enable_review,
"enable_vlm_review": request.enable_vlm_review,
"max_review_iterations": request.max_review_iterations,
"output_dir": str(request.output_dir) if request.output_dir else None,
"target_pages": request.target_pages,
}
result = await ep.generate(metadata, **options)
print(f"Status: {result.status}, Words: {result.total_word_count}")
asyncio.run(main())
Inline metadata
import asyncio
from easypaper import EasyPaper, PaperMetaData
async def main():
ep = EasyPaper(config_path="configs/dev.yaml")
metadata = PaperMetaData(
title="My Paper Title",
idea_hypothesis="...",
method="...",
data="...",
experiments="...",
references=["@article{...}"],
)
result = await ep.generate(metadata)
print(f"Status: {result.status}, Words: {result.total_word_count}")
asyncio.run(main())
Generate metadata from a materials folder
When the user has a folder of research materials (code, data, images, PDFs, notes, BibTeX) instead of a pre-written metadata.json, EasyPaper can scan the folder and synthesize PaperMetaData automatically:
import asyncio
from pathlib import Path
from easypaper import EasyPaper
async def main():
ep = EasyPaper(config_path=str(Path("configs/openrouter.yaml").resolve()))
metadata = await ep.generate_metadata_from_folder(
str(Path("path/to/materials").resolve()),
max_figures=12,
max_tables=12,
vision_enrich_figures=True,
)
result = await ep.generate(metadata, compile_pdf=True)
print(f"Status: {result.status}")
asyncio.run(main())
The pipeline scans files, extracts fragments, synthesizes prose (idea_hypothesis, method, data, experiments), infers style_guide / target_pages / per-asset section, deduplicates and curates figures/tables under the specified caps, and (optionally) enriches figure descriptions via a vision model with disk caching.
For the full parameter reference and cost-control guidance, see plugins/easypaper/skills/easypaper-paper-from-metadata/SKILL.md § "Alternative: Generate Metadata from a Materials Folder".
Path handling
- Metadata files should use relative paths where practical.
- Figure/table asset paths resolve through
materials_root first, then the current working directory.
- For metadata loaded from a file, set
materials_root to the metadata file parent when it is missing.
- Normalize
template_path and local code_repository.path relative to the metadata file parent before SDK execution.
- Folder-generated metadata uses an absolute
materials_root plus relative POSIX figure/table paths.
enable_review controls the text review/revision loop and defaults to true.
enable_vlm_review controls VLM/PDF visual review and page-overflow checks and defaults to false.
Key Reference Files
When working with EasyPaper, refer to these files in the repository:
Commands (Workflow Execution)
Skills (Domain Guidance)
Configuration and Examples
PaperMetaData Fields
Required:
title, idea_hypothesis, method, data, experiments, references
Optional:
style_guide (venue name), target_pages, template_path, figures, tables, code_repository, export_prompt_traces
See examples/meta.json for schema shape, examples/template/meta.json for a runnable self-contained sample, and economist_example/metadata.json for a larger repo-root example.
Final PDF Selection
When review loop is enabled, multiple iteration PDFs can exist. Always report the final artifact using this priority:
result.pdf_path (authoritative final output)
- Under
result.output_path: iteration_*_final/**/*.pdf
- Under
result.output_path: latest iteration_* directory PDF
result.output_path/paper.pdf (last fallback)
If no PDF is found, report that final PDF is unavailable and include recent compile errors.
Streaming Generation
from easypaper import EasyPaper, PaperMetaData, EventType
async for event in ep.generate_stream(metadata):
if event.get("type") == EventType.PHASE_START:
print(f"▶ [{event['phase']}] {event['message']}")
elif event.get("type") == EventType.COMPLETED:
print(f"Done!")
When to Use This Skill
Use this skill when:
- User wants to generate academic papers programmatically
- User needs to understand EasyPaper SDK usage
- User asks about paper generation workflows
- User needs venue-specific formatting guidance
For detailed workflows and execution contracts, refer to files in plugins/easypaper/ directory.