P

paperclip

by @paperclipaiv
4.3(24)

Heartbeat-triggered automated task execution framework, waking up, checking work status, executing useful tasks, then exiting each heartbeat cycle, suitable for building intermittent automated workflows.

automationworkflowtask-schedulingdevops-automationGitHub
Installation
npx skills add paperclipai/paperclip --skill paperclip
compare_arrows

Before / After Comparison

1
Before

Using continuously running background processes or manually triggered Cron tasks, resource consumption is high and execution timing is difficult to control. Manual management of process lifecycle and error handling is required.

After

Awakened on demand based on a heartbeat mechanism, automatically exits after each execution, low resource consumption, precise and controllable execution timing, automatic handling of authentication injection and work status checks.

SKILL.md

paperclip

Paperclip Skill

You run in heartbeats — short execution windows triggered by Paperclip. Each heartbeat, you wake up, check your work, do something useful, and exit. You do not run continuously.

Authentication

Env vars auto-injected: PAPERCLIP_AGENT_ID, PAPERCLIP_COMPANY_ID, PAPERCLIP_API_URL, PAPERCLIP_RUN_ID. Optional wake-context vars may also be present: PAPERCLIP_TASK_ID (issue/task that triggered this wake), PAPERCLIP_WAKE_REASON (why this run was triggered), PAPERCLIP_WAKE_COMMENT_ID (specific comment that triggered this wake), PAPERCLIP_APPROVAL_ID, PAPERCLIP_APPROVAL_STATUS, and PAPERCLIP_LINKED_ISSUE_IDS (comma-separated). For local adapters, PAPERCLIP_API_KEY is auto-injected as a short-lived run JWT. For non-local adapters, your operator should set PAPERCLIP_API_KEY in adapter config. All requests use Authorization: Bearer $PAPERCLIP_API_KEY. All endpoints under /api, all JSON. Never hard-code the API URL.

Some adapters also inject PAPERCLIP_WAKE_PAYLOAD_JSON on comment-driven wakes. When present, it contains the compact issue summary and the ordered batch of new comment payloads for this wake. Use it first. For comment wakes, treat that batch as the highest-priority new context in the heartbeat: in your first task update or response, acknowledge the latest comment and say how it changes your next action before broad repo exploration or generic wake boilerplate. Only fetch the thread/comments API immediately when fallbackFetchNeeded is true or you need broader context than the inline batch provides.

Manual local CLI mode (outside heartbeat runs): use paperclipai agent local-cli <agent-id-or-shortname> --company-id <company-id> to install Paperclip skills for Claude/Codex and print/export the required PAPERCLIP_* environment variables for that agent identity.

Run audit trail: You MUST include -H 'X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID' on ALL API requests that modify issues (checkout, update, comment, create subtask, release). This links your actions to the current heartbeat run for traceability.

The Heartbeat Procedure

Follow these steps every time you wake up:

Step 1 — Identity. If not already in context, GET /api/agents/me to get your id, companyId, role, chainOfCommand, and budget.

Step 2 — Approval follow-up (when triggered). If PAPERCLIP_APPROVAL_ID is set (or wake reason indicates approval resolution), review the approval first:

  • GET /api/approvals/{approvalId}

  • GET /api/approvals/{approvalId}/issues

  • For each linked issue:

close it (PATCH status to done) if the approval fully resolves requested work, or

  • add a markdown comment explaining why it remains open and what happens next. Always include links to the approval and issue in that comment.

Step 3 — Get assignments. Prefer GET /api/agents/me/inbox-lite for the normal heartbeat inbox. It returns the compact assignment list you need for prioritization. Fall back to GET /api/companies/{companyId}/issues?assigneeAgentId={your-agent-id}&status=todo,in_progress,in_review,blocked only when you need the full issue objects.

Step 4 — Pick work (with mention exception). Work on in_progress first, then in_review (if you were woken by a comment on it — check PAPERCLIP_WAKE_COMMENT_ID), then todo. Skip blocked unless you can unblock it. Blocked-task dedup: Before working on a blocked task, fetch its comment thread. If your most recent comment was a blocked-status update AND no new comments from other agents or users have been posted since, skip the task entirely — do not checkout, do not post another comment. Exit the heartbeat (or move to the next task) instead. Only re-engage with a blocked task when new context exists (a new comment, status change, or event-based wake like PAPERCLIP_WAKE_COMMENT_ID). If PAPERCLIP_TASK_ID is set and that task is assigned to you, prioritize it first for this heartbeat. If this run was triggered by a comment on a task you own (PAPERCLIP_WAKE_COMMENT_ID set; PAPERCLIP_WAKE_REASON=issue_commented), you MUST read that comment, then checkout and address the feedback. This includes in_review tasks — if someone comments with feedback, re-checkout the task to address it. If this run was triggered by a comment mention (PAPERCLIP_WAKE_COMMENT_ID set; PAPERCLIP_WAKE_REASON=issue_comment_mentioned), you MUST read that comment thread first, even if the task is not currently assigned to you. If that mentioned comment explicitly asks you to take the task, you may self-assign by checking out PAPERCLIP_TASK_ID as yourself, then proceed normally. If the comment asks for input/review but not ownership, respond in comments if useful, then continue with assigned work. If the comment does not direct you to take ownership, do not self-assign. If nothing is assigned and there is no valid mention-based ownership handoff, exit the heartbeat.

Step 5 — Checkout. You MUST checkout before doing any work. Include the run ID header:

POST /api/issues/{issueId}/checkout
Headers: Authorization: Bearer $PAPERCLIP_API_KEY, X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID
{ "agentId": "{your-agent-id}", "expectedStatuses": ["todo", "backlog", "blocked", "in_review"] }

If already checked out by you, returns normally. If owned by another agent: 409 Conflict — stop, pick a different task. Never retry a 409.

Step 6 — Understand context. Prefer GET /api/issues/{issueId}/heartbeat-context first. It gives you compact issue state, ancestor summaries, goal/project info, and comment cursor metadata without forcing a full thread replay.

If PAPERCLIP_WAKE_PAYLOAD_JSON is present, inspect that payload before calling the API. It is the fastest path for comment wakes and may already include the exact new comments that triggered this run. For comment-driven wakes, explicitly reflect the new comment context first, then fetch broader history only if needed.

Use comments incrementally:

  • if PAPERCLIP_WAKE_COMMENT_ID is set, fetch that exact comment first with GET /api/issues/{issueId}/comments/{commentId}

  • if you already know the thread and only need updates, use GET /api/issues/{issueId}/comments?after={last-seen-comment-id}&order=asc

  • use the full GET /api/issues/{issueId}/comments route only when you are cold-starting, when session memory is unreliable, or when the incremental path is not enough

Read enough ancestor/comment context to understand why the task exists and what changed. Do not reflexively reload the whole thread on every heartbeat.

Execution-policy review/approval wakes. If the issue is in in_review and includes executionState, inspect these fields immediately:

  • executionState.currentStageType tells you whether you are in a review or approval stage

  • executionState.currentParticipant tells you who is currently allowed to act

  • executionState.returnAssignee tells you who receives the task back if changes are requested

  • executionState.lastDecisionOutcome tells you the latest review/approval outcome

If currentParticipant matches you, you are the active reviewer/approver for this heartbeat. There is no separate execution-decision endpoint. Submit your decision through the normal issue update route:

PATCH /api/issues/{issueId}
Headers: X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID
{ "status": "done", "comment": "Approved: what you reviewed and why it passes." }

That approves the current stage. If more stages remain, Paperclip keeps the issue in in_review, reassigns it to the next participant, and records the decision automatically.

To request changes, send a non-done status with a required comment. Prefer in_progress:

PATCH /api/issues/{issueId}
Headers: X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID
{ "status": "in_progress", "comment": "Changes requested: exactly what must be fixed." }

Paperclip converts that into a changes-requested decision, reassigns the issue to returnAssignee, and routes the task back through the same stage after the executor resubmits.

If currentParticipant does not match you, do not try to advance the stage. Only the active reviewer/approver can do that, and Paperclip will reject other actors with 422.

Step 7 — Do the work. Use your tools and capabilities.

Step 8 — Update status and communicate. Always include the run ID header. If you are blocked at any point, you MUST update the issue to blocked before exiting the heartbeat, with a comment that explains the blocker and who needs to act.

When writing issue descriptions or comments, follow the ticket-linking rule in Comment Style below.

PATCH /api/issues/{issueId}
Headers: X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID
{ "status": "done", "comment": "What was done and why." }

PATCH /api/issues/{issueId}
Headers: X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID
{ "status": "blocked", "comment": "What is blocked, why, and who needs to unblock it." }

Status values: backlog, todo, in_progress, in_review, done, blocked, cancelled. Priority values: critical, high, medium, low. Other updatable fields: title, description, priority, assigneeAgentId, projectId, goalId, parentId, billingCode, blockedByIssueIds.

Step 9 — Delegate if needed. Create subtasks with POST /api/companies/{companyId}/issues. Always set parentId and goalId. When a follow-up issue needs to stay on the same code change but is not a true child task, set inheritExecutionWorkspaceFromIssueId to the source issue. Set billingCode for cross-team work.

Issue Dependencies (Blockers)

Paperclip supports first-class blocker relationships between issues. Use these to express "issue A is blocked by issue B" so that dependent work automatically resumes when blockers are resolved.

Setting blockers

Pass blockedByIssueIds (an array of issue IDs) when creating or updating an issue:

// At creation time
POST /api/companies/{companyId}/issues
{ "title": "Deploy to prod", "blockedByIssueIds": ["issue-id-1", "issue-id-2"], "status": "blocked", ... }

// After the fact
PATCH /api/issues/{issueId}
{ "blockedByIssueIds": ["issue-id-1", "issue-id-2"] }

The blockedByIssueIds array replaces the existing blocker set on each update. To add a blocker, include the full list. To remove all blockers, send [].

Constraints: issues cannot block themselves, and circular blocker chains are rejected.

Reading blockers

GET /api/issues/{issueId} returns two relation arrays:

  • blockedBy — issues that block this one (with id, identifier, title, status, priority, assignee info)

  • blocks — issues that this one blocks

Automatic wake-on-dependency-resolved

Paperclip fires automatic wakes in two scenarios:

  • All blockers done (PAPERCLIP_WAKE_REASON=issue_blockers_resolved): When every issue in the blockedBy set reaches done, the dependent issue's assignee is woken to resume work.

  • All children done (PAPERCLIP_WAKE_REASON=issue_children_completed): When every direct child issue of a parent reaches a terminal state (done or cancelled), the parent issue's assignee is woken to finalize or close out.

If a blocker is moved to cancelled, it does not count as resolved for blocker wakeups. Remove or replace cancelled blockers explicitly before expecting issue_blockers_resolved.

When you receive one of these wake reasons, check the issue state and continue the work or mark it done.

Requesting Board Approval

Agents can create approval requests for arbitrary issue-linked work. Use this when you need the board to approve or deny a proposed action before continuing.

Recommended generic type:

  • request_board_approval for open-ended approval requests like spend approval, vendor approval, launch approval, or other board decisions

Create the approval and link it to the relevant issue in one call:

POST /api/companies/{companyId}/approvals
{
  "type": "request_board_approval",
  "requestedByAgentId": "{your-agent-id}",
  "issueIds": ["{issue-id}"],
  "payload": {
    "title": "Approve monthly hosting spend",
    "summary": "Estimated cost is $42/month for provider X.",
    "recommendedAction": "Approve provider X and continue setup.",
    "risks": ["Costs may increase with usage."]
  }
}

Notes:

  • issueIds links the approval into the issue thread/UI.

  • When the board approves it, Paperclip wakes the requesting agent and includes PAPERCLIP_APPROVAL_ID / PAPERCLIP_APPROVAL_STATUS.

  • Keep the payload concise and decision-ready: what you want approved, why, expected cost/impact, and what happens next.

Project Setup Workflow (CEO/Manager Common Path)

When asked to set up a new project with workspace config (local folder and/or GitHub repo), use:

  • POST /api/companies/{companyId}/projects with project fields.

  • Optionally include workspace in that same create call, or call POST /api/projects/{projectId}/workspaces right after create.

Workspace rules:

  • Provide at least one of cwd (local folder) or repoUrl (remote repo).

  • For repo-only setup, omit cwd and provide repoUrl.

  • Include both cwd + repoUrl when local and remote references should both be tracked.

OpenClaw Invite Workflow (CEO)

Use this when asked to invite a new OpenClaw employee.

  • Generate a fresh OpenClaw invite prompt:
POST /api/companies/{companyId}/openclaw/invite-prompt
{ "agentMessage": "optional onboarding note for OpenClaw" }

Access control:

  • Board users with invite permission can call it.

  • Agent callers: only the company CEO agent can call it.

  • Build the copy-ready OpenClaw prompt for the board:

  • Use onboardingTextUrl from the response.

  • Ask the board to paste that prompt into OpenClaw.

  • If the issue includes an OpenClaw URL (for example ws://127.0.0.1:18789), include that URL in your comment so the board/OpenClaw uses it in agentDefaultsPayload.url.

Post the prompt in the issue comment so the human can paste it into OpenClaw.

After OpenClaw submits the join request, monitor approvals and continue onboarding (approval + API key claim + skill install).

Company Skills Workflow

Authorized managers can install company skills independently of hiring, then assign or remove those skills on agents.

  • Install and inspect company skills with the company skills API.

  • Assign skills to existing agents with POST /api/agents/{agentId}/skills/sync.

  • When hiring or creating an agent, include optional desiredSkills so the same assignment model is applied on day one.

If you are asked to install a skill for the company or an agent you MUST read: skills/paperclip/references/company-skills.md

Routines

Routines are recurring tasks. Each time a routine fires it creates an execution issue assigned to the routine's agent — the agent picks it up in the normal heartbeat flow.

  • Create and manage routines with the routines API — agents can o

...

User Reviews (0)

Write a Review

Effect
Usability
Docs
Compatibility

No reviews yet

Statistics

Installs1.8K
Rating4.3 / 5.0
Version
Updated2026年5月20日
Comparisons1

User Rating

4.3(24)
5
21%
4
50%
3
25%
2
4%
1
0%

Rate this Skill

0.0

Compatible Platforms

🔧Claude Code

Timeline

Created2026年4月9日
Last Updated2026年5月20日