
Paper Assembly
- 1.2k installs
- 255 repo stars
- Updated February 27, 2026
- lingzhi227/agent-research-skills
paper-assembly is a research skill for compiling academic paper sections from atomic notes.
About
The paper-assembly skill from agent-research-skills helps agents compile academic paper drafts by organizing atomic research notes, experiment results, and literature summaries into coherent sections. It defines workflows for mapping claims to evidence, maintaining citation placeholders, and sequencing introduction, methods, results, and discussion from prior decomposition work. Agents ensure each paragraph traces to sourced findings rather than invented metrics and cross-link to companion atomic-decomposition and experiment-code skills in the research pipeline. The skill targets researchers accelerating manuscript assembly while preserving traceability from section text back to underlying experiments.
- Assembles paper sections from atomic notes and experiment outputs.
- Maps claims to evidence with citation placeholder discipline.
- Sequences intro, methods, results, and discussion from prior work.
- Pairs with atomic-decomposition and experiment-code research skills.
- Preserves traceability from prose back to experiments.
Paper Assembly by the numbers
- 1,215 all-time installs (skills.sh)
- +34 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #927 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/lingzhi227/agent-research-skills --skill paper-assemblyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.2k |
|---|---|
| repo stars | ★ 255 |
| Security audit | 3 / 3 scanners passed |
| Last updated | February 27, 2026 |
| Repository | lingzhi227/agent-research-skills ↗ |
How do I assemble a paper draft from my research notes and experiments?
Assemble research paper sections from atomic notes and experiment outputs.
Who is it for?
Researchers using agent-research-skills pipeline for manuscript assembly.
Skip if: Skip for non-academic writing without experiment-backed sections.
When should I use this skill?
User assembles paper sections from decomposed research notes and results.
What you get
Sectioned manuscript draft with claims mapped to evidence and citations.
- assembled paper draft
- phase checkpoints
- completeness report
By the numbers
- Covers 8 pipeline phases from literature through review
- Includes a Python pipeline completeness check script
Files
Paper Assembly
Orchestrate the entire paper pipeline end-to-end with state management and checkpointing.
Input
$0— Paper project directory or paper plan
References
- Orchestration patterns and state management:
~/.claude/skills/paper-assembly/references/orchestration-patterns.md
Scripts
Check pipeline completeness
python ~/.claude/skills/paper-assembly/scripts/assembly_checker.py --dir paper/ --output checkpoint.json
python ~/.claude/skills/paper-assembly/scripts/assembly_checker.py --dir paper/ --verboseScans paper directory, checks 9 pipeline phases, reports missing artifacts, suggests next steps.
Workflow
Step 1: Assess Current State
1. Scan the paper directory for existing artifacts 2. Identify which phases are complete vs pending 3. Build a dependency graph of remaining work
Step 2: Execute Pipeline Phases
Run phases in dependency order:
| Phase | Skill | Input | Output |
|---|---|---|---|
| 1. Literature | literature-search, literature-review | Topic | Knowledge base, BibTeX |
| 2. Planning | research-planning | Knowledge base | Paper structure, task list |
| 3. Code | experiment-code | Plan | Training/eval pipeline |
| 4. Experiments | experiment-design | Code | Results JSON/CSV |
| 5. Figures | figure-generation | Results | PNG figures |
| 6. Tables | table-generation | Results | LaTeX tables |
| 7. Writing | paper-writing-section | All above | main.tex sections |
| 8. Citations | citation-management | Draft | references.bib |
| 9. Formatting | latex-formatting | Draft | Formatted LaTeX |
| 10. Compilation | paper-compilation | All | |
| 11. Review | self-review | Review scores |
Step 3: State Propagation
After each phase completes: 1. Save output artifacts to the paper directory 2. Propagate results to downstream phases 3. Update the progress checkpoint file
Step 4: Quality Gates
Before proceeding to the next phase:
- Verify all required outputs exist
- Check for consistency (e.g., all cited keys in .bib)
- Validate figures/tables match experimental results
Step 5: Final Assembly
1. Merge all sections into main.tex 2. Verify all \includegraphics files exist 3. Verify all \cite keys exist in .bib 4. Compile to PDF 5. Run self-review for quality check
Orchestration Patterns
Sequential Pipeline (AI-Scientist)
generate_ideas → experiments → writeup → reviewMulti-Agent State Broadcasting (AgentLaboratory)
# Propagate results to all downstream agents
set_agent_attr("dataset_code", code)
set_agent_attr("results", results_json)Copilot Mode (AgentLaboratory)
Human can intervene at any phase boundary for review/correction.
Checkpoint Format
{
"project": "paper-name",
"phases_completed": ["literature", "planning", "code"],
"current_phase": "experiments",
"artifacts": {
"literature": "knowledge_base.json",
"plan": "research_plan.json",
"code": "experiments/",
"results": null
},
"last_updated": "2024-01-15T10:30:00Z"
}Rules
- Never skip phases — each depends on previous outputs
- Save checkpoints after every phase completion
- Human review is recommended at phase boundaries
- All numbers in the paper must trace to actual experiment logs
- Re-run downstream phases if upstream changes
Related Skills
- Upstream: all other skills (this is the orchestrator)
- Downstream: paper-compilation, self-review
- See also: research-planning
Paper Assembly Orchestration Patterns
Extracted from AI-Scientist (launch_scientist.py), AI-Researcher (main_ai_researcher.py), and AgentLaboratory (ai_lab_repo.py).
Pattern 1: Sequential Pipeline (AI-Scientist)
# launch_scientist.py main loop:
# Phase 1: Idea Generation
ideas = generate_ideas(
base_dir=base_dir,
client=client,
model=model,
max_num_generations=MAX_NUM_GENERATIONS,
num_reflections=NUM_REFLECTIONS,
)
# Phase 2: Novelty Check
for idea in ideas:
novel = check_idea_novelty(
idea=idea,
max_num_iterations=10,
)
if not novel:
continue
# Phase 3: Experiments
success = perform_experiments(idea, base_dir)
if not success:
continue
# Phase 4: Writeup
perform_writeup(idea, base_dir, client, model)
# Phase 5: Review
review = perform_review(
paper_path=f"{base_dir}/latex/paper.pdf",
model=model,
num_reflections=5,
num_reviews_ensemble=5,
)Pattern 2: Multi-Agent State Broadcasting (AgentLaboratory)
# ai_lab_repo.py — propagate results to all agents
def set_agent_attr(self, attr_name, value):
"""Broadcast an attribute to all agents in the lab."""
for agent in self.agents:
setattr(agent, attr_name, value)
# Usage during pipeline:
lab.set_agent_attr("literature_review", lit_review_text)
lab.set_agent_attr("research_plan", plan_json)
lab.set_agent_attr("dataset_code", code_str)
lab.set_agent_attr("experiment_results", results_dict)
lab.set_agent_attr("paper_sections", sections_dict)
# Each agent can access shared state:
class PhdAgent:
def write_section(self, section_name):
# Can reference self.experiment_results, self.literature_review, etc.
passPattern 3: FlowModule Caching (AI-Researcher)
# main_ai_researcher.py — cache each agent's output
class FlowModule:
"""Base class for cacheable pipeline stages."""
def __init__(self, cache_dir):
self.cache_dir = cache_dir
def run(self, input_data):
cache_key = self._compute_cache_key(input_data)
cached = self._load_cache(cache_key)
if cached is not None:
return cached
result = self._execute(input_data)
self._save_cache(cache_key, result)
return result
def _execute(self, input_data):
raise NotImplementedError
# Pipeline with caching:
modules = [
PlanAgent(cache_dir="cache/plan"),
SurveyAgent(cache_dir="cache/survey"),
CodeAgent(cache_dir="cache/code"),
ExperimentAgent(cache_dir="cache/experiment"),
WriteupAgent(cache_dir="cache/writeup"),
]
state = initial_input
for module in modules:
state = module.run(state) # Cached if previously computedPattern 4: Copilot Mode Checkpoints (AgentLaboratory)
# Human intervention at phase boundaries
PHASES = [
"literature_review",
"plan_formulation",
"data_preparation",
"running_experiments",
"results_interpretation",
"report_writing",
"report_refinement",
]
for phase in PHASES:
print(f"\n{'='*50}")
print(f"Phase: {phase}")
print(f"{'='*50}\n")
result = execute_phase(phase, state)
if copilot_mode:
print(f"\nPhase '{phase}' complete.")
print(f"Result preview: {result[:500]}...")
action = input("Continue / Edit / Redo / Skip? ")
if action == "Edit":
result = get_human_edits(result)
elif action == "Redo":
result = execute_phase(phase, state)
elif action == "Skip":
continue
state[phase] = result
save_checkpoint(state, f"checkpoint_{phase}.json")Checkpoint File Format
{
"project_name": "my-paper",
"created_at": "2024-01-15T10:00:00Z",
"last_updated": "2024-01-15T14:30:00Z",
"current_phase": "report_writing",
"phases": {
"literature_review": {
"status": "completed",
"output_file": "literature_review.json",
"completed_at": "2024-01-15T10:30:00Z"
},
"plan_formulation": {
"status": "completed",
"output_file": "research_plan.json",
"completed_at": "2024-01-15T11:00:00Z"
},
"data_preparation": {
"status": "completed",
"output_file": "data_prep.py",
"completed_at": "2024-01-15T12:00:00Z"
},
"running_experiments": {
"status": "completed",
"output_file": "results.json",
"completed_at": "2024-01-15T13:30:00Z"
},
"results_interpretation": {
"status": "completed",
"output_file": "analysis.json",
"completed_at": "2024-01-15T14:00:00Z"
},
"report_writing": {
"status": "in_progress",
"output_file": null,
"started_at": "2024-01-15T14:00:00Z"
},
"report_refinement": {
"status": "pending"
}
},
"artifacts": {
"bib_file": "references.bib",
"figures": ["Figure_1.png", "Figure_2.png"],
"tables": ["table_comparison.tex"],
"main_tex": "main.tex"
}
}Phase Dependency Graph
literature_review
↓
plan_formulation
↓
data_preparation ──→ running_experiments
↓
results_interpretation
↓
report_writing ──→ report_refinement
↑ ↓
figure_generation self_review
table_generation ↓
citation_management final_compilationError Recovery
# If a phase fails, recover from last checkpoint:
def recover_from_checkpoint(checkpoint_path):
state = load_checkpoint(checkpoint_path)
# Find the last completed phase
last_completed = None
for phase in PHASES:
if state["phases"][phase]["status"] == "completed":
last_completed = phase
else:
break
# Resume from next phase
resume_idx = PHASES.index(last_completed) + 1 if last_completed else 0
for phase in PHASES[resume_idx:]:
state = execute_phase(phase, state)
save_checkpoint(state)
return state#!/usr/bin/env python3
"""Check paper pipeline completeness and report missing artifacts.
Scans a paper directory, checks which pipeline phases are complete
(literature, code, figures, tables, bib, sections), reports missing
artifacts, and suggests next steps.
Self-contained: uses only stdlib.
Usage:
python assembly_checker.py --dir paper/ --output checkpoint.json
python assembly_checker.py --dir paper/
python assembly_checker.py --dir paper/ --verbose
"""
import argparse
import glob
import json
import os
import re
import sys
PIPELINE_PHASES = [
{
"name": "literature",
"description": "Literature search and review",
"artifacts": ["*.jsonl", "knowledge_base.*", "papers.bib"],
"patterns": ["literature", "papers", "references"],
},
{
"name": "planning",
"description": "Research plan and paper structure",
"artifacts": ["research_plan.*", "plan.*", "outline.*"],
"patterns": ["plan", "outline"],
},
{
"name": "code",
"description": "Experiment code and scripts",
"artifacts": ["*.py", "*.sh", "train.*", "eval.*"],
"patterns": ["code", "scripts", "src", "experiments"],
},
{
"name": "results",
"description": "Experimental results",
"artifacts": ["results.*", "*.csv", "metrics.*", "logs/"],
"patterns": ["results", "output", "logs"],
},
{
"name": "figures",
"description": "Generated figures",
"artifacts": ["*.png", "*.pdf", "*.eps"],
"patterns": ["figures", "figs", "plots", "images"],
},
{
"name": "tables",
"description": "LaTeX tables",
"artifacts": ["*table*.tex", "*results*.tex"],
"patterns": ["tables"],
},
{
"name": "bibliography",
"description": "BibTeX bibliography",
"artifacts": ["*.bib"],
"patterns": ["."],
},
{
"name": "sections",
"description": "Paper sections (LaTeX)",
"artifacts": ["*.tex"],
"patterns": ["sections", "."],
},
{
"name": "compilation",
"description": "Compiled PDF",
"artifacts": ["*.pdf"],
"patterns": ["."],
},
]
EXPECTED_SECTIONS = [
"abstract", "introduction", "related", "method",
"experiment", "result", "conclusion", "appendix",
]
def find_artifacts(base_dir: str, phase: dict) -> list[str]:
"""Find artifacts for a pipeline phase."""
found = []
search_dirs = [base_dir]
for pattern_dir in phase["patterns"]:
candidate = os.path.join(base_dir, pattern_dir)
if os.path.isdir(candidate):
search_dirs.append(candidate)
for search_dir in search_dirs:
for artifact_pattern in phase["artifacts"]:
if artifact_pattern.endswith("/"):
# Check for directory
dpath = os.path.join(search_dir, artifact_pattern.rstrip("/"))
if os.path.isdir(dpath):
found.append(dpath)
else:
matches = glob.glob(os.path.join(search_dir, artifact_pattern))
found.extend(matches)
# Deduplicate
return sorted(set(found))
def check_tex_sections(base_dir: str) -> dict:
"""Check which paper sections exist in .tex files."""
tex_files = glob.glob(os.path.join(base_dir, "**/*.tex"), recursive=True)
all_tex = ""
for tf in tex_files:
try:
with open(tf, encoding="utf-8", errors="replace") as f:
all_tex += f.read() + "\n"
except Exception:
pass
found_sections = set()
for match in re.finditer(r"\\section\*?\{([^}]+)\}", all_tex):
name = match.group(1).lower().strip()
for expected in EXPECTED_SECTIONS:
if expected in name:
found_sections.add(expected)
if re.search(r"\\begin\{abstract\}", all_tex):
found_sections.add("abstract")
return {
"found": sorted(found_sections),
"missing": sorted(set(EXPECTED_SECTIONS[:7]) - found_sections),
"tex_files": [os.path.relpath(f, base_dir) for f in tex_files],
}
def check_citations(base_dir: str) -> dict:
"""Check citation status."""
tex_files = glob.glob(os.path.join(base_dir, "**/*.tex"), recursive=True)
bib_files = glob.glob(os.path.join(base_dir, "**/*.bib"), recursive=True)
cite_keys = set()
for tf in tex_files:
try:
with open(tf, encoding="utf-8", errors="replace") as f:
content = f.read()
for match in re.findall(r"\\cite[a-z]*\{([^}]+)\}", content):
for key in match.split(","):
cite_keys.add(key.strip())
except Exception:
pass
bib_keys = set()
for bf in bib_files:
try:
with open(bf, encoding="utf-8", errors="replace") as f:
content = f.read()
bib_keys.update(re.findall(r"@\w+\{([^,]+),", content))
except Exception:
pass
return {
"cited": len(cite_keys),
"in_bib": len(bib_keys),
"missing": sorted(cite_keys - bib_keys),
"unused": len(bib_keys - cite_keys),
}
def check_figures(base_dir: str) -> dict:
"""Check figure status."""
tex_files = glob.glob(os.path.join(base_dir, "**/*.tex"), recursive=True)
fig_refs = set()
for tf in tex_files:
try:
with open(tf, encoding="utf-8", errors="replace") as f:
content = f.read()
fig_refs.update(re.findall(r"\\includegraphics(?:\[.*?\])?\{([^}]+)\}", content))
except Exception:
pass
missing_figs = []
for fig in fig_refs:
fig_path = os.path.join(base_dir, fig)
found = os.path.exists(fig_path)
if not found:
for ext in [".png", ".pdf", ".jpg", ".eps"]:
if os.path.exists(fig_path + ext):
found = True
break
if not found:
missing_figs.append(fig)
return {
"referenced": len(fig_refs),
"missing": missing_figs,
}
def suggest_next_steps(phase_status: dict) -> list[str]:
"""Suggest next steps based on pipeline status."""
steps = []
for phase_name, status in phase_status.items():
if not status["complete"]:
if phase_name == "literature":
steps.append("Run literature search: use literature-search skill")
elif phase_name == "planning":
steps.append("Create research plan: use research-planning skill")
elif phase_name == "code":
steps.append("Write experiment code: use experiment-code skill")
elif phase_name == "results":
steps.append("Run experiments to generate results")
elif phase_name == "figures":
steps.append("Generate figures: use figure-generation skill")
elif phase_name == "tables":
steps.append("Generate tables: use table-generation skill")
elif phase_name == "bibliography":
steps.append("Add bibliography: use citation-management skill")
elif phase_name == "sections":
steps.append("Write paper sections: use paper-writing-section skill")
elif phase_name == "compilation":
steps.append("Compile paper: use paper-compilation skill")
return steps
def main():
parser = argparse.ArgumentParser(description="Check paper pipeline completeness")
parser.add_argument("--dir", required=True, help="Paper directory")
parser.add_argument("--output", "-o", help="Output JSON checkpoint file")
parser.add_argument("--verbose", action="store_true", help="Show detailed artifacts")
args = parser.parse_args()
if not os.path.isdir(args.dir):
print(f"Error: {args.dir} is not a directory", file=sys.stderr)
sys.exit(1)
phase_status = {}
completed = 0
for phase in PIPELINE_PHASES:
artifacts = find_artifacts(args.dir, phase)
is_complete = len(artifacts) > 0
phase_status[phase["name"]] = {
"complete": is_complete,
"artifacts": [os.path.relpath(a, args.dir) for a in artifacts],
"count": len(artifacts),
}
if is_complete:
completed += 1
# Detailed checks
section_info = check_tex_sections(args.dir)
citation_info = check_citations(args.dir)
figure_info = check_figures(args.dir)
next_steps = suggest_next_steps(phase_status)
report = {
"directory": os.path.abspath(args.dir),
"phases_completed": completed,
"phases_total": len(PIPELINE_PHASES),
"completion_pct": round(100 * completed / len(PIPELINE_PHASES)),
"phases": phase_status,
"sections": section_info,
"citations": citation_info,
"figures": figure_info,
"next_steps": next_steps,
}
# Print summary
print(f"Paper Pipeline Status: {args.dir}")
print(f" Completion: {completed}/{len(PIPELINE_PHASES)} phases ({report['completion_pct']}%)\n")
for name, status in phase_status.items():
icon = "+" if status["complete"] else "-"
print(f" [{icon}] {name}: {status['count']} artifacts")
if args.verbose and status["artifacts"]:
for a in status["artifacts"][:5]:
print(f" {a}")
if section_info["missing"]:
print(f"\n Missing sections: {', '.join(section_info['missing'])}")
if citation_info["missing"]:
print(f" Missing citations: {len(citation_info['missing'])}")
if figure_info["missing"]:
print(f" Missing figures: {', '.join(figure_info['missing'])}")
if next_steps:
print(f"\n Next steps:")
for step in next_steps:
print(f" -> {step}")
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"\n Checkpoint saved to {args.output}", file=sys.stderr)
if __name__ == "__main__":
main()
Related skills
Forks & variants (2)
Paper Assembly has 2 known copies in the catalog totaling 12 installs. They canonicalize to this original listing.
- lingzhi227 - 11 installs
- lingzhi227 - 1 installs
How it compares
Choose paper-assembly when multi-phase state and resumption across an entire paper matter more than a single literature or writing pass.
FAQ
What inputs does it use?
Atomic research notes, experiment results, and literature summaries.
Which companion skills exist?
atomic-decomposition and experiment-code in the same research family.
How are claims handled?
Each claim maps to evidence with citation placeholders, not invented metrics.
Is Paper Assembly safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.