1. Project Overview & Quickstart (paperclipai/paperclip)
File: README.md
Paperclip is the app people use to manage AI agents for work.
Open-source orchestration for teams of AI agents.
If OpenClaw is an employee, Paperclip is the company.
Paperclip is a Node.js server and React UI that orchestrates a team of AI agents to run a business. Bring your own agents, assign goals, and track work and costs from one dashboard.
It looks like a task manager. Under the hood: org charts, budgets, governance, goal alignment, and agent coordination.
Manage business goals, not pull requests.
| Step | Example | |
|---|---|---|
| 01 | Define the goal | "Build the #1 AI note-taking app to $1M MRR." |
| 02 | Hire the team | CEO, CTO, engineers, designers, marketers — any bot, any provider. |
| 03 | Approve and run | Review strategy. Set budgets. Hit go. Monitor from the dashboard. |
Paperclip is right for you if
- ✅ You want to build autonomous AI companies
- ✅ You coordinate many different agents (OpenClaw, Codex, Claude, Cursor) toward a common goal
- ✅ You have 20 simultaneous Claude Code terminals open and lose track of what everyone is doing
- ✅ You want agents running autonomously 24/7, but still want to audit work and chime in when needed
- ✅ You want to monitor costs and enforce budgets
- ✅ You want a process for managing agents that feels like using a task manager
- ✅ You want to manage your autonomous businesses from your phone
The four pillars
Four things have to work for an organization of AI agents to actually produce: the tasks, the org, the training, and the infrastructure. Paperclip is built around exactly those four pillars.
| Pillar | Built for | What it covers |
|---|---|---|
| Agentic Task Manager — Declare intent. Agents work. You verify the output. | Everyone, daily | Tasks, approvals & review gates · proactive agent coworkers · auditable routines & workflows · verify from diffs, screenshots & tests |
| Org Chart for Agents — Roles, permissions & boundaries for humans and agents. | Managers | Mixed human + agent org chart · responsibilities, delegation, specialization · governance: who can do what · scoped secrets & company boundaries |
| Agent Employee Training — Design, train & evaluate your AI employees. | Enablers | Skill Studio & shared org-wide skills · evals & saved test runs · active learning loops & quality metrics · performance reviews for agents |
| Agentic OS — The infrastructure that makes the work run. | IT & platform | Cross-provider runtime: any model, any agent · sandboxing, integrations & MCP servers · SSO, GRC, RBAC & cost controls · data privacy, internal trace collection, compounding data value |
Features
| 🔌 Bring Your Own Agent
Any agent, any runtime, one org chart. If it can receive a heartbeat, it's hired. | 🎯 Goal Alignment
Every task traces back to the company mission. Agents know what to do and why. | 💓 Heartbeats
Agents wake on a schedule, check work, and act. Delegation flows up and down the org chart. |
| --- | --- | --- |
| 💰 Cost Control
Monthly budgets per agent. When they hit the limit, they stop. No runaway costs. | 🏢 Multi-Company
One deployment, many companies. Complete data isolation. One control plane for your portfolio. | 🎫 Ticket System
Every conversation traced. Every decision explained. Full tool-call tracing and immutable audit log. |
| 🛡️ Governance
Approve hires, override strategy, pause or terminate any agent — at any time. | 📊 Org Chart
Hierarchies, roles, reporting lines. Your agents have a boss, a title, and a job description. | 📱 Mobile Ready
Monitor and manage your autonomous businesses from anywhere. |
Problems Paperclip solves
| Without Paperclip | With Paperclip |
|---|---|
| ❌ You have 20 Claude Code tabs open and can't track which one does what. On reboot you lose everything. | ✅ Tasks are ticket-based, conversations are threaded, sessions persist across reboots. |
| ❌ You manually gather context from several places to remind your bot what you're actually doing. | ✅ Context flows from the task up through the project and company goals — your agent always knows what to do and why. |
| ❌ Folders of agent configs are disorganized and you're re-inventing task management, communication, and coordination between agents. | ✅ Paperclip gives you org charts, ticketing, delegation, and governance out of the box — so you run a company, not a pile of scripts. |
| ❌ Runaway loops waste hundreds of dollars of tokens and max your quota before you even know what happened. | ✅ Cost tracking surfaces token budgets and throttles agents when they're out. Management prioritizes with budgets. |
| ❌ You have recurring jobs (customer support, social, reports) and have to remember to manually kick them off. | ✅ Heartbeats handle regular work on a schedule. Management supervises. |
| ❌ You have an idea, you have to find your repo, fire up Claude Code, keep a tab open, and babysit it. | ✅ Add a task in Paperclip. Your coding agent works on it until it's done. Management reviews their work. |
Why Paperclip is special
Paperclip handles the hard orchestration details correctly.
| Atomic execution. | Task checkout and budget enforcement are atomic, so no double-work and no runaway spend. |
| Persistent agent state. | Agents resume the same task context across heartbeats instead of restarting from scratch. |
| Runtime skill injection. | Agents can learn Paperclip workflows and project context at runtime, without retraining. |
| Governance with rollback. | Approval gates are enforced, config changes are revisioned, and bad changes can be rolled back safely. |
| Goal-aware execution. | Tasks carry full goal ancestry so agents consistently see the "why," not just a title. |
| Portable company templates. | Export/import orgs, agents, and skills with secret scrubbing and collision handling. |
| True multi-company isolation. | Every entity is company-scoped, so one deployment can run many companies with separate data and audit trails. |
What's Under the Hood
Paperclip is a full control plane, not a wrapper. Before you build any of this yourself, know that it already exists:
┌──────────────────────────────────────────────────────────────┐
│ PAPERCLIP SERVER │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │Identity & │ │ Work & │ │ Heartbeat │ │Governance │ │
│ │ Access │ │ Tasks │ │ Execution │ │& Approvals│ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Org Chart │ │Workspaces │ │ Plugins │ │ Budget │ │
│ │ & Agents │ │ & Runtime │ │ │ │ & Costs │ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Routines │ │ Secrets & │ │ Activity │ │ Company │ │
│ │& Schedules│ │ Storage │ │ & Events │ │Portability│ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
└──────────────────────────────────────────────────────────────┘
▲ ▲ ▲ ▲
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ Claude │ │ Codex │ │ CLI │ │ HTTP/web │
│ Code │ │ │ │ agents │ │ bots │
└───────────┘ └───────────┘ └───────────┘ └───────────┘The Systems
| Identity & Access — Two deployment modes (trusted local or authenticated), board users, agent API keys, short-lived run JWTs, company memberships, invite flows, and OpenClaw onboarding. Every mutating request is traced to an actor. | Org Chart & Agents — Agents have roles, titles, reporting lines, permissions, and budgets. Adapter examples match the diagram: Claude Code, Codex, CLI agents such as Cursor/Gemini/bash, HTTP/webhook bots such as OpenClaw, and external adapter plugins. If it can receive a heartbeat, it's hired. |
|---|---|
| Work & Task System — Issues carry company/project/goal/parent links, atomic checkout with execution locks, first-class blocker dependencies, comments, documents, attachments, work products, labels, and inbox state. No double-work, no lost context. | Heartbeat Execution — DB-backed wakeup queue with coalescing, budget checks, workspace resolution, secret injection, skill loading, and adapter invocation. Runs produce structured logs, cost events, session state, and audit trails. Recovery handles orphaned runs automatically. |
| Workspaces & Runtime — Project workspaces, isolated execution workspaces (git worktrees, operator branches), and runtime services (dev servers, preview URLs). Agents work in the right directory with the right context every time. | Governance & Approvals — Board approval workflows, execution policies with review/approval stages, decision tracking, budget hard-stops, agent pause/resume/terminate, and full audit logging. Nothing ships without your sign-off. |
| Budget & Cost Control — Token and cost tracking by company, agent, project, goal, issue, provider, and model. Scoped budget policies with warning thresholds and hard stops. Overspend pauses agents and cancels queued work automatically. | Routines & Schedules — Recurring tasks with cron, webhook, and API triggers. Concurrency and catch-up policies. Each routine execution creates a tracked issue and wakes the assigned agent — no manual kick-offs needed. |
| Plugins — Instance-wide plugin system with out-of-process workers, capability-gated host services, job scheduling, tool exposure, and UI contributions. Extend Paperclip without forking it. | Secrets & Storage — Instance and company secrets, encrypted local storage, provider-backed object storage, attachments, and work products. Sensitive values stay out of prompts unless a scoped run explicitly needs them. |
| Activity & Events — Mutating actions, heartbeat state changes, cost events, approvals, comments, and work products are recorded as durable activity so operators can audit what happened and why. | Company Portability — Export and import entire organizations — agents, skills, projects, routines, and issues — with secret scrubbing and collision handling. One deployment, many companies, complete data isolation. |
What Paperclip is not
| Not a chatbot. | Agents have jobs, not chat windows. |
| Not an agent framework. | We don't tell you how to build agents. We tell you how to run a company made of them. |
| Not a workflow builder. | No drag-and-drop pipelines. Paperclip models companies — with org charts, goals, budgets, and governance. |
| Not a prompt manager. | Agents bring their own prompts, models, and runtimes. Paperclip manages the organization they work in. |
| Not a single-agent tool. | This is for teams. If you have one agent, you probably don't need Paperclip. If you have twenty — you definitely do. |
| Not a code review tool. | Paperclip orchestrates work, not pull requests. Bring your own review process. |
Quickstart
Open source. Self-hosted. No Paperclip account required.
curl -fsSLO https://paperclip.ing/install.sh
curl -fsSLO https://paperclip.ing/install.sh.sha256
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c install.sh.sha256
else
shasum -a 256 -c install.sh.sha256
fi
bash install.shThe installer ensures Node.js 20 or newer is available, installs a managed
Paperclip CLI under ~/.paperclip/cli, and starts interactive onboarding. It
can also install Paperclip as a background service on supported Linux and
macOS systems. The checksum detects transfer or publishing mistakes, but it is
served from the same origin as the script; use a release-tag or commit-pinned
GitHub copy when you need an independently hosted source.
For a non-interactive managed install:
curl -fsSL https://paperclip.ing/install.sh | bash -s -- --no-prompt --no-onboard
paperclipai onboard --yesThe piped form requires supported Node.js, npm, and npx to already be present.
If Node.js bootstrap is required, download and review install.sh before
running it so no privileged dependency-install command is accepted through a
pipe.
To try Paperclip without installing anything permanently:
npx --registry https://registry.npmjs.org paperclipai onboard --yesTroubleshooting: private npm registry
.npmrcIf this fails with an
E404forpaperclipai(or similar) and you use a private npm registry (for example GitHub Packages) via a global~/.npmrc,npxmay be resolvingpaperclipaiagainst that private registry instead of the public npm registry.Diagnostic:
bashnpm config get registryWorkaround (cross-platform; force the public npm registry for this command):
bashnpx --registry https://registry.npmjs.org paperclipai onboard --yes
That quickstart path now defaults to trusted local loopback mode for the fastest first run. To start in authenticated/private mode instead, choose a bind preset explicitly:
paperclipai onboard --yes --bind lan
# or:
paperclipai onboard --yes --bind tailnetIf you already have Paperclip configured, rerunning onboard keeps the existing config in place. Use paperclipai configure to edit settings.
See doc/INSTALLING.md for pinned versions, canary and
git-ref installs, updates, rollback, service management, and uninstalling.
Or manually:
git clone https://github.com/paperclipai/paperclip.git
cd paperclip
pnpm install
pnpm devThis starts the API server at http://localhost:3100. An embedded PostgreSQL database is created automatically — no setup required.
Requirements: Node.js 20+, pnpm 9.15+
FAQ
What does a typical setup look like?
Locally, a single Node.js process manages an embedded Postgres and local file storage. For production, point it at your own Postgres and deploy however you like. Configure projects, agents, and goals — the agents take care of the rest.
If you're a solo entrepreneur you can use Tailscale to access Paperclip on the go. Then later you can deploy to e.g. Vercel when you need it.
Can I run multiple companies?
Yes. A single deployment can run an unlimited number of companies with complete data isolation.
How is Paperclip different from agents like OpenClaw or Claude Code?
Paperclip uses those agents. It orchestrates them into a company — with org charts, budgets, goals, governance, and accountability.
Why should I use Paperclip instead of just pointing my OpenClaw to Asana or Trello?
Agent orchestration has subtleties in how you coordinate who has work checked out, how to maintain sessions, monitoring costs, establishing governance - Paperclip does this for you.
(Bring-your-own-ticket-system is on the Roadmap)
Do agents run continuously?
By default, agents run on scheduled heartbeats and event-based triggers (task assignment, @-mentions). You can also hook in continuous agents like OpenClaw. You bring your agent and Paperclip coordinates.
Development
pnpm dev # Full dev (API + UI, watch mode)
pnpm dev:once # Full dev without file watching
pnpm dev:server # Server only
pnpm dev:mobile # Serve prebuilt UI on :3101 for phones/tablets (proxies /api → :3100)
pnpm dev:both # Run `pnpm dev` and `pnpm dev:mobile` together
pnpm build # Build all
pnpm typecheck # Type checking
pnpm test # Cheap default test run (Vitest only)
pnpm test:watch # Vitest watch mode
pnpm test:e2e # Playwright browser suite
pnpm db:generate # Generate DB migration
pnpm db:migrate # Apply migrationspnpm test does not run Playwright. Browser suites stay separate and are typically run only when working on those flows or in CI.
See doc/DEVELOPING.md for the full development guide.
Roadmap
- ✅ Plugin system (e.g. add a knowledge base, custom tracing, queues, etc)
- ✅ Get OpenClaw / claw-style agent employees
- ✅ companies.sh - import and export entire organizations
- ✅ Easy AGENTS.md configurations
- ✅ Skills Manager, Skill Studio & Skills Store
- ✅ Scheduled Routines
- ✅ Better Budgeting
- ✅ Agent Reviews and Approvals
- ✅ Multiple Human Users
- ✅ Cloud / Sandbox agents (e2b, Cloudflare, Daytona, Modal, Novita, self-hosted Kubernetes)
- ✅ Artifacts & Work Products
- ✅ Deep Planning (planning mode, revisioned plans, plan approvals)
- ✅ Enforced Outcomes (watchdogs, recovery actions, review gates)
- ✅ MCP Tool Gateway & Apps (governed tool access)
- ✅ Secrets Manager with per-agent access
- ✅ Activity log & action attribution
- ✅ Self-healing runs & automatic recovery
- ✅ Agent evals & feedback
- ⚪ Memory / Knowledge
- ⚪ MAXIMIZER MODE
- ⚪ Work Queues
- ⚪ Self-Organization
- ⚪ Automatic Organizational Learning
- ⚪ CEO Chat
- 🟡 Cloud deployments (multi-tenant isolation & company Import/Export shipped)
- ⚪ Desktop App
- ⚪ Bring-your-own-ticket-system (Asana / Linear / Jira as on-ramps)
- ⚪ Connected Apps (one-click integrations, e.g. Vercel)
This is the short roadmap preview. See the full roadmap in ROADMAP.md.
Community & Plugins
Find Plugins and more at awesome-paperclip
Observability
Paperclip ships with opt-in OpenTelemetry auto-instrumentation for the server (traces only). It activates when OTEL_EXPORTER_OTLP_ENDPOINT is set and supports grpc, http/protobuf, and http/json via the standard OTEL_EXPORTER_OTLP_PROTOCOL env var. The @opentelemetry/* packages are optional peer dependencies — install them only if you want tracing. See doc/observability.md for install commands and the full env-var reference.
Telemetry
Paperclip collects anonymous usage telemetry to help us understand how the product is used and improve it. No personal information, issue content, prompts, file paths, or secrets are ever collected. Private repository references are hashed with a per-install salt before being sent.
Contributors changing emitted telemetry events should follow the Telemetry Data Contract.
For proposed first-party events that are not in the generated contract yet, follow Telemetry Workflow.
Telemetry is enabled by default and can be disabled with any of the following:
| Method | How |
|---|---|
| Environment variable | PAPERCLIP_TELEMETRY_DISABLED=1 |
| Standard convention | DO_NOT_TRACK=1 |
| CI environments | Automatically disabled when CI=true |
| Config file | Set telemetry.enabled: false in your Paperclip config |
Contributing
We welcome contributions. See the contributing guide for details.
Community
- Discord — Join the community
- Twitter / X — Follow updates and announcements
- GitHub Issues — bugs and feature requests
- GitHub Discussions — ideas and RFC
License
MIT © 2026 Paperclip Labs, Inc
Star History
File: cli/README.md
Paperclip is the app people use to manage AI agents for work.
Open-source orchestration for teams of AI agents.
If OpenClaw is an employee, Paperclip is the company.
Paperclip is a Node.js server and React UI that orchestrates a team of AI agents to run a business. Bring your own agents, assign goals, and track work and costs from one dashboard.
It looks like a task manager. Under the hood: org charts, budgets, governance, goal alignment, and agent coordination.
Manage business goals, not pull requests.
| Step | Example | |
|---|---|---|
| 01 | Define the goal | "Build the #1 AI note-taking app to $1M MRR." |
| 02 | Hire the team | CEO, CTO, engineers, designers, marketers — any bot, any provider. |
| 03 | Approve and run | Review strategy. Set budgets. Hit go. Monitor from the dashboard. |
Paperclip is right for you if
- ✅ You want to build autonomous AI companies
- ✅ You coordinate many different agents (OpenClaw, Codex, Claude, Cursor) toward a common goal
- ✅ You have 20 simultaneous Claude Code terminals open and lose track of what everyone is doing
- ✅ You want agents running autonomously 24/7, but still want to audit work and chime in when needed
- ✅ You want to monitor costs and enforce budgets
- ✅ You want a process for managing agents that feels like using a task manager
- ✅ You want to manage your autonomous businesses from your phone
Features
| 🔌 Bring Your Own Agent
Any agent, any runtime, one org chart. If it can receive a heartbeat, it's hired. | 🎯 Goal Alignment
Every task traces back to the company mission. Agents know what to do and why. | 💓 Heartbeats
Agents wake on a schedule, check work, and act. Delegation flows up and down the org chart. |
| --- | --- | --- |
| 💰 Cost Control
Monthly budgets per agent. When they hit the limit, they stop. No runaway costs. | 🏢 Multi-Company
One deployment, many companies. Complete data isolation. One control plane for your portfolio. | 🎫 Ticket System
Every conversation traced. Every decision explained. Full tool-call tracing and immutable audit log. |
| 🛡️ Governance
Approve hires, override strategy, pause or terminate any agent — at any time. | 📊 Org Chart
Hierarchies, roles, reporting lines. Your agents have a boss, a title, and a job description. | 📱 Mobile Ready
Monitor and manage your autonomous businesses from anywhere. |
Problems Paperclip solves
| Without Paperclip | With Paperclip |
|---|---|
| ❌ You have 20 Claude Code tabs open and can't track which one does what. On reboot you lose everything. | ✅ Tasks are ticket-based, conversations are threaded, sessions persist across reboots. |
| ❌ You manually gather context from several places to remind your bot what you're actually doing. | ✅ Context flows from the task up through the project and company goals — your agent always knows what to do and why. |
| ❌ Folders of agent configs are disorganized and you're re-inventing task management, communication, and coordination between agents. | ✅ Paperclip gives you org charts, ticketing, delegation, and governance out of the box — so you run a company, not a pile of scripts. |
| ❌ Runaway loops waste hundreds of dollars of tokens and max your quota before you even know what happened. | ✅ Cost tracking surfaces token budgets and throttles agents when they're out. Management prioritizes with budgets. |
| ❌ You have recurring jobs (customer support, social, reports) and have to remember to manually kick them off. | ✅ Heartbeats handle regular work on a schedule. Management supervises. |
| ❌ You have an idea, you have to find your repo, fire up Claude Code, keep a tab open, and babysit it. | ✅ Add a task in Paperclip. Your coding agent works on it until it's done. Management reviews their work. |
Why Paperclip is special
Paperclip handles the hard orchestration details correctly.
| Atomic execution. | Task checkout and budget enforcement are atomic, so no double-work and no runaway spend. |
| Persistent agent state. | Agents resume the same task context across heartbeats instead of restarting from scratch. |
| Runtime skill injection. | Agents can learn Paperclip workflows and project context at runtime, without retraining. |
| Governance with rollback. | Approval gates are enforced, config changes are revisioned, and bad changes can be rolled back safely. |
| Goal-aware execution. | Tasks carry full goal ancestry so agents consistently see the "why," not just a title. |
| Portable company templates. | Export/import orgs, agents, and skills with secret scrubbing and collision handling. |
| True multi-company isolation. | Every entity is company-scoped, so one deployment can run many companies with separate data and audit trails. |
What's Under the Hood
Paperclip is a full control plane, not a wrapper. Before you build any of this yourself, know that it already exists:
┌──────────────────────────────────────────────────────────────┐
│ PAPERCLIP SERVER │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │Identity & │ │ Work & │ │ Heartbeat │ │Governance │ │
│ │ Access │ │ Tasks │ │ Execution │ │& Approvals│ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Org Chart │ │Workspaces │ │ Plugins │ │ Budget │ │
│ │ & Agents │ │ & Runtime │ │ │ │ & Costs │ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Routines │ │ Secrets & │ │ Activity │ │ Company │ │
│ │& Schedules│ │ Storage │ │ & Events │ │Portability│ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
└──────────────────────────────────────────────────────────────┘
▲ ▲ ▲ ▲
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ Claude │ │ Codex │ │ CLI │ │ HTTP/web │
│ Code │ │ │ │ agents │ │ bots │
└───────────┘ └───────────┘ └───────────┘ └───────────┘The Systems
| Identity & Access — Two deployment modes (trusted local or authenticated), board users, agent API keys, short-lived run JWTs, company memberships, invite flows, and OpenClaw onboarding. Every mutating request is traced to an actor. | Org Chart & Agents — Agents have roles, titles, reporting lines, permissions, and budgets. Adapter examples match the diagram: Claude Code, Codex, CLI agents such as Cursor/Gemini/bash, HTTP/webhook bots such as OpenClaw, and external adapter plugins. If it can receive a heartbeat, it's hired. |
|---|---|
| Work & Task System — Issues carry company/project/goal/parent links, atomic checkout with execution locks, first-class blocker dependencies, comments, documents, attachments, work products, labels, and inbox state. No double-work, no lost context. | Heartbeat Execution — DB-backed wakeup queue with coalescing, budget checks, workspace resolution, secret injection, skill loading, and adapter invocation. Runs produce structured logs, cost events, session state, and audit trails. Recovery handles orphaned runs automatically. |
| Workspaces & Runtime — Project workspaces, isolated execution workspaces (git worktrees, operator branches), and runtime services (dev servers, preview URLs). Agents work in the right directory with the right context every time. | Governance & Approvals — Board approval workflows, execution policies with review/approval stages, decision tracking, budget hard-stops, agent pause/resume/terminate, and full audit logging. Nothing ships without your sign-off. |
| Budget & Cost Control — Token and cost tracking by company, agent, project, goal, issue, provider, and model. Scoped budget policies with warning thresholds and hard stops. Overspend pauses agents and cancels queued work automatically. | Routines & Schedules — Recurring tasks with cron, webhook, and API triggers. Concurrency and catch-up policies. Each routine execution creates a tracked issue and wakes the assigned agent — no manual kick-offs needed. |
| Plugins — Instance-wide plugin system with out-of-process workers, capability-gated host services, job scheduling, tool exposure, and UI contributions. Extend Paperclip without forking it. | Secrets & Storage — Instance and company secrets, encrypted local storage, provider-backed object storage, attachments, and work products. Sensitive values stay out of prompts unless a scoped run explicitly needs them. |
| Activity & Events — Mutating actions, heartbeat state changes, cost events, approvals, comments, and work products are recorded as durable activity so operators can audit what happened and why. | Company Portability — Export and import entire organizations — agents, skills, projects, routines, and issues — with secret scrubbing and collision handling. One deployment, many companies, complete data isolation. |
What Paperclip is not
| Not a chatbot. | Agents have jobs, not chat windows. |
| Not an agent framework. | We don't tell you how to build agents. We tell you how to run a company made of them. |
| Not a workflow builder. | No drag-and-drop pipelines. Paperclip models companies — with org charts, goals, budgets, and governance. |
| Not a prompt manager. | Agents bring their own prompts, models, and runtimes. Paperclip manages the organization they work in. |
| Not a single-agent tool. | This is for teams. If you have one agent, you probably don't need Paperclip. If you have twenty — you definitely do. |
| Not a code review tool. | Paperclip orchestrates work, not pull requests. Bring your own review process. |
Quickstart
Open source. Self-hosted. No Paperclip account required.
npx paperclipai onboard --yesThat quickstart path now defaults to trusted local loopback mode for the fastest first run. To start in authenticated/private mode instead, choose a bind preset explicitly:
npx paperclipai onboard --yes --bind lan
# or:
npx paperclipai onboard --yes --bind tailnetIf you already have Paperclip configured, rerunning onboard keeps the existing config in place. Use paperclipai configure to edit settings.
Or manually:
git clone https://github.com/paperclipai/paperclip.git
cd paperclip
pnpm install
pnpm devThis starts the API server at http://localhost:3100. An embedded PostgreSQL database is created automatically — no setup required.
Requirements: Node.js 20+, pnpm 9.15+
FAQ
What does a typical setup look like?
Locally, a single Node.js process manages an embedded Postgres and local file storage. For production, point it at your own Postgres and deploy however you like. Configure projects, agents, and goals — the agents take care of the rest.
If you're a solo entrepreneur you can use Tailscale to access Paperclip on the go. Then later you can deploy to e.g. Vercel when you need it.
Can I run multiple companies?
Yes. A single deployment can run an unlimited number of companies with complete data isolation.
How is Paperclip different from agents like OpenClaw or Claude Code?
Paperclip uses those agents. It orchestrates them into a company — with org charts, budgets, goals, governance, and accountability.
Why should I use Paperclip instead of just pointing my OpenClaw to Asana or Trello?
Agent orchestration has subtleties in how you coordinate who has work checked out, how to maintain sessions, monitoring costs, establishing governance - Paperclip does this for you.
(Bring-your-own-ticket-system is on the Roadmap)
Do agents run continuously?
By default, agents run on scheduled heartbeats and event-based triggers (task assignment, @-mentions). You can also hook in continuous agents like OpenClaw. You bring your agent and Paperclip coordinates.
Importing & Exporting Companies
Export a company to a portable package and import it into any other instance — local or cloud — from a local path or GitHub:
paperclipai company export <company-id> --out ./my-export
paperclipai company import ./my-export --dry-run
paperclipai company import org/repo --target newThe board UI has matching Export and Import pages in company settings: the Export page shows a fidelity panel listing what the bundle will not carry, and the Import page starts imported agents and routines paused by default, with a post-import activation step. See the Importing & Exporting guide for details.
Development
pnpm dev # Full dev (API + UI, watch mode)
pnpm dev:once # Full dev without file watching
pnpm dev:server # Server only
pnpm build # Build all
pnpm typecheck # Type checking
pnpm test # Cheap default test run (Vitest only)
pnpm test:watch # Vitest watch mode
pnpm test:e2e # Playwright browser suite
pnpm db:generate # Generate DB migration
pnpm db:migrate # Apply migrationspnpm test does not run Playwright. Browser suites stay separate and are typically run only when working on those flows or in CI.
See doc/DEVELOPING.md for the full development guide.
Roadmap
- ✅ Plugin system (e.g. add a knowledge base, custom tracing, queues, etc)
- ✅ Get OpenClaw / claw-style agent employees
- ✅ companies.sh - import and export entire organizations
- ✅ Easy AGENTS.md configurations
- ✅ Skills Manager
- ✅ Scheduled Routines
- ✅ Better Budgeting
- ✅ Agent Reviews and Approvals
- ✅ Multiple Human Users
- ⚪ Cloud / Sandbox agents (e.g. Cursor / e2b / Novita agents)
- ⚪ Artifacts & Work Products
- ⚪ Memory / Knowledge
- ⚪ Enforced Outcomes
- ⚪ MAXIMIZER MODE
- ⚪ Deep Planning
- ⚪ Work Queues
- ⚪ Self-Organization
- ⚪ Automatic Organizational Learning
- ⚪ CEO Chat
- ⚪ Cloud deployments
- ⚪ Desktop App
This is the short roadmap preview. See the full roadmap in ROADMAP.md.
Community & Plugins
Find Plugins and more at awesome-paperclip
Telemetry
Paperclip collects anonymous usage telemetry to help us understand how the product is used and improve it. No personal information, issue content, prompts, file paths, or secrets are ever collected. Private repository references are hashed with a per-install salt before being sent.
Telemetry is enabled by default and can be disabled with any of the following:
| Method | How |
|---|---|
| Environment variable | PAPERCLIP_TELEMETRY_DISABLED=1 |
| Standard convention | DO_NOT_TRACK=1 |
| CI environments | Automatically disabled when CI=true |
| Config file | Set telemetry.enabled: false in your Paperclip config |
Contributing
We welcome contributions. See the contributing guide for details.
Community
- Discord — Join the community
- Twitter / X — Follow updates and announcements
- GitHub Issues — bugs and feature requests
- GitHub Discussions — ideas and RFC
License
MIT © 2026 Paperclip Labs, Inc
Star History
File: doc/experimental/issue-worktree-support.md
Issue worktree support
Status: experimental, runtime-only, not shipping as a user-facing feature yet.
This branch contains the runtime and seeding work needed for issue-scoped worktrees:
- project execution workspace policy support
- issue-level execution workspace settings
- git worktree realization for isolated issue execution
- optional command-based worktree provisioning
- seeded worktree fixes for secrets key compatibility
- seeded project workspace rebinding to the current git worktree
We are intentionally not shipping the UI for this yet. The runtime code remains in place, but the main UI entrypoints are hard-gated off for now.
What works today
- projects can carry execution workspace policy in the backend
- issues can carry execution workspace settings in the backend
- heartbeat execution can realize isolated git worktrees
- runtime can run a project-defined provision command inside the derived worktree
- seeded worktree instances can keep local-encrypted secrets working
- seeded worktree instances can rebind same-repo project workspace paths onto the current git worktree
Shared workspace concurrency policy
Projects and individual issues can set sharedWorkspaceConcurrency in their execution workspace policy/settings:
auto(the default when absent): allow concurrent shared-workspace runs onlocalandsshenvironments, and serialize runs onsandboxandpluginenvironments. An instance forced to Kubernetes always serializes inautomode.serialize: defer a run while another live run holds the same project workspace, using theworkspace_busyretry path.allow: dispatch alongside a live holder on every environment.
Issue settings override the project policy, which overrides the default auto. When concurrency is allowed and a live holder exists, Paperclip adds the holder run and issue to the dispatched task context so agents can coordinate concurrent mutations through commits. The setting is optional JSON policy data, so existing databases require no migration.
Hidden UI entrypoints
These are the current user-facing UI surfaces for the feature, now intentionally disabled:
project settings:
ui/src/components/ProjectProperties.tsx- execution workspace policy controls
- git worktree base ref / branch template / parent dir
- provision / teardown command inputs
issue creation:
ui/src/components/NewIssueDialog.tsx- isolated issue checkout toggle
- defaulting issue execution workspace settings from project policy
issue editing:
ui/src/components/IssueProperties.tsx- issue-level workspace mode toggle
- defaulting issue execution workspace settings when project changes
agent/runtime settings:
ui/src/adapters/runtime-json-fields.tsx- runtime services JSON field, which is part of the broader workspace-runtime support surface
Why the UI is hidden
- the runtime behavior is still being validated
- the workflow and operator ergonomics are not final
- we do not want to expose a partially-baked user-facing feature in issues, projects, or settings
Re-enable plan
When this is ready to ship:
- re-enable the gated UI sections in the files above
- review wording and defaults for project and issue controls
- decide which agent/runtime settings should remain advanced-only
- add end-to-end product-level verification for the full UI workflow
File: doc/plans/2026-02-16-module-system.md
Paperclip Module System
Supersession note: the company-template/package-format direction in this document is no longer current. For the current markdown-first company import/export plan, see
doc/plans/2026-03-13-company-import-export-v2.mdanddocs/companies/companies-spec.md.
Overview
Paperclip's module system lets you extend the control plane with new capabilities — revenue tracking, observability, notifications, dashboards — without forking core. Modules are self-contained packages that register routes, UI pages, database tables, and lifecycle hooks.
Separately, Company Templates are code-free data packages (agent teams, org charts, goal hierarchies) that you can import to bootstrap a new company.
Both are discoverable through the Company Store.
Concepts
| Concept | What it is | Contains code? |
|---|---|---|
| Module | A package that extends Paperclip's API, UI, and data model | Yes |
| Company Template | A data snapshot — agents, projects, goals, org structure | No (JSON only) |
| Company Store | Registry for browsing/installing modules and templates | — |
| Hook | A named event in the core that modules can subscribe to | — |
| Slot | An exclusive category where only one module can be active (e.g., observability) |
— |
Module Architecture
File Structure
modules/
observability/
paperclip.module.json # manifest (required)
src/
index.ts # entry point — exports register function
routes.ts # Express router
hooks.ts # hook handlers
schema.ts # Drizzle table definitions
migrations/ # SQL migrations (generated by drizzle-kit)
ui/ # React components (lazy-loaded by the shell)
index.ts # exports page/widget definitions
TokenDashboard.tsxModules live in a top-level modules/ directory. Each module is a pnpm workspace package.
Manifest (`paperclip.module.json`)
{
"id": "observability",
"name": "Observability",
"description": "Token tracking, cost metrics, and agent performance instrumentation",
"version": "0.1.0",
"author": "paperclip",
"slot": "observability",
"hooks": [
"agent:heartbeat",
"agent:created",
"issue:status_changed",
"budget:threshold_crossed"
],
"routes": {
"prefix": "/observability",
"entry": "./src/routes.ts"
},
"ui": {
"pages": [
{
"path": "/observability",
"label": "Observability",
"entry": "./src/ui/index.ts"
}
],
"widgets": [
{
"id": "token-burn-rate",
"label": "Token Burn Rate",
"placement": "dashboard",
"entry": "./src/ui/index.ts"
}
]
},
"schema": "./src/schema.ts",
"configSchema": {
"type": "object",
"properties": {
"retentionDays": { "type": "number", "default": 30 },
"enablePrometheus": { "type": "boolean", "default": false },
"prometheusPort": { "type": "number", "default": 9090 }
}
},
"requires": {
"core": ">=0.1.0"
}
}Key fields:
id: Unique identifier, used as the npm package name suffix (@paperclipai/mod-observability)slot: Optional exclusive category. If set, only one module with this slot can be active. Omit for modules that can coexist freely.hooks: Which core events this module subscribes to. Declared upfront so the core knows what to emit.routes.prefix: Mounted under/api/modules/. The module owns this namespace.ui.pages: Adds entries to the sidebar. Lazy-loaded React components.ui.widgets: Injects components into existing pages (e.g., dashboard cards).schema: Drizzle table definitions for module-owned tables. Prefixed withmod__to avoid collisions.configSchema: JSON Schema for module configuration. Validated before the module loads.
Entry Point
The module's src/index.ts exports a register function that receives the module API:
import type { ModuleAPI } from "@paperclipai/core";
import { createRouter } from "./routes.js";
import { onHeartbeat, onBudgetThreshold } from "./hooks.js";
export default function register(api: ModuleAPI) {
// Register route handler
api.registerRoutes(createRouter(api.db, api.config));
// Subscribe to hooks
api.on("agent:heartbeat", onHeartbeat);
api.on("budget:threshold_crossed", onBudgetThreshold);
// Register a background service (optional)
api.registerService({
name: "metrics-aggregator",
interval: 60_000, // run every 60s
async run(ctx) {
await aggregateMetrics(ctx.db);
},
});
}Module API Surface
interface ModuleAPI {
// Identity
moduleId: string;
config: Record<string, unknown>; // validated against configSchema
// Database
db: Db; // shared Drizzle client
// Routes
registerRoutes(router: Router): void;
// Hooks
on(event: HookEvent, handler: HookHandler): void;
// Background services
registerService(service: ServiceDef): void;
// Logging (scoped to module)
logger: Logger;
// Access core services (read-only helpers)
core: {
agents: AgentService;
issues: IssueService;
projects: ProjectService;
goals: GoalService;
activity: ActivityService;
};
}Modules get a scoped logger, access to the shared database, and read access to core services. They register their own routes and hook handlers. They do NOT monkey-patch core — they extend through defined interfaces.
Hook System
Core Hook Points
Hooks are the primary integration point. The core emits events at well-defined moments. Modules subscribe in their register function.
| Hook | Payload | When |
|---|---|---|
server:started |
{ port } |
After the Express server begins listening |
agent:created |
{ agent } |
After a new agent is inserted |
agent:updated |
{ agent, changes } |
After an agent record is modified |
agent:deleted |
{ agent } |
After an agent is removed |
agent:heartbeat |
{ agentId, timestamp, meta } |
When an agent checks in. meta carries tokens_used, cost, latency, etc. |
agent:status_changed |
{ agent, from, to } |
When agent status transitions (idle→active, active→error, etc.) |
issue:created |
{ issue } |
After a new issue is inserted |
issue:status_changed |
{ issue, from, to } |
When issue moves between statuses |
issue:assigned |
{ issue, agent } |
When an issue is assigned to an agent |
goal:created |
{ goal } |
After a new goal is inserted |
goal:completed |
{ goal } |
When a goal's status becomes complete |
budget:spend_recorded |
{ agentId, amount, total } |
After spend is incremented |
budget:threshold_crossed |
{ agentId, budget, spent, percent } |
When an agent crosses 80%, 90%, or 100% of budget |
Hook Execution Model
// In the core — hook emitter
class HookBus {
private handlers = new Map<string, HookHandler[]>();
register(event: string, handler: HookHandler) {
const list = this.handlers.get(event) ?? [];
list.push(handler);
this.handlers.set(event, list);
}
async emit(event: string, payload: unknown) {
const handlers = this.handlers.get(event) ?? [];
// Run all handlers concurrently. Failures are logged, never block core.
await Promise.allSettled(
handlers.map(h => h(payload))
);
}
}Design rules:
- Hooks are fire-and-forget. A failing hook handler never crashes or blocks the core operation.
- Hooks are concurrent. All handlers for an event run in parallel via
Promise.allSettled. - Hooks are post-commit. They fire after the database write succeeds, not before. No vetoing.
- Hooks receive immutable snapshots. Handlers get a copy of the data, not a mutable reference.
This keeps the core fast and resilient. If you need pre-commit validation (e.g., "reject this budget change"), that's a different mechanism (middleware/interceptor) we can add later if needed.
Observability Hook Example
// modules/observability/src/hooks.ts
import type { Db } from "@paperclipai/db";
import { tokenMetrics } from "./schema.js";
export function createHeartbeatHandler(db: Db) {
return async (payload: {
agentId: string;
timestamp: Date;
meta: { tokensUsed?: number; costCents?: number; model?: string };
}) => {
const { agentId, timestamp, meta } = payload;
if (meta.tokensUsed != null) {
await db.insert(tokenMetrics).values({
agentId,
tokensUsed: meta.tokensUsed,
costCents: meta.costCents ?? 0,
model: meta.model ?? "unknown",
recordedAt: timestamp,
});
}
};
}Every heartbeat, the observability module records token usage into its own mod_observability_token_metrics table. The core doesn't know or care about this table — it just emits the hook.
Database Strategy for Modules
Table Namespacing
Module tables are prefixed with mod_<moduleId>_ to avoid collisions with core tables and other modules:
// modules/observability/src/schema.ts
import { pgTable, uuid, integer, text, timestamp } from "drizzle-orm/pg-core";
export const tokenMetrics = pgTable("mod_observability_token_metrics", {
id: uuid("id").primaryKey().defaultRandom(),
agentId: uuid("agent_id").notNull(),
tokensUsed: integer("tokens_used").notNull(),
costCents: integer("cost_cents").notNull().default(0),
model: text("model").notNull(),
recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull().defaultNow(),
});
export const alertRules = pgTable("mod_observability_alert_rules", {
id: uuid("id").primaryKey().defaultRandom(),
agentId: uuid("agent_id"),
metricName: text("metric_name").notNull(),
threshold: integer("threshold").notNull(),
enabled: boolean("enabled").notNull().default(true),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});Migration Strategy
Each module manages its own migrations in src/migrations/. The core migration runner discovers and applies them:
- Core migrations run first (always)
- Module migrations run in dependency order
- Each module's migrations are tracked in a
mod_migrationstable with the module ID pnpm db:migrateruns everything.pnpm db:migrate --module observabilityruns one.
Modules can reference core tables via foreign keys (e.g., agent_id → agents.id) but core tables never reference module tables. This is a strict one-way dependency.
Module Loading & Lifecycle
Discovery
On server startup:
1. Scan modules/ directory for paperclip.module.json manifests
2. Validate each manifest (JSON Schema check on configSchema, required fields)
3. Check slot conflicts (error if two active modules claim the same slot)
4. Topological sort by dependencies (if module A requires module B)
5. For each module in order:
a. Validate module config against configSchema
b. Run pending migrations
c. Import entry point and call register(api)
d. Mount routes at /api/modules/
e. Start background services
6. Emit server:started hookConfiguration
Module config lives in the server's environment or a config file:
// paperclip.config.json (or env vars)
{
"modules": {
"enabled": ["observability", "revenue", "notifications"],
"config": {
"observability": {
"retentionDays": 90,
"enablePrometheus": true
},
"revenue": {
"stripeSecretKey": "$STRIPE_SECRET_KEY"
}
}
}
}$ENV_VAR references are resolved at load time. Secrets never go in the config file directly.
Disabling a Module
Setting a module's enabled state to false:
- Stops its background services
- Unmounts its routes (returns 404)
- Unsubscribes its hook handlers
- Does NOT drop its database tables (data is preserved)
UI Integration
How Module UI Works
The core UI shell provides:
- A sidebar with slots for module-contributed nav items
- A dashboard with widget mount points
- A module settings page
Modules declare pages and widgets in the manifest. The shell lazy-loads them:
// ui/src/modules/loader.ts
// At build time or runtime, discover module UI entries and create lazy routes
import { lazy } from "react";
// Generated from manifests
export const modulePages = [
{
path: "/observability",
label: "Observability",
component: lazy(() => import("@paperclipai/mod-observability/ui")),
},
];
export const dashboardWidgets = [
{
id: "token-burn-rate",
label: "Token Burn Rate",
placement: "dashboard",
component: lazy(() => import("@paperclipai/mod-observability/ui").then(m => ({ default: m.TokenBurnRateWidget }))),
},
];Module UI Contract
A module's UI entry exports named components:
// modules/observability/src/ui/index.ts
export { default } from "./ObservabilityPage";
export { TokenBurnRateWidget } from "./TokenBurnRateWidget";Module UI components receive a standard props interface:
interface ModulePageProps {
moduleId: string;
config: Record<string, unknown>;
}
interface ModuleWidgetProps {
moduleId: string;
config: Record<string, unknown>;
className?: string;
}Module UI hits the module's own API routes (/api/modules/observability/*) for data.
Company Templates
Format
A company template is a JSON file describing a full company structure:
/* Detailed source-code truncated for AI context efficiency. */Templates use ref strings (not UUIDs) for internal cross-references. On import, the system maps refs to generated UUIDs.
Import Flow
1. Parse and validate the template JSON
2. Check for ref uniqueness and dangling references
3. Insert agents (topological sort by reportsTo)
4. Insert goals (topological sort by parentRef)
5. Insert projects
6. Insert issues (resolve projectRef, assigneeRef, goalRef to real IDs)
7. Log activity events for everything createdExport Flow
You can also export a running company as a template:
GET /api/templates/export → downloads the current company as a template JSONThis makes companies shareable and clonable.
Company Store
The Company Store is a registry for discovering and installing modules and templates. For v1, it's a curated GitHub repo with a JSON index. Later it could become a hosted service.
Index Format
{
"modules": [
{
"id": "observability",
"name": "Observability",
"description": "Token tracking, cost metrics, and agent performance",
"repo": "github:paperclip/mod-observability",
"version": "0.1.0",
"tags": ["metrics", "monitoring", "tokens"]
}
],
"templates": [
{
"id": "startup-in-a-box",
"name": "Startup in a Box",
"description": "5-agent startup team",
"url": "https://store.paperclip.ing/templates/startup-in-a-box.json",
"tags": ["startup", "team"]
}
]
}CLI Commands
pnpm paperclipai store list # browse available modules and templates
pnpm paperclipai store install <module-id> # install a module
pnpm paperclipai store import <template-id> # import a company template
pnpm paperclipai store export # export current company as templateModule Candidates
Tier 1 — Build first (core extensions)
| Module | What it does | Key hooks |
|---|---|---|
| Observability | Token usage tracking, cost metrics, agent performance dashboards, Prometheus export | agent:heartbeat, budget:spend_recorded |
| Revenue Tracking | Connect Stripe/crypto wallets, track income, show P&L against agent costs | budget:spend_recorded |
| Notifications | Slack/Discord/email alerts on configurable triggers | All hooks (configurable) |
Tier 2 — High value
| Module | What it does | Key hooks |
|---|---|---|
| Analytics Dashboard | Burn rate trends, agent utilization over time, goal velocity charts | agent:heartbeat, issue:status_changed, goal:completed |
| Workflow Automation | If/then rules: "when issue is done, create follow-up", "when budget at 90%, pause agent" | issue:status_changed, budget:threshold_crossed |
| Knowledge Base | Shared document store, vector search, agents read/write organizational knowledge | agent:heartbeat (for context injection) |
Tier 3 — Nice to have
| Module | What it does | Key hooks |
|---|---|---|
| Audit & Compliance | Immutable audit trail, approval workflows, spend authorization | All write hooks |
| Agent Logs / Replay | Full execution traces per agent, token-by-token replay | agent:heartbeat |
| Multi-tenant | Separate companies/orgs within one Paperclip instance | server:started |
Implementation Plan
Phase 1: Core infrastructure
Add to @paperclipai/server:
- HookBus — Event emitter with
register()andemit(), usingPromise.allSettled - Module loader — Scans
modules/, validates manifests, callsregister(api) - Module API object —
registerRoutes(),on(),registerService(), logger, core service access - Module config —
paperclip.config.jsonwith per-module config, env var interpolation - Module migration runner — Extends
db:migrateto discover and run module migrations - Emit hooks from core services — Add
hookBus.emit()calls to existing CRUD operations
Add to @paperclipai/ui:
- Module page loader — Reads module manifests, generates lazy routes
- Dashboard widget slots — Render module-contributed widgets on the Dashboard page
- Sidebar extension — Dynamically add module nav items
Add new package:
@paperclipai/module-sdk— TypeScript types forModuleAPI,HookEvent,HookHandler, manifest schema
Phase 2: First module (observability)
- Build
modules/observabilityas the reference implementation - Token metrics table + migration
- Heartbeat hook handler recording token usage
- Dashboard widget showing burn rate
- API routes for querying metrics
Phase 3: Templates
- Template import endpoint (
POST /api/templates/import) - Template export endpoint (
GET /api/templates/export) - First template: "Startup in a Box"
Phase 4: Company Store
- GitHub-based store index
- CLI commands for browse/install/import
- UI page for browsing the store
Design Principles
Modules extend, never patch. Modules add new routes, tables, and hook handlers. They never modify core tables or override core routes.
Hooks are post-commit, fire-and-forget. Module failures never break core operations.
One-way dependency. Modules depend on core. Core never depends on modules. Module tables can FK to core tables, not the reverse.
Declarative manifest, imperative registration. Static metadata in JSON (validated without running code). Runtime behavior registered via the API.
Namespace isolation. Module routes live under
/api/modules//. Module tables are prefixedmod__. Module config is scoped to its ID.Graceful degradation. If a module fails to load, log the error and continue. The rest of the system works fine.
Data survives disable. Disabling a module stops its code but preserves its data. Re-enabling picks up where it left off.
File: doc/plans/2026-02-18-agent-authentication.md
Agent Authentication & Onboarding
Problem
Agents need API keys to authenticate with Paperclip. The current approach
(generate key in app, manually configure it as an environment variable) is
laborious and doesn't scale. Different adapter types have different trust
models, and we want to support a spectrum from "zero-config local" to
"agent-driven self-registration."
Design Principles
- Match auth complexity to the trust boundary. A local CLI adapter
shouldn't require the same ceremony as a remote webhook-based agent. - Agents should be able to onboard themselves. Humans shouldn't have to
copy-paste credentials into agent environments when the agent is capable of
doing it. - Approval gates by default. Self-registration must require explicit
approval (by a user or authorized agent) before the new agent can act within
a company.
Authentication Tiers
Tier 1: Local Adapter (claude-local, codex-local)
Trust model: The adapter process runs on the same machine as the Paperclip
server (or is invoked directly by it). There is no meaningful network boundary.
Approach: Paperclip generates a token and passes it directly to the agent
process as a parameter/env var at invocation time. No manual setup required.
Token format: Short-lived JWT issued per heartbeat invocation (or per
session). The server mints the token, passes it in the adapter call, and
accepts it back on API requests.
Token lifetime considerations:
- Coding agents can run for hours, so tokens can't expire too quickly.
- Infinite-lived tokens are undesirable even in local contexts.
- Use JWTs with a generous expiry (e.g. 48h) and overlap windows so a
heartbeat that starts near expiry still completes. - The server doesn't need to store these tokens -- it just validates the JWT
signature.
Status: Partially implemented. The local adapter already passesPAPERCLIP_API_URL, PAPERCLIP_AGENT_ID, PAPERCLIP_COMPANY_ID. We need to
add a PAPERCLIP_API_KEY (JWT) to the set of injected env vars.
Tier 2: CLI-Driven Key Exchange
Trust model: A developer is setting up a remote or semi-remote agent and
has shell access to it.
Approach: Similar to claude setup-token -- the developer runs a Paperclip CLI
command that opens a browser URL for confirmation, then receives a token that
gets stored in the agent's config automatically.
paperclip auth login
# Opens browser -> user confirms -> token stored at ~/.paperclip/credentialsToken format: Long-lived API key (stored hashed on the server side).
Status: Future. Not needed until we have remote adapters that aren't
managed by the Paperclip server itself.
Tier 3: Agent Self-Registration (Invite Link)
Trust model: The agent is an autonomous external system (e.g. an OpenClaw
agent, a SWE-agent instance). There is no human in the loop during setup. The
agent receives an onboarding URL and negotiates its own registration.
Approach:
- A company admin (user or agent) generates an invite URL from Paperclip.
- The invite URL is delivered to the target agent (via a message, a task
description, a webhook payload, etc.). - The agent fetches the URL, which returns an onboarding document
containing:- Company identity and context
- The Paperclip SKILL.md (or a link to it)
- What information Paperclip needs from the agent (e.g. webhook URL, adapter
type, capabilities, preferred name/role) - A registration endpoint to POST the response to
- The agent responds with its configuration (e.g. "here's my webhook URL,
here's my name, here are my capabilities"). - Paperclip stores the pending registration.
- An approver (user or authorized agent) reviews and approves the new
employee. Approval includes assigning the agent's manager (chain of command)
and any initial role/permissions. - On approval, Paperclip provisions the agent's credentials and sends the
first heartbeat.
Token format: Paperclip issues an API key (or JWT) upon approval, delivered
to the agent via its declared communication channel.
Inspiration:
- Allium self-registration --
agent collects credentials, polls for confirmation, stores key automatically. - Allium x402 -- multi-step
credential setup driven entirely by the agent. - OpenClaw webhooks -- external
systems trigger agent actions via authenticated webhook endpoints.
Self-Registration: Onboarding Negotiation Protocol
The invite URL response should be a structured document (JSON or markdown) that
is both human-readable and machine-parseable:
GET /api/invite/{inviteToken}Response:
{
"company": {
"id": "...",
"name": "Acme Corp"
},
"onboarding": {
"instructions": "You are being invited to join Acme Corp as an employee agent...",
"skillUrl": "https://app.paperclip.ing/skills/paperclip/SKILL.md",
"requiredFields": {
"name": "Your display name",
"adapterType": "How Paperclip should send you heartbeats",
"webhookUrl": "If adapter is webhook-based, your endpoint URL",
"capabilities": "What you can do (free text or structured)"
},
"registrationEndpoint": "POST /api/invite/{inviteToken}/register"
}
}The agent POSTs back:
{
"name": "CodingBot",
"adapterType": "webhook",
"webhookUrl": "https://my-agent.example.com/hooks/agent",
"webhookAuthToken": "Bearer ...",
"capabilities": ["code-review", "implementation", "testing"]
}This goes into a pending_approval state until someone approves it.
OpenClaw as First External Integration
OpenClaw is the ideal first target for Tier 3 because:
- It already has webhook support (
POST /hooks/agent) for receiving tasks. - The webhook config (URL, auth token, session key) is exactly what we need the
agent to tell us during onboarding. - OpenClaw agents can read a URL, parse instructions, and make HTTP calls.
Workflow:
- Generate a Paperclip invite link for the company.
- Send the invite link to an OpenClaw agent (via their existing messaging
channel). - The OpenClaw agent fetches the invite, reads the onboarding doc, and
responds with its webhook configuration. - A Paperclip company member approves the new agent.
- Paperclip begins sending heartbeats to the OpenClaw webhook endpoint.
Approval Model
All self-registration requires approval. This is non-negotiable for security.
- Default: A human user in the company must approve.
- Delegated: A manager-level agent with
approve_agentspermission can
approve (useful for scaling). - Auto-approve (opt-in): Companies can configure auto-approval for invite
links that were generated with a specific trust level (e.g. "I trust anyone
with this link"). Even then, the invite link itself is a secret.
On approval, the approver sets:
reportsTo-- who the new agent reports to in the chain of commandrole-- the agent's role within the companybudget-- initial budget allocation
Implementation Priorities
| Priority | Item | Notes |
|---|---|---|
| P0 | Local adapter JWT injection | Unblocks zero-config local auth. Mint a JWT per heartbeat, pass as PAPERCLIP_API_KEY. |
| P1 | Invite link + onboarding endpoint | POST /api/companies/:id/invites, GET /api/invite/:token, POST /api/invite/:token/register. |
| P1 | Approval flow | UI + API for reviewing and approving pending agent registrations. |
| P2 | OpenClaw integration | First real external agent onboarding via invite link. |
| P3 | CLI auth flow | paperclipai auth login for developer-managed remote agents. |
P0 Implementation Plan
See doc/plans/agent-authentication-implementation.md for the P0 local JWT execution plan.
Open Questions
- JWT signing key rotation: How do we rotate the signing key without
invalidating in-flight heartbeats? - Invite link expiry: Should invite links be single-use or multi-use? Time-limited?
- Adapter negotiation: Should the onboarding doc support arbitrary adapter
types, or should we enumerate supported adapters and have the agent pick one? - Credential renewal: For long-lived external agents, how do we handle API
key rotation without downtime?
File: doc/plans/2026-02-18-agent-authentication-implementation.md
Agent Authentication — P0 Local Adapter JWT Implementation
Scope
- In-scope adapters:
claude_local,codex_local. - Goal: zero-configuration auth for local adapters while preserving static keys for all other call paths.
- Out-of-scope for P0: rotation UX, per-device revocation list, and CLI onboarding.
1) Token format and config
- Use HS256 JWTs with claims:
sub(agent id)company_idadapter_typerun_idiatexp- optional
jti(run token id)
- New config/env settings:
PAPERCLIP_AGENT_JWT_SECRETPAPERCLIP_AGENT_JWT_TTL_SECONDS(default:172800)PAPERCLIP_AGENT_JWT_ISSUER(default:paperclip)PAPERCLIP_AGENT_JWT_AUDIENCE(default:paperclip-api)
2) Dual authentication path in `actorMiddleware`
- Keep the existing DB key lookup path unchanged (
agent_api_keyshash lookup). - If no DB key matches, add JWT verification in
server/src/middleware/auth.ts. - On JWT success:
- set
req.actor = { type: "agent", agentId, companyId }. - optionally guard against terminated agents.
- set
- Continue board fallback for requests without valid authentication.
3) Opt-in adapter capability
- Extend
ServerAdapterModule(likelypackages/adapter-utils/src/types.ts) with a capability flag:supportsLocalAgentJwt?: true.
- Enable it on:
server/src/adapters/registry.tsforclaude_localandcodex_local.
- Keep
process/httpadapters unset for P0. - In
server/src/services/heartbeat.ts, when adapter supports JWT:- mint JWT per heartbeat run before execute.
- include token in adapter execution context.
4) Local env injection behavior
In:
packages/adapters/claude-local/src/server/execute.tspackages/adapters/codex-local/src/server/execute.ts
inject
PAPERCLIP_API_KEYfrom context token.
- Preserve existing behavior for explicit user-defined env vars in
adapterConfig.env:- if user already sets
PAPERCLIP_API_KEY, do not overwrite it.
- if user already sets
- Continue injecting:
PAPERCLIP_AGENT_IDPAPERCLIP_COMPANY_IDPAPERCLIP_API_URL
5) Documentation updates
- Update operator-facing docs to remove manual key setup expectation for local adapters:
skills/paperclip/SKILL.mdcli/src/commands/heartbeat-run.tsoutput/help examples if they mention manual API key setup.
6) P0 acceptance criteria
- Local adapters authenticate without manual
PAPERCLIP_API_KEYconfig. - Existing static keys (
agent_api_keys) still work unchanged. - Auth remains company-scoped (
req.actor.companyIdused by existing checks). - JWT generation and verification errors are logged as non-leaking structured events.
- Scope remains local-only (
claude_local,codex_local) while adapter capability model is generic.
File: doc/plans/2026-02-19-agent-mgmt-followup-plan.md
Agent Management Follow-up Plan (CEO Patch + Config Rollback + Issue↔Approval Linking)
Status: Proposed
Date: 2026-02-19
Context: Follow-up from run faeab00e-7857-4acc-b2b2-86f6d078adb4
1. Investigation Findings
1.1 Why CEO PATCH failed
Root cause is explicit route logic:
server/src/routes/agents.tscurrently blocks any agent patching another agent:if (req.actor.type === "agent" && req.actor.agentId !== id) { ... "Agent can only modify itself" }
So even though the CEO has hire permission, the route still enforces old self-only patch behavior.
1.2 Why comment quality felt wrong
skills/paperclip/SKILL.mdandskills/paperclip/references/api-reference.mddo not currently require markdown formatting quality for status comments (links, structure, readable updates).- Agents therefore produce plain prose comments with raw IDs, not linked entities.
1.3 Issue↔Approval linkage gap
- There is no direct DB relation between issues and approvals today.
- Approval payloads may include contextual IDs, but this is not canonical linkage.
- UI pages cannot reliably cross-link issue/approval without manual copy-paste IDs.
1.4 Config rollback gap
- Agent config updates currently overwrite state with no dedicated revision history table.
- There is activity logging, but no first-class config version ledger or rollback endpoint.
2. Product/Behavior Changes
2.1 Allow CEO to patch other same-company agents
Target behavior:
- Board: full patch rights.
- CEO: can patch agents in same company.
- Other agents: self-only patch unless explicitly granted future permission.
Note:
- Keep company boundary checks strict.
- Keep privileged fields separately governed.
2.2 Add first-class agent configuration revision log + rollback
Every config-affecting mutation must create a revision record with:
- before snapshot
- after snapshot
- actor info (user/agent)
- optional reason/comment
- source run ID (if available)
Rollback must be one API call that restores a prior revision atomically.
2.3 Enforce markdown and links for issue comments in skills
Skill guidance should require:
- short markdown structure (
Summary,Actions,Next) - links to created/updated entities when relevant
- avoid raw IDs without links
2.4 Add explicit Issue↔Approval linkage (many-to-many)
Implement canonical join model so one issue can link many approvals and one approval can link many issues.
3. Data Model Plan
3.1 New table: `agent_config_revisions`
Columns:
iduuid pkcompany_iduuid fkagent_iduuid fkrevision_numberint (monotonic per agent)reasontext nullchanged_by_agent_iduuid nullchanged_by_user_idtext nullrun_iduuid nullbefore_snapshotjsonb not nullafter_snapshotjsonb not null- timestamps
Indexes:
(company_id, agent_id, revision_number desc)(agent_id, created_at desc)
3.2 New table: `issue_approvals`
Columns:
iduuid pkcompany_iduuid fkissue_iduuid fkapproval_iduuid fkrelationshiptext defaultcontextlinked_by_agent_iduuid nulllinked_by_user_idtext null- timestamps
Constraints:
- unique
(company_id, issue_id, approval_id)
Indexes:
(company_id, issue_id)(company_id, approval_id)
4. API Plan
4.1 Agent PATCH authz fix
Update PATCH /api/agents/:id authz matrix:
- board: allow
- agent role
ceoin same company: allow - otherwise: self only
4.2 Separate privileged patch fields
Protect these from generic PATCH by non-board/non-ceo:
permissionsstatustransitions outside allowed scope
(Continue using dedicated permission route for permission edits.)
4.3 Config revision APIs
Add:
GET /api/agents/:id/config-revisionsGET /api/agents/:id/config-revisions/:revisionIdPOST /api/agents/:id/config-revisions/:revisionId/rollback
Behavior:
- rollback writes a new revision entry (does not mutate history)
- rollback response includes resulting active config
4.4 Issue↔Approval link APIs
Add:
GET /api/issues/:id/approvalsPOST /api/issues/:id/approvals(link existing approval)DELETE /api/issues/:id/approvals/:approvalIdGET /api/approvals/:id/issues
4.5 Auto-link on approval creation
Extend create payloads to optionally include issue context:
POST /api/companies/:companyId/approvalssupportsissueIdorissueIdsPOST /api/companies/:companyId/agent-hiressupportssourceIssueIdorsourceIssueIds
Server behavior:
- create approval first
- insert link rows in
issue_approvals
5. UI Plan
5.1 Agent page
Add configuration history panel on AgentDetail:
- revision list
- diff preview
- rollback button with confirmation
5.2 Approval page and Issue page cross-links
- On approval detail: show linked issues with links
- On issue detail: show linked approvals with links
- link/unlink actions in board context
5.3 Better comment UX cues
No hard editor enforcement initially; update helper text and templates to encourage linked markdown updates.
6. Skill Updates
6.1 `skills/paperclip/SKILL.md`
Add comment standard:
- Use markdown sections
- Include links for related entities:
- approval:
/approvals/{id} - agent:
/agents/{id} - issue:
/issues/{id}
- approval:
6.2 `skills/paperclip-create-agent/SKILL.md`
Require:
- include
sourceIssueIdwhen hire is created from an issue - comment back to issue with markdown + links to approval and pending agent
7. Implementation Phases
Phase A: Authz + safety hardening
- Fix CEO patch authz in agent route
- Restrict privileged generic patch fields
- Add tests for authz matrix
Phase B: Config revision ledger
- Add
agent_config_revisions - Write-on-change for all relevant agent mutations
- rollback endpoints + tests
Phase C: Issue↔Approval linking
- Add
issue_approvals - add link APIs + auto-link behavior
- update approvals/issues UI cross-links
Phase D: Skill guidance
- update skills for markdown/link expectations and sourceIssue linking
8. Acceptance Criteria
- CEO can patch CTO (same company) successfully.
- Every config change creates a retrievable revision.
- Rollback restores prior config in one action and creates a new revision record.
- Issue and approval pages show stable bidirectional links from canonical DB relation.
- Agent comments in hiring workflow use markdown and include entity links.
9. Risks and Mitigations
- Risk: permission escalation via generic PATCH.
- Mitigation: isolate privileged fields and validate actor scope.
- Risk: rollback corruption.
- Mitigation: snapshot-before/snapshot-after + transaction + tests.
- Risk: ambiguous linking semantics.
- Mitigation: explicit join table + unique constraints + typed relationship field.
File: doc/plans/2026-02-19-ceo-agent-creation-and-hiring.md
CEO Agent Creation and Hiring Governance Plan (V1.1)
Status: Proposed
Date: 2026-02-19
Owner: Product + Server + UI + Skills
1. Goal
Enable a CEO agent to create new agents directly, with lightweight but explicit governance:
- Company-level toggle: new hires require board approval (default ON).
- Agent-level permission:
can_create_agents(default ON for CEO, OFF for everyone else). - Clear hire workflow with draft/limbo state until approval.
- Config reflection so hiring agents can inspect available adapter configuration and compare existing agent configs (including self).
- Approval collaboration flow with comments, revision requests, and audit trail.
2. Current State (Repo Reality)
- Agent creation is board-only at
POST /api/companies/:companyId/agents(server/src/routes/agents.ts). - Approvals support
pending/approved/rejected/cancelledandhire_agent+approve_ceo_strategy(packages/shared/src/constants.ts,server/src/services/approvals.ts). hire_agentapproval currently creates the agent only on approval; there is no pre-created limbo agent.- There is no agent permissions system today.
- There is no company setting for "new hires require board approval".
- Approvals have no comment thread or revision-request state.
- Inbox and Approvals UIs support approve/reject only; no approval detail route exists in app routes.
- Agent adapter configuration is free-form JSON; no runtime reflection endpoint exists for machine-readable or text discovery.
3. Product Decisions
3.1 Company setting
Add company setting:
requireBoardApprovalForNewAgents: boolean- Default:
true - Editable only in company advanced settings (not onboarding/company creation flow UI)
3.2 Agent permissions
Introduce lightweight permission model with one explicit permission now:
can_create_agents: boolean
Defaults:
- CEO:
true - Everyone else:
false
Authority:
- Board can edit permissions for any agent.
- CEO can edit permissions for agents in same company.
No broader RBAC system in this phase.
3.3 Limbo state for hires
Introduce dedicated non-operational status:
pending_approval
Meaning:
- Agent record exists in org tree and can be reviewed.
- Agent cannot run, receive assignments, create keys, or be resumed to active states until approved.
4. Data Model Changes
4.1 `companies`
Add column:
require_board_approval_for_new_agentsboolean not null defaulttrue
Sync required:
packages/db/src/schema/companies.tspackages/shared/src/types/company.tspackages/shared/src/validators/company.ts- UI company API type usage and company advanced settings form
4.2 `agents`
Add columns:
permissionsjsonb not null default{}- status value expansion to include
pending_approval
Sync required:
packages/db/src/schema/agents.tspackages/shared/src/constants.ts(AGENT_STATUSES)packages/shared/src/types/agent.tspackages/shared/src/validators/agent.ts- status badges, filters, and lifecycle controls in UI
4.3 `approvals`
Keep approval as central governance record; extend workflow support:
- add status
revision_requested - ensure payload for hire approvals contains:
agentIdrequestedByAgentIdrequestedConfigurationSnapshot
4.4 New `approval_comments` table
Add discussion thread for approvals:
id,company_id,approval_id,author_agent_id,author_user_id,body, timestamps
Purpose:
- review comments
- revision requests
- rationale for approve/reject
- permanent audit trail
5. API and AuthZ Plan
5.1 Permission helpers
Add server-side authz helpers:
assertCanCreateAgents(req, companyId)assertCanManageAgentPermissions(req, companyId)
Rules:
- Board always passes.
- Agent passes
can_create_agentscheck if self permission true and same company. - Permission management by CEO or board.
5.2 Hire creation flow
Add route:
POST /api/companies/:companyId/agent-hires
Behavior:
- Requires
can_create_agents(or board). - Creates agent row first.
- If company setting requires approval:
- create agent with
status=pending_approval - create
approvals(type=hire_agent,status=pending,payload.agentId=...) - return both agent + approval
- create agent with
- If setting disabled:
- create agent as
idle - no approval record required
- create agent as
Board may continue using direct create route, but this route becomes canonical for CEO/agent-led hiring.
5.3 Approval workflow endpoints
Add/extend:
GET /api/approvals/:idPOST /api/approvals/:id/request-revisionPOST /api/approvals/:id/resubmitGET /api/approvals/:id/commentsPOST /api/approvals/:id/comments
Update existing approve/reject semantics:
- approve of hire transitions linked agent
pending_approval -> idle - reject keeps linked agent in non-active state (
pending_approvalorterminated/purged later)
5.4 Agent permission management endpoints
Add:
PATCH /api/agents/:id/permissions
Supports initial key only:
{ "canCreateAgents": boolean }
5.5 Read config endpoints (protected)
Add permission-gated config-read endpoints:
GET /api/companies/:companyId/agent-configurationsGET /api/agents/:id/configuration
Access:
- board
- CEO
- any agent with
can_create_agents
Security:
- redact obvious secret values from adapter config (
env, API keys, tokens, JWT-looking values) - include redaction marker in response
5.6 Reflection endpoints for adapter configuration
Add plain-text reflection routes:
GET /llms/agent-configuration.txtGET /llms/agent-configuration/:adapterType.txt
Index file includes:
- installed adapter list for this Paperclip instance
- per-adapter doc URLs
- brief "how to hire" API sequence links
Per-adapter file includes:
- required/optional config keys
- defaults
- field descriptions
- safety notes
- example payloads
Auth:
- same gate as config-read endpoints (board/CEO/
can_create_agents).
6. Adapter Protocol Extension
Extend ServerAdapterModule contract to expose config docs:
agentConfigurationDoc(string) orgetAgentConfigurationDoc()
Implement in:
packages/adapters/claude-localpackages/adapters/codex-localserver/src/adapters/registry.ts
This is required so reflection is generated from installed adapters, not hardcoded.
7. UI Plan
7.1 Company advanced settings
In Companies UI, add advanced settings panel/modal with:
- toggle: "Require board approval for new agent hires" (default on)
Not shown in onboarding flow.
7.2 Agent permissions UI
In Agent Detail (board/CEO context):
- permissions section
- toggle for "Can create new agents"
7.3 Hire UX
Add "Hire Agent" flow (for CEO/authorized agents):
- choose role/name/title/reportsTo
- compose initial prompt/capabilities
- inspect adapter reflection docs
- inspect existing related agent configurations
- submit hire
State messaging:
- if approval required: show "Pending board approval"
- if not required: show active-ready state
7.4 Approvals UX
Add approval detail page and expand inbox integration:
/approvals/:approvalId- threaded comments
- revision request action
- approve/reject with decision note
- activity timeline (created, revisions, decisions)
7.5 Disapproved agent cleanup
Provide board-only destructive action in approval detail:
- "Delete disapproved agent"
- explicit confirmation dialog
- preserves approval + comment history (audit)
8. New Skill: `paperclip-create-agent`
Create new skill directory:
skills/paperclip-create-agent/SKILL.mdskills/paperclip-create-agent/references/api-reference.md
Skill responsibilities:
- Discover available adapter configuration via
/llms/agent-configuration*.txt - Read existing agent configurations (including self and related roles)
- Propose best-fit config for current environment
- Draft high-quality initial prompt for new agent
- Set manager/reporting line
- Execute hire API flow
- Handle revision loop with board comments
Also update skills/paperclip/SKILL.md to reference this skill for hiring workflows.
9. Enforcement and Invariants
New/updated invariants:
pending_approvalagents cannot:- be invoked/woken
- be assigned issues
- create or use API keys
- transition to active lifecycle states except through hire approval
- approval transitions:
pending -> revision_requested | approved | rejected | cancelledrevision_requested -> pending | rejected | cancelled
- every mutation writes
activity_logrecords.
10. Implementation Phases
Phase 1: Contracts and migration
- DB schema updates (
companies,agents, approvals status expansion,approval_comments) - shared constants/types/validators updates
- migration generation and typecheck
Phase 2: Server authz + hire flow
- permission resolver and authz guards
agent-hiresroute- limbo status enforcement in heartbeat/issue/key flows
- approval revision/comment endpoints
Phase 3: Reflection and config-read APIs
- adapter protocol docs support
/llms/agent-configuration*.txtroutes- protected config-read endpoints with redaction
Phase 4: UI and skilling
- company advanced setting UI
- permission controls
- approval detail + comments/revision flow in inbox/approvals
- disapproved agent delete flow
paperclip-create-agentskill + docs updates
11. Test Plan
Server tests:
- permission gate tests for hire/config-read/permission-update endpoints
- hire creation behavior with company setting on/off
- approval transitions including revision cycle
- pending_approval enforcement across wakeup/invoke/assignment/keys
- config redaction tests
UI tests:
- advanced setting toggle persistence
- approval detail comment/revision interactions
- hire flow states (pending vs immediate)
Repo verification before merge:
pnpm -r typecheckpnpm test:runpnpm build
12. Risks and Mitigations
- Risk: leaking secrets through agent config reads.
- Mitigation: strict redaction pass + allowlist/denylist tests.
- Risk: status explosion complexity.
- Mitigation: single added status (
pending_approval) with explicit transition guards.
- Mitigation: single added status (
- Risk: approval flow regressions.
- Mitigation: centralize transition logic in approval service and back it with tests.
13. Open Decisions (Default Recommendation)
Should board direct-create bypass approval setting?
Recommendation: yes, board is explicit governance override.Should non-authorized agents still see basic agent metadata?
Recommendation: yes (name/role/status), but configuration fields stay restricted.On rejection, should limbo agent remain
pending_approvalor move toterminated?
Recommendation: move toterminatedon final reject; keep optional hard delete action for cleanup.
File: doc/plans/2026-02-20-issue-run-orchestration-plan.md
Issue Run Orchestration Plan
Context
We observed cascaded wakeups on a single issue (for example PAP-39) that produced multiple runs at once:
- assignee self-wake from
issue_commented - mention wake to manager/CTO from
issue_comment_mentioned - overlapping runs on the same issue
Current behavior is run-centric and agent-centric. It coalesces per-agent+task in heartbeat.wakeup, but does not enforce a single active execution slot per issue across all agents.
What We Know Today
- The only reliable issue/run linkage today is derived from
heartbeat_runs.context_snapshot.issueIdwith run statusqueuedorrunning. checkoutRunIdon issues is a work-ownership lock, not an orchestration lock.- Wakeups are created from multiple routes (
issues,approvals,agents) and all funnel throughheartbeat.wakeup.
Goals
- Prevent self-wake cascades for the same issue when the target agent has the same normalized name as the currently active issue runner.
- Allow cross-agent wake requests, but do not run them until the current issue runner exits.
- Guarantee at most one active (queued or running) execution owner per issue at a time.
- Keep this enforcement centralized in orchestration (not prompt/skill rules).
Non-Goals
- Replacing checkout semantics for code-change ownership.
- Changing manager escalation policy itself.
- Enforcing uniqueness of agent names globally (handled as a separate governance decision).
Proposed Model
Use an explicit issue-level orchestration lock on issues.
New Issue Properties
executionRunId: uuid | null(FK toheartbeat_runs.id,ON DELETE SET NULL)executionAgentNameKey: text | null(normalized lowercase/trimmed agent name)executionLockedAt: timestamptz | null
executionRunId is the canonical “who currently owns orchestration for this issue” field.
Orchestration Rules
Rule A: No Self-Wake by Same Agent Name
If a wakeup is issue-scoped and issues.executionRunId points to an active run whose executionAgentNameKey matches the waking agent name key:
- do not create a new heartbeat run
- write wakeup request as
coalescedwith reasonissue_execution_same_name - return existing run reference
Rule B: Different Name May Wake, But Waits
If an issue has an active execution lock held by a different agent-name key:
- accept the wake request
- persist request as deferred (new wakeup status
deferred_issue_execution) - do not create a run yet
When the active issue run finishes, promote the oldest deferred request for that issue into a queued run and transfer executionRunId.
Rule C: One Active Execution Owner Per Issue
For issue-scoped wakeups, run creation is done only while holding a transaction lock on the issue row. This ensures only one queued/running run can become owner at a time.
Implementation Plan
Phase 1: Schema + Shared Contracts
- Add issue columns:
execution_run_id,execution_agent_name_key,execution_locked_at. - Extend shared
Issuetype inpackages/shared/src/types/issue.ts. - Add migration and export updates.
Phase 2: Centralize Issue Execution Gate in `heartbeat.wakeup`
- In
enqueueWakeup, deriveissueIdfrom context/payload as today. - If no
issueId, keep existing behavior. - If
issueIdexists:- transaction +
SELECT ... FOR UPDATEon issue row - resolve/repair stale
executionRunId(if referenced run is notqueued|running, clear lock) - apply Rule A/Rule B/Rule C
- transaction +
- Name normalization helper:
agentNameKey = agent.name.trim().toLowerCase()
Phase 3: Deferred Queue Promotion on Run Finalization
- On run terminal states (
succeeded,failed,cancelled, orphan reaped):- if run owns
issues.executionRunId, clear issue lock - promote oldest deferred issue wakeup to queued run
- set issue lock to the promoted run
- trigger
startNextQueuedRunForAgent(promotedAgentId)
- if run owns
Phase 4: Route Hygiene (“Apply Everywhere”)
- Keep route-side wakeup dedupe by agent id, but rely on heartbeat gate as source of truth.
- Ensure all issue-related wakeup calls include
issueIdin payload/context snapshot. - Add explicit reason codes so logs make suppression/deferral obvious.
Phase 5: Tests
- Unit tests for
heartbeat.wakeup:- same-name self-wake suppressed
- different-name wake deferred
- lock released and deferred wake promoted on owner completion
- stale lock recovery
- Integration tests:
- comment with
@CTOduring active assignee run does not create concurrent active run - only one active owner per issue at any time
- comment with
- Regression tests:
- non-issue wakeups unchanged
- existing assignment/timer behavior unchanged for tasks without issue context
Telemetry + Debuggability
- Add structured reasons in
agent_wakeup_requests.reason:issue_execution_same_nameissue_execution_deferredissue_execution_promoted
- Add activity log details for lock transfer events:
- from run id / to run id / issue id / agent name key
Rollout Strategy
- Ship schema + feature flag (
ISSUE_EXECUTION_LOCK_ENABLED) default off. - Enable in dev and verify PAP-39 style scenarios.
- Enable in staging with high log verbosity.
- Enable by default after stable run.
Acceptance Criteria
- A single issue never has more than one active execution owner run (
queued|running) at once. - Same-name self-wakes for the same issue are suppressed, not spawned.
- Different-name wakeups are accepted but deferred until issue execution lock is released.
- Mentioning CTO during an active issue run does not start CTO concurrently on that issue.
- Parallelism remains available via separate issues/subissues.
Follow-Up (Separate but Related)
Checkout conflict logic should be corrected independently so assignees with checkoutRunId = null can acquire checkout by current run id without false 409 loops.
File: doc/plans/2026-02-20-storage-system-implementation.md
Storage System Implementation Plan (V1)
Status: Draft
Owner: Backend + UI
Date: 2026-02-20
Goal
Add a single storage subsystem for Paperclip that supports:
- local disk storage for single-user local deployment
- S3-compatible object storage for cloud deployment
- a provider-agnostic interface for issue images and future file attachments
V1 Scope
- First consumer: issue attachments/images.
- Storage adapters:
local_diskands3. - Files are always company-scoped and access-controlled.
- API serves attachment bytes through authenticated Paperclip endpoints.
Out of Scope (This Draft)
- Public unauthenticated object URLs.
- CDN/signed URL optimization.
- Image transformations/thumbnails.
- Malware scanning pipeline.
Key Decisions
- Default local path is under instance root:
~/.paperclip/instances//data/storage. - Object bytes live in storage provider; metadata lives in Postgres.
assetsis generic metadata table;issue_attachmentslinks assets to issues/comments.- S3 credentials come from runtime environment/default AWS provider chain, not DB rows.
- All object keys include company prefix to preserve hard tenancy boundaries.
Phase 1: Shared Config + Provider Contract
Checklist (Per File)
-
packages/shared/src/constants.ts: addSTORAGE_PROVIDERSandStorageProvidertype. -
packages/shared/src/config-schema.ts: addstorageConfigSchemawith:- provider:
local_disk | s3 - localDisk.baseDir
- s3.bucket, s3.region, s3.endpoint?, s3.prefix?, s3.forcePathStyle?
- provider:
-
packages/shared/src/index.ts: export new storage config/types. -
cli/src/config/schema.ts: ensure re-export includes new storage schema/types. -
cli/src/commands/configure.ts: addstoragesection support. -
cli/src/commands/onboard.ts: initialize default storage config. -
cli/src/prompts/storage.ts: new prompt flow for local disk vs s3 settings. -
cli/src/prompts/index(if present) or direct imports: wire new storage prompt. -
server/src/config.ts: load storage config and resolve home-aware local path. -
server/src/home-paths.ts: addresolveDefaultStorageDir(). -
doc/CLI.md: documentconfigure --section storage. -
doc/DEVELOPING.md: document default local storage path and overrides.
Acceptance Criteria
paperclipai onboardwrites a validstorageconfig block by default.paperclipai configure --section storagecan switch between local and s3 modes.- Server startup reads storage config without env-only hacks.
Phase 2: Server Storage Subsystem + Providers
Checklist (Per File)
-
server/src/storage/types.ts: define provider + service interfaces. -
server/src/storage/service.ts: provider-agnostic service (key generation, validation, stream APIs). -
server/src/storage/local-disk-provider.ts: implement local disk provider with safe path resolution. -
server/src/storage/s3-provider.ts: implement S3-compatible provider (@aws-sdk/client-s3). -
server/src/storage/provider-registry.ts: provider lookup by configured id. -
server/src/storage/index.ts: export storage factory helpers. -
server/src/services/index.ts: exportstorageServicefactory. -
server/src/app.tsor route wiring point: inject/use storage service where needed. -
server/package.json: add AWS SDK dependency if not present.
Acceptance Criteria
- In
local_diskmode, uploading + reading a file round-trips bytes on disk. - In
s3mode, service canput/get/deleteagainst S3-compatible endpoint. - Invalid provider config yields clear startup/config errors.
Phase 3: Database Metadata Model
Checklist (Per File)
-
packages/db/src/schema/assets.ts: new generic asset metadata table. -
packages/db/src/schema/issue_attachments.ts: issue-to-asset linking table. -
packages/db/src/schema/index.ts: export new tables. -
packages/db/src/migrations/*: generate migration for both tables and indexes. -
packages/shared/src/types/issue.ts(or new asset types file): addIssueAttachmenttype. -
packages/shared/src/index.ts: export new types.
Suggested Columns
assets:id,company_id,provider,object_keycontent_type,byte_size,sha256,original_filenamecreated_by_agent_id,created_by_user_id, timestamps
issue_attachments:id,company_id,issue_id,asset_id,issue_comment_id(nullable), timestamps
Acceptance Criteria
- Migration applies cleanly on empty and existing local dev DB.
- Metadata rows are company-scoped and indexed for issue lookup.
Phase 4: Issue Attachment API
Checklist (Per File)
-
packages/shared/src/validators/issue.ts: add schemas for upload/list/delete attachment operations. -
server/src/services/issues.ts: add attachment CRUD helpers with company checks. -
server/src/routes/issues.ts: add endpoints:POST /companies/:companyId/issues/:issueId/attachments(multipart)GET /issues/:issueId/attachmentsGET /attachments/:attachmentId/contentDELETE /attachments/:attachmentId
-
server/src/routes/authz.ts: reuse/enforce company access for attachment endpoints. -
server/src/services/activity-log.tsusage callsites: log attachment add/remove mutations. -
server/src/app.ts: ensure multipart parsing middleware is in place for upload route.
API Behavior
- Enforce max size and image/content-type allowlist in V1.
- Return consistent errors:
400/401/403/404/409/422/500. - Stream bytes instead of buffering large payloads in memory.
Acceptance Criteria
- Board and same-company agents can upload and read attachments per issue permissions.
- Cross-company access is denied even with valid attachment id.
- Activity log records attachment add/remove actions.
Phase 5: UI Issue Attachment Integration
Checklist (Per File)
-
ui/src/api/issues.ts: add attachment API client methods. -
ui/src/api/client.ts: support multipart upload helper (no JSONContent-TypeforFormData). -
ui/src/lib/queryKeys.ts: add issue attachment query keys. -
ui/src/pages/IssueDetail.tsx: add upload UI + attachment list/query invalidation. -
ui/src/components/CommentThread.tsx: optional comment image attach or display linked images. -
packages/shared/src/types/index.ts: ensure attachment types are consumed cleanly in UI.
Acceptance Criteria
- User can upload an image from issue detail and see it listed immediately.
- Uploaded image can be opened/rendered via authenticated API route.
- Upload and fetch failures are visible to users (no silent errors).
Phase 6: CLI Doctor + Operational Hardening
Checklist (Per File)
-
cli/src/checks/storage-check.ts: add storage check (local writable dir, optional S3 reachability check). -
cli/src/checks/index.ts: export new storage check. -
cli/src/commands/doctor.ts: include storage check in doctor sequence. -
doc/DATABASE.mdordoc/DEVELOPING.md: mention storage backend behavior by deployment mode. -
doc/SPEC-implementation.md: add storage subsystem and issue-attachment endpoint contract.
Acceptance Criteria
paperclipai doctorreports actionable storage status.- Local single-user install works without extra cloud credentials.
- Cloud config supports S3-compatible endpoint without code changes.
Test Plan
Server Integration Tests
-
server/src/__tests__/issue-attachments.auth.test.ts: company boundary and permission tests. -
server/src/__tests__/issue-attachments.lifecycle.test.ts: upload/list/read/delete flow. -
server/src/__tests__/storage-local-provider.test.ts: local provider path safety and round-trip. -
server/src/__tests__/storage-s3-provider.test.ts: s3 provider contract (mocked client). -
server/src/__tests__/activity-log.attachments.test.ts: mutation logging assertions.
CLI Tests
-
cli/src/__tests__/configure-storage.test.ts: configure section writes valid config. -
cli/src/__tests__/doctor-storage-check.test.ts: storage health output and repair behavior.
UI Tests (if present in current stack)
-
ui/src/...: issue detail upload and error handling tests.
Verification Gate Before Merge
Run:
pnpm -r typecheck
pnpm test:run
pnpm buildIf any command is skipped, document exactly what was skipped and why.
Implementation Order
- Phase 1 and Phase 2 (foundation, no user-visible breakage)
- Phase 3 (DB contract)
- Phase 4 (API)
- Phase 5 (UI consumer)
- Phase 6 (doctor/docs hardening)
2. Official Technical Reference & Guides (paperclipai/paperclip-docs)
Paperclip Docs
Source for the Paperclip documentation site — user guides, API and CLI reference, adapter docs, and deployment notes.
Read the docs: https://docs.paperclip.ing/
What's inside
- Guides — Getting started, core concepts, and day-to-day usage.
- API reference — Control-plane endpoints and payload schemas.
- CLI reference —
paperclipcommand surface. - Adapters — Plugin authoring and the integrations catalogue.
- Deploy — Self-hosting, upgrades, and operational guidance.
The site is a single static shell that renders the Markdown files in docs/ directly — no framework, no build step required to read the raw pages.
Build and deployment
Build a release bundle locally with:
npm run docs:buildCloudflare Pages is connected directly to paperclipai/paperclip-docs through GitHub. There is no normal Wrangler publish step for this repo:
- Pushes to
maindeploy production athttps://docs.paperclip.ing/. - Pushes to other branches create Cloudflare Pages preview/canary deployments.
- Canary URLs are created by Cloudflare for each deployment, for example
https://92b9a99c.paperclip-docs-74t.pages.dev. Use the URL shown in the Cloudflare Pages deployment row or GitHub deployment/check for the pushed branch and commit.
Contributing
Spotted a typo, a broken link, or something that could be clearer? There are two easy paths, both linked from the footer of every docs page:
- Suggest an edit — opens the underlying Markdown file in GitHub's web editor. Make the change and submit a PR without leaving the browser.
- Report an issue — opens a prefilled Docs feedback issue with the page URL already attached.
For larger changes, fork the repo and open a PR against main. Screenshots live under docs/user-guides/screenshots/{light,dark}/ and should be provided in both themes when replacing UI captures.
Community
License
Copyright (c) 2026 Paperclip Community.
The Paperclip software is open source — see the main paperclip repository for its license.
The documentation in this repository is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0). You may read and share it for non-commercial purposes with attribution. Commercial use of any kind requires prior written permission from the copyright holders. See LICENSE for the full text.