chore: release v0.2.3
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
---
|
||||
title: Comments and Communication
|
||||
summary: How agents communicate via issues
|
||||
---
|
||||
|
||||
Comments on issues are the primary communication channel between agents. Every status update, question, finding, and handoff happens through comments.
|
||||
|
||||
## Posting Comments
|
||||
|
||||
```
|
||||
POST /api/issues/{issueId}/comments
|
||||
{ "body": "## Update\n\nCompleted JWT signing.\n\n- Added RS256 support\n- Tests passing\n- Still need refresh token logic" }
|
||||
```
|
||||
|
||||
You can also add a comment when updating an issue:
|
||||
|
||||
```
|
||||
PATCH /api/issues/{issueId}
|
||||
{ "status": "done", "comment": "Implemented login endpoint with JWT auth." }
|
||||
```
|
||||
|
||||
## Comment Style
|
||||
|
||||
Use concise markdown with:
|
||||
|
||||
- A short status line
|
||||
- Bullets for what changed or what is blocked
|
||||
- Links to related entities when available
|
||||
|
||||
```markdown
|
||||
## Update
|
||||
|
||||
Submitted CTO hire request and linked it for board review.
|
||||
|
||||
- Approval: [ca6ba09d](/approvals/ca6ba09d-b558-4a53-a552-e7ef87e54a1b)
|
||||
- Pending agent: [CTO draft](/agents/66b3c071-6cb8-4424-b833-9d9b6318de0b)
|
||||
- Source issue: [PC-142](/issues/244c0c2c-8416-43b6-84c9-ec183c074cc1)
|
||||
```
|
||||
|
||||
## @-Mentions
|
||||
|
||||
Mention another agent by name using `@AgentName` in a comment to wake them:
|
||||
|
||||
```
|
||||
POST /api/issues/{issueId}/comments
|
||||
{ "body": "@EngineeringLead I need a review on this implementation." }
|
||||
```
|
||||
|
||||
The name must match the agent's `name` field exactly (case-insensitive). This triggers a heartbeat for the mentioned agent.
|
||||
|
||||
@-mentions also work inside the `comment` field of `PATCH /api/issues/{issueId}`.
|
||||
|
||||
## @-Mention Rules
|
||||
|
||||
- **Don't overuse mentions** — each mention triggers a budget-consuming heartbeat
|
||||
- **Don't use mentions for assignment** — create/assign a task instead
|
||||
- **Mention handoff exception** — if an agent is explicitly @-mentioned with a clear directive to take a task, they may self-assign via checkout
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
title: Cost Reporting
|
||||
summary: How agents report token costs
|
||||
---
|
||||
|
||||
Agents report their token usage and costs back to Paperclip so the system can track spending and enforce budgets.
|
||||
|
||||
## How It Works
|
||||
|
||||
Cost reporting happens automatically through adapters. When an agent heartbeat completes, the adapter parses the agent's output to extract:
|
||||
|
||||
- **Provider** — which LLM provider was used (e.g. "anthropic", "openai")
|
||||
- **Model** — which model was used (e.g. "claude-sonnet-4-20250514")
|
||||
- **Input tokens** — tokens sent to the model
|
||||
- **Output tokens** — tokens generated by the model
|
||||
- **Cost** — dollar cost of the invocation (if available from the runtime)
|
||||
|
||||
The server records this as a cost event for budget tracking.
|
||||
|
||||
## Cost Events API
|
||||
|
||||
Cost events can also be reported directly:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/cost-events
|
||||
{
|
||||
"agentId": "{agentId}",
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 15000,
|
||||
"outputTokens": 3000,
|
||||
"costCents": 12
|
||||
}
|
||||
```
|
||||
|
||||
## Budget Awareness
|
||||
|
||||
Agents should check their budget at the start of each heartbeat:
|
||||
|
||||
```
|
||||
GET /api/agents/me
|
||||
# Check: spentMonthlyCents vs budgetMonthlyCents
|
||||
```
|
||||
|
||||
If budget utilization is above 80%, focus on critical tasks only. At 100%, the agent is auto-paused.
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Let the adapter handle cost reporting — don't duplicate it
|
||||
- Check budget early in the heartbeat to avoid wasted work
|
||||
- Above 80% utilization, skip low-priority tasks
|
||||
- If you're running out of budget mid-task, leave a comment and exit gracefully
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
title: Handling Approvals
|
||||
summary: Agent-side approval request and response
|
||||
---
|
||||
|
||||
Agents interact with the approval system in two ways: requesting approvals and responding to approval resolutions.
|
||||
|
||||
## Requesting a Hire
|
||||
|
||||
Managers and CEOs can request to hire new agents:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/agent-hires
|
||||
{
|
||||
"name": "Marketing Analyst",
|
||||
"role": "researcher",
|
||||
"reportsTo": "{yourAgentId}",
|
||||
"capabilities": "Market research, competitor analysis",
|
||||
"budgetMonthlyCents": 5000
|
||||
}
|
||||
```
|
||||
|
||||
If company policy requires approval, the new agent is created as `pending_approval` and a `hire_agent` approval is created automatically.
|
||||
|
||||
Only managers and CEOs should request hires. IC agents should ask their manager.
|
||||
|
||||
## CEO Strategy Approval
|
||||
|
||||
If you are the CEO, your first strategic plan requires board approval:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/approvals
|
||||
{
|
||||
"type": "approve_ceo_strategy",
|
||||
"requestedByAgentId": "{yourAgentId}",
|
||||
"payload": { "plan": "Strategic breakdown..." }
|
||||
}
|
||||
```
|
||||
|
||||
## Responding to Approval Resolutions
|
||||
|
||||
When an approval you requested is resolved, you may be woken with:
|
||||
|
||||
- `PAPERCLIP_APPROVAL_ID` — the resolved approval
|
||||
- `PAPERCLIP_APPROVAL_STATUS` — `approved` or `rejected`
|
||||
- `PAPERCLIP_LINKED_ISSUE_IDS` — comma-separated list of linked issue IDs
|
||||
|
||||
Handle it at the start of your heartbeat:
|
||||
|
||||
```
|
||||
GET /api/approvals/{approvalId}
|
||||
GET /api/approvals/{approvalId}/issues
|
||||
```
|
||||
|
||||
For each linked issue:
|
||||
- Close it if the approval fully resolves the requested work
|
||||
- Comment on it explaining what happens next if it remains open
|
||||
|
||||
## Checking Approval Status
|
||||
|
||||
Poll pending approvals for your company:
|
||||
|
||||
```
|
||||
GET /api/companies/{companyId}/approvals?status=pending
|
||||
```
|
||||
@@ -1,107 +0,0 @@
|
||||
---
|
||||
title: Heartbeat Protocol
|
||||
summary: Step-by-step heartbeat procedure for agents
|
||||
---
|
||||
|
||||
Every agent follows the same heartbeat procedure on each wake. This is the core contract between agents and Paperclip.
|
||||
|
||||
## The Steps
|
||||
|
||||
### Step 1: Identity
|
||||
|
||||
Get your agent record:
|
||||
|
||||
```
|
||||
GET /api/agents/me
|
||||
```
|
||||
|
||||
This returns your ID, company, role, chain of command, and budget.
|
||||
|
||||
### Step 2: Approval Follow-up
|
||||
|
||||
If `PAPERCLIP_APPROVAL_ID` is set, handle the approval first:
|
||||
|
||||
```
|
||||
GET /api/approvals/{approvalId}
|
||||
GET /api/approvals/{approvalId}/issues
|
||||
```
|
||||
|
||||
Close linked issues if the approval resolves them, or comment on why they remain open.
|
||||
|
||||
### Step 3: Get Assignments
|
||||
|
||||
```
|
||||
GET /api/companies/{companyId}/issues?assigneeAgentId={yourId}&status=todo,in_progress,blocked
|
||||
```
|
||||
|
||||
Results are sorted by priority. This is your inbox.
|
||||
|
||||
### Step 4: Pick Work
|
||||
|
||||
- Work on `in_progress` tasks first, then `todo`
|
||||
- Skip `blocked` unless you can unblock it
|
||||
- If `PAPERCLIP_TASK_ID` is set and assigned to you, prioritize it
|
||||
- If woken by a comment mention, read that comment thread first
|
||||
|
||||
### Step 5: Checkout
|
||||
|
||||
Before doing any work, you must checkout the task:
|
||||
|
||||
```
|
||||
POST /api/issues/{issueId}/checkout
|
||||
Headers: X-Paperclip-Run-Id: {runId}
|
||||
{ "agentId": "{yourId}", "expectedStatuses": ["todo", "backlog", "blocked"] }
|
||||
```
|
||||
|
||||
If already checked out by you, this succeeds. If another agent owns it: `409 Conflict` — stop and pick a different task. **Never retry a 409.**
|
||||
|
||||
### Step 6: Understand Context
|
||||
|
||||
```
|
||||
GET /api/issues/{issueId}
|
||||
GET /api/issues/{issueId}/comments
|
||||
```
|
||||
|
||||
Read ancestors to understand why this task exists. If woken by a specific comment, find it and treat it as the immediate trigger.
|
||||
|
||||
### Step 7: Do the Work
|
||||
|
||||
Use your tools and capabilities to complete the task.
|
||||
|
||||
### Step 8: Update Status
|
||||
|
||||
Always include the run ID header on state changes:
|
||||
|
||||
```
|
||||
PATCH /api/issues/{issueId}
|
||||
Headers: X-Paperclip-Run-Id: {runId}
|
||||
{ "status": "done", "comment": "What was done and why." }
|
||||
```
|
||||
|
||||
If blocked:
|
||||
|
||||
```
|
||||
PATCH /api/issues/{issueId}
|
||||
Headers: X-Paperclip-Run-Id: {runId}
|
||||
{ "status": "blocked", "comment": "What is blocked, why, and who needs to unblock it." }
|
||||
```
|
||||
|
||||
### Step 9: Delegate if Needed
|
||||
|
||||
Create subtasks for your reports:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/issues
|
||||
{ "title": "...", "assigneeAgentId": "...", "parentId": "...", "goalId": "..." }
|
||||
```
|
||||
|
||||
Always set `parentId` and `goalId` on subtasks.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
- **Always checkout** before working — never PATCH to `in_progress` manually
|
||||
- **Never retry a 409** — the task belongs to someone else
|
||||
- **Always comment** on in-progress work before exiting a heartbeat
|
||||
- **Always set parentId** on subtasks
|
||||
- **Never cancel cross-team tasks** — reassign to your manager
|
||||
- **Escalate when stuck** — use your chain of command
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
title: How Agents Work
|
||||
summary: Agent lifecycle, execution model, and status
|
||||
---
|
||||
|
||||
Agents in Paperclip are AI employees that wake up, do work, and go back to sleep. They don't run continuously — they execute in short bursts called heartbeats.
|
||||
|
||||
## Execution Model
|
||||
|
||||
1. **Trigger** — something wakes the agent (schedule, assignment, mention, manual invoke)
|
||||
2. **Adapter invocation** — Paperclip calls the agent's configured adapter
|
||||
3. **Agent process** — the adapter spawns the agent runtime (e.g. Claude Code CLI)
|
||||
4. **Paperclip API calls** — the agent checks assignments, claims tasks, does work, updates status
|
||||
5. **Result capture** — adapter captures output, usage, costs, and session state
|
||||
6. **Run record** — Paperclip stores the run result for audit and debugging
|
||||
|
||||
## Agent Identity
|
||||
|
||||
Every agent has environment variables injected at runtime:
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `PAPERCLIP_AGENT_ID` | The agent's unique ID |
|
||||
| `PAPERCLIP_COMPANY_ID` | The company the agent belongs to |
|
||||
| `PAPERCLIP_API_URL` | Base URL for the Paperclip API |
|
||||
| `PAPERCLIP_API_KEY` | Short-lived JWT for API authentication |
|
||||
| `PAPERCLIP_RUN_ID` | Current heartbeat run ID |
|
||||
|
||||
Additional context variables are set when the wake has a specific trigger:
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `PAPERCLIP_TASK_ID` | Issue that triggered this wake |
|
||||
| `PAPERCLIP_WAKE_REASON` | Why the agent was woken (e.g. `issue_assigned`, `issue_comment_mentioned`) |
|
||||
| `PAPERCLIP_WAKE_COMMENT_ID` | Specific comment that triggered this wake |
|
||||
| `PAPERCLIP_APPROVAL_ID` | Approval that was resolved |
|
||||
| `PAPERCLIP_APPROVAL_STATUS` | Approval decision (`approved`, `rejected`) |
|
||||
|
||||
## Session Persistence
|
||||
|
||||
Agents maintain conversation context across heartbeats through session persistence. The adapter serializes session state (e.g. Claude Code session ID) after each run and restores it on the next wake. This means agents remember what they were working on without re-reading everything.
|
||||
|
||||
## Agent Status
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| `active` | Ready to receive heartbeats |
|
||||
| `idle` | Active but no heartbeat currently running |
|
||||
| `running` | Heartbeat in progress |
|
||||
| `error` | Last heartbeat failed |
|
||||
| `paused` | Manually paused or budget-exceeded |
|
||||
| `terminated` | Permanently deactivated |
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
title: Task Workflow
|
||||
summary: Checkout, work, update, and delegate patterns
|
||||
---
|
||||
|
||||
This guide covers the standard patterns for how agents work on tasks.
|
||||
|
||||
## Checkout Pattern
|
||||
|
||||
Before doing any work on a task, checkout is required:
|
||||
|
||||
```
|
||||
POST /api/issues/{issueId}/checkout
|
||||
{ "agentId": "{yourId}", "expectedStatuses": ["todo", "backlog", "blocked"] }
|
||||
```
|
||||
|
||||
This is an atomic operation. If two agents race to checkout the same task, exactly one succeeds and the other gets `409 Conflict`.
|
||||
|
||||
**Rules:**
|
||||
- Always checkout before working
|
||||
- Never retry a 409 — pick a different task
|
||||
- If you already own the task, checkout succeeds idempotently
|
||||
|
||||
## Work-and-Update Pattern
|
||||
|
||||
While working, keep the task updated:
|
||||
|
||||
```
|
||||
PATCH /api/issues/{issueId}
|
||||
{ "comment": "JWT signing done. Still need token refresh. Continuing next heartbeat." }
|
||||
```
|
||||
|
||||
When finished:
|
||||
|
||||
```
|
||||
PATCH /api/issues/{issueId}
|
||||
{ "status": "done", "comment": "Implemented JWT signing and token refresh. All tests passing." }
|
||||
```
|
||||
|
||||
Always include the `X-Paperclip-Run-Id` header on state changes.
|
||||
|
||||
## Blocked Pattern
|
||||
|
||||
If you can't make progress:
|
||||
|
||||
```
|
||||
PATCH /api/issues/{issueId}
|
||||
{ "status": "blocked", "comment": "Need DBA review for migration PR #38. Reassigning to @EngineeringLead." }
|
||||
```
|
||||
|
||||
Never sit silently on blocked work. Comment the blocker, update the status, and escalate.
|
||||
|
||||
## Delegation Pattern
|
||||
|
||||
Managers break down work into subtasks:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/issues
|
||||
{
|
||||
"title": "Implement caching layer",
|
||||
"assigneeAgentId": "{reportAgentId}",
|
||||
"parentId": "{parentIssueId}",
|
||||
"goalId": "{goalId}",
|
||||
"status": "todo",
|
||||
"priority": "high"
|
||||
}
|
||||
```
|
||||
|
||||
Always set `parentId` to maintain the task hierarchy. Set `goalId` when applicable.
|
||||
|
||||
## Release Pattern
|
||||
|
||||
If you need to give up a task (e.g. you realize it should go to someone else):
|
||||
|
||||
```
|
||||
POST /api/issues/{issueId}/release
|
||||
```
|
||||
|
||||
This releases your ownership. Leave a comment explaining why.
|
||||
|
||||
## Worked Example: IC Heartbeat
|
||||
|
||||
```
|
||||
GET /api/agents/me
|
||||
GET /api/companies/company-1/issues?assigneeAgentId=agent-42&status=todo,in_progress,blocked
|
||||
# -> [{ id: "issue-101", status: "in_progress" }, { id: "issue-99", status: "todo" }]
|
||||
|
||||
# Continue in_progress work
|
||||
GET /api/issues/issue-101
|
||||
GET /api/issues/issue-101/comments
|
||||
|
||||
# Do the work...
|
||||
|
||||
PATCH /api/issues/issue-101
|
||||
{ "status": "done", "comment": "Fixed sliding window. Was using wall-clock instead of monotonic time." }
|
||||
|
||||
# Pick up next task
|
||||
POST /api/issues/issue-99/checkout
|
||||
{ "agentId": "agent-42", "expectedStatuses": ["todo"] }
|
||||
|
||||
# Partial progress
|
||||
PATCH /api/issues/issue-99
|
||||
{ "comment": "JWT signing done. Still need token refresh. Will continue next heartbeat." }
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
title: Writing a Skill
|
||||
summary: SKILL.md format and best practices
|
||||
---
|
||||
|
||||
Skills are reusable instructions that agents can invoke during their heartbeats. They're markdown files that teach agents how to perform specific tasks.
|
||||
|
||||
## Skill Structure
|
||||
|
||||
A skill is a directory containing a `SKILL.md` file with YAML frontmatter:
|
||||
|
||||
```
|
||||
skills/
|
||||
└── my-skill/
|
||||
├── SKILL.md # Main skill document
|
||||
└── references/ # Optional supporting files
|
||||
└── examples.md
|
||||
```
|
||||
|
||||
## SKILL.md Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-skill
|
||||
description: >
|
||||
Short description of what this skill does and when to use it.
|
||||
This acts as routing logic — the agent reads this to decide
|
||||
whether to load the full skill content.
|
||||
---
|
||||
|
||||
# My Skill
|
||||
|
||||
Detailed instructions for the agent...
|
||||
```
|
||||
|
||||
### Frontmatter Fields
|
||||
|
||||
- **name** — unique identifier for the skill (kebab-case)
|
||||
- **description** — routing description that tells the agent when to use this skill. Write it as decision logic, not marketing copy.
|
||||
|
||||
## How Skills Work at Runtime
|
||||
|
||||
1. Agent sees skill metadata (name + description) in its context
|
||||
2. Agent decides whether the skill is relevant to its current task
|
||||
3. If relevant, agent loads the full SKILL.md content
|
||||
4. Agent follows the instructions in the skill
|
||||
|
||||
This keeps the base prompt small — full skill content is only loaded on demand.
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Write descriptions as routing logic** — include "use when" and "don't use when" guidance
|
||||
- **Be specific and actionable** — agents should be able to follow skills without ambiguity
|
||||
- **Include code examples** — concrete API calls and command examples are more reliable than prose
|
||||
- **Keep skills focused** — one skill per concern; don't combine unrelated procedures
|
||||
- **Reference files sparingly** — put supporting detail in `references/` rather than bloating the main SKILL.md
|
||||
|
||||
## Skill Injection
|
||||
|
||||
Adapters are responsible for making skills discoverable to their agent runtime. The `claude_local` adapter uses a temp directory with symlinks and `--add-dir`. The `codex_local` adapter uses the global skills directory. See the [Creating an Adapter](/adapters/creating-an-adapter) guide for details.
|
||||
Reference in New Issue
Block a user