Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. Management & Multi-Tenancy
Overview
The company is the first-order business entity in Paperclip. Every other business record (agents, goals, projects, issues, costs, activity) is scoped to exactly one company, and a single deployment can run many companies with complete data isolation. This feature covers the company lifecycle, per-company configuration, multi-company data boundaries, and company portability (export/import of entire organizations).
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Create/list/get/update/archive companies; switch between them; import/export orgs |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Operates strictly within its own company; must never see another company's data |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support creating a company with a name, description, status, and issue prefix/counter. | Must | The system shall support creating a company with a name, description, status, and issue prefix/counter. |
| FR-02MustThe system shall enforce that every business record belongs to exactly one company and that company boundaries are checked on every fetch/mutation. | Must | The system shall enforce that every business record belongs to exactly one company and that company boundaries are checked on every fetch/mutation. |
| FR-03MustThe system shall support listing, getting, updating, and archiving companies. | Must | The system shall support listing, getting, updating, and archiving companies. |
| FR-04Mustpaused \ | Must | The system shall maintain company status as active \ | paused \ | archived with pause reason and paused-at tracking. |
| FR-05ShouldThe system shall support per-company branding (brand color, logo) and feedback-sharing consent fields. | Should | The system shall support per-company branding (brand color, logo) and feedback-sharing consent fields. |
| FR-06ShouldThe system shall support exporting and importing entire companies (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Should | The system shall support exporting and importing entire companies (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
| FR-07ShouldThe system shall support per-company attachment size limits (`attachment_max_bytes`). | Should | The system shall support per-company attachment size limits (attachment_max_bytes). |
| FR-08MayThe system shall support per-company board-approval requirement flag for new agents (`require_board_approval_for_new_agents`). | May | The system shall support per-company board-approval requirement flag for new agents (require_board_approval_for_new_agents). |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustAgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys must not access other companies' data; cross-company reads/writes must be rejected. | Must | Security | AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys must not access other companies' data; cross-company reads/writes must be rejected. |
| NFR-02MustEvery company mutation must write an `activity_log` entry attributed to an actor. | Must | Auditability | Every company mutation must write an activity_log entry attributed to an actor. |
| NFR-03ShouldCompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. CRUD must meet the p95 < 250 ms latency target at 1k tasks/company. | Should | Performance | CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. CRUD must meet the p95 < 250 ms latency target at 1k tasks/company. |
Constraints
- Single-tenant deployment with a multi-company data model (one deployment, many isolated companies).
- BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. has full read/write across all companies in the deployment.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-01MustThe system shall support creating a company with a name, description, status, and issue prefix/counter.
- Given a board operator
- When they create a company with required fields
- Then a company row exists with status
active, a generated issue prefix, and a zeroed issue counter
- FR-02MustThe system shall enforce that every business record belongs to exactly one company and that company boundaries are checked on every fetch/mutation.
- Given two companies A and B and an agent key scoped to A
- When the agent attempts to read or mutate a B-scoped entity
- Then the request is rejected with
403/404and no B data is returned
- FR-04Mustpaused \
- Given an active company
- When it is paused
- Then
status=paused,paused_atis set, and a pause reason is recorded
- FR-06ShouldThe system shall support exporting and importing entire companies (agents, skills, projects, routines, issues) with secret scrubbing and collision handling.
- Given an exported company package
- When it is imported into a fresh deployment
- Then agents, skills, projects, routines, and issues are recreated with secrets scrubbed and id collisions handled
- NFR-01MustAgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys must not access other companies' data; cross-company reads/writes must be rejected.
- Given an agent API key for company A
- When it calls any endpoint scoped to company B
- Then the request is denied before any company B data is exposed
Conflicts
None identified yet.
Open Questions
- What is the exact set of entities included in company export/import, and how are secret references resolved on import?
Specification: CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. Management & Multi-Tenancy
Overview
Companies are top-level isolated tenants. Each company row carries configuration, branding, budget, and issue-counter state. CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. scoping is enforced by a company_id foreign key on every business table plus boundary checks in routes/services. Portability is provided by a markdown-first package contract rooted at COMPANY.md with .paperclip.yaml sidecar.
Architecture
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. ──► /api/companies (CRUD + archive)
│
▼
companies table ──► company_id FK on agents, goals, projects,
│ issues, cost_events, activity_log, secrets, ...
▼
per-company isolation enforced in services/routes
Data Models
companies
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK, not null | CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. identifier |
| name | text | not null | CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. name |
| description | text | null | Optional description |
| status | enum | not null | active \| paused \| archived |
| pause_reason | text | null | Reason when paused |
| paused_at | timestamptz | null | When paused |
| issue_prefix | text | not null | Prefix for issue identifiers (e.g. PAPA) |
| issue_counter | int | not null | Monotonic per-company issue counter |
| budget_monthly_cents | int | not null, default 0 | Monthly budget |
| spent_monthly_cents | int | not null, default 0 | Month-to-date spend |
| attachment_max_bytes | int | not null | Per-company attachment size cap |
| require_board_approval_for_new_agents | boolean | not null, default false | Governance flag |
| brand_color / branding | - | null | Branding fields |
API Contracts
POST /companies
Creates a company. Returns the created company.
GET /companies, GET /companies/:companyId, PATCH /companies/:companyId, PATCH /companies/:companyId/branding, POST /companies/:companyId/archive
Standard CRUD + branding + archive. All under /api. BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based.-only.
CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. import/export
Preview/apply endpoints for portable company packages (companies.ts, company-import-paths.ts, company-portability.ts service).
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Validation error |
| 403 | UNAUTHORIZED | Caller lacks company access |
| 404 | NOT_FOUND | CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. not found |
Sequences
Archive a company
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → PATCH/archive → companies(status=archived) → activity_log
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Tenancy model | Single-tenant deployment, multi-company data model | One deployment runs many isolated companies without multi-tenant infra |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. identifiers | Per-company prefix + counter | Human-readable, collision-free within a company |
Risks and Unknowns
- Export/import secret resolution and collision handling semantics need precise documentation.
Out of Scope
- Cloud-grade multi-tenant infra or centralized policy overlays (Pro/Enterprise).
requirements
- What is the exact set of entities included in company export/import, and how are secret references resolved on import?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Org Chart & Agents
Overview
Agents are the AI employees of a company. They have roles, titles, reporting lines, capabilities, budgets, permissions, and adapter configuration. Agents form a strict reporting tree (reports_to nullable root) with no multi-manager reporting and no cycles. This feature covers agent lifecycle, org structure, adapter/API-key configuration, pause/resume/terminate, and the board approval flow for hiring.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Hire (directly or via approval), configure, pause/resume/terminate agents; view org chart |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Proposes strategy; delegates work down the tree after board approval |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Has an identity, reporting manager, budget, and an adapter that receives heartbeats |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support creating an agent scoped to a company with name, role, title, adapter type/config, and `reports_to`. | Must | The system shall support creating an agent scoped to a company with name, role, title, adapter type/config, and reports_to. |
| FR-02MustThe system shall enforce a strict tree org graph: `reports_to` nullable root, agent and manager in the same company, and no cycles. | Must | The system shall enforce a strict tree org graph: reports_to nullable root, agent and manager in the same company, and no cycles. |
| FR-03Mustpaused \ | Must | The system shall manage agent status (active \ | paused \ | idle \ | running \ | error \ | pending_approval \ | terminated) with the defined transition rules. |
| FR-04MustThe system shall reject resuming a `terminated` agent. | Must | The system shall reject resuming a terminated agent. |
| FR-05MustThe system shall create agent API keys hashed at rest, showing plaintext once at creation, with revocation. | Must | The system shall create agent API keys hashed at rest, showing plaintext once at creation, with revocation. |
| FR-06MustThe system shall support pause/resume/terminate actions (board-only for terminate). | Must | The system shall support pause/resume/terminate actions (board-only for terminate). |
| FR-07ShouldThe system shall support a hire-agent approval flow requested by an agent and decided by the board. | Should | The system shall support a hire-agent approval flow requested by an agent and decided by the board. |
| FR-08Shouldfat`), permissions JSONB, and optional cheap-model profile lane. | Should | The system shall support per-agent runtime config, context mode (thin \ | fat), permissions JSONB, and optional cheap-model profile lane. |
| FR-09ShouldThe system shall track `last_heartbeat_at` and budget spent per agent. | Should | The system shall track last_heartbeat_at and budget spent per agent. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustOnly hashed API keys are stored; plaintext is shown once at creation. | Must | Security | Only hashed API keys are stored; plaintext is shown once at creation. |
| NFR-02MustAll agent mutations (hire, pause, resume, terminate, key ops) write `activity_log`. | Must | Auditability | All agent mutations (hire, pause, resume, terminate, key ops) write activity_log. |
Constraints
terminatedis irreversible.- AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. and manager must be in the same company.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-02MustThe system shall enforce a strict tree org graph: `reports_to` nullable root, agent and manager in the same company, and no cycles.
- Given an existing reporting tree
- When a cycle-creating
reports_tois attempted - Then the update is rejected with a
422/409and the tree remains acyclic
- FR-03Mustpaused \
- Given an agent in
running - When it is paused mid-run
- Then the run is gracefully cancelled then force-killed and status becomes
paused
- Given an agent in
- FR-05MustThe system shall create agent API keys hashed at rest, showing plaintext once at creation, with revocation.
- Given a new API key request
- When the key is created
- Then only the hash is persisted and the plaintext is returned exactly once
- NFR-01MustOnly hashed API keys are stored; plaintext is shown once at creation.
- Given the
agent_api_keystable - When inspected
- Then no row contains recoverable plaintext key material
- Given the
Conflicts
None identified yet.
Open Questions
- What adapter types are fully supported in V1 and which are plugin-only?
Specification: Org Chart & Agents
Overview
Agents live in a company-scoped strict reporting tree. Each agent carries adapter/runtime configuration, a status state machine, a monthly budget, and one or more hashed API keys. Hiring may go through a board approval. Built-in adapters cover process, http, local CLI tools (claude/codex/gemini/opencode/pi/cursor), and the OpenClaw gateway; external adapters load via the plugin flow.
Architecture
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. ──► /api/agents (CRUD, pause/resume/terminate, keys)
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. ──► /api/agents/:id/heartbeat/invoke (via API key)
│
▼
agents table (company_id, reports_to, status, adapter_config, budget)
│
▼
agent_api_keys (hashed) + approvals(hire_agent)
Data Models
agents
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. id |
| company_id | uuid | FK companies, not null | Scoping |
| name / role / title / icon | text | - | Identity |
| status | enum | not null | active \| paused \| idle \| running \| error \| pending_approval \| terminated |
| reports_to | uuid | FK agents, null | Manager (nullable root) |
| adapter_type | text | - | process, http, claude_local, codex_local, etc. |
| adapter_config | jsonb | not null | AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin).-specific config |
| runtime_config | jsonb | default {} |
Runtime policy incl. modelProfiles.cheap |
| context_mode | enum | default thin |
thin \| fat |
| budget_monthly_cents / spent_monthly_cents | int | not null | Budgets |
| permissions | jsonb | default {} |
Permissions |
| last_heartbeat_at | timestamptz | null | Liveness |
agent_api_keys
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| agent_id / company_id | uuid | FK, not null | Scoping |
| name | text | not null | Label |
| key_hash | text | not null | Hashed key (plaintext shown once) |
| last_used_at / revoked_at | timestamptz | null | Usage/revocation |
API Contracts
POST /companies/:companyId/agents, GET /agents/:agentId, PATCH /agents/:agentId
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. CRUD.
POST /agents/:agentId/pause | /resume | /terminate
Lifecycle transitions (terminate board-only).
POST /agents/:agentId/keys, POST /agents/:agentId/heartbeat/invoke
Key management and heartbeat invocation.
Error Responses
| Status | Code | Description |
|---|---|---|
| 409 | CONFLICT | Invalid status transition or cycle in reports_to |
| 422 | RULE_VIOLATION | e.g. resuming a terminated agent |
Sequences
Hire via approval
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. → approvals(hire_agent, pending) → BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. approve → create agent row + optional key → activity_log
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Org graph | Strict tree (reports_to) |
Simple, auditable delegation; no multi-manager ambiguity |
| Key storage | Hashed at rest | Plaintext shown once; safe at rest |
Risks and Unknowns
- Graceful-cancel-then-force-kill semantics during pause of an active run need careful adapter coordination.
Out of Scope
- Multi-board governance or role-based human permission granularity.
requirements
- What adapter types are fully supported in V1 and which are plugin-only?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). System (Issues)
Overview
Issues are the core task entity and the primary unit of work. Each issue traces to a company goal chain, has a single assignee, supports parent/child hierarchy, and uses atomic checkout to guarantee no double-work. Issues carry comments, documents, work products, attachments, labels, blocker relations, thread interactions, inbox/read state, and execution locks. Work modes (standard, ask, planning) control what execution is allowed.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Create/assign/force-reassign/cancel tasks; view kanban and audit trail |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Atomically check out assigned tasks, execute, comment, attach artifacts, delegate children |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Decompose approved plans into child issues |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01Musttodo \ | Must | The system shall support issue lifecycle with status backlog \ | todo \ | in_progress \ | in_review \ | done \ | blocked \ | cancelled and the defined transitions. |
| FR-02MustThe system shall enforce single-assignee ownership and require an assignee before `in_progress`. | Must | The system shall enforce single-assignee ownership and require an assignee before in_progress. |
| FR-03MustThe system shall provide atomic checkout that sets assignee, status `in_progress`, and execution locks via a single guarded SQL update, returning `409` on concurrent claims. | Must | The system shall provide atomic checkout that sets assignee, status in_progress, and execution locks via a single guarded SQL update, returning 409 on concurrent claims. |
| FR-04MustThe system shall enforce that every task traces to a company goal chain via `goal_id`, `parent_id`, or project-goal linkage. | Must | The system shall enforce that every task traces to a company goal chain via goal_id, parent_id, or project-goal linkage. |
| FR-05MustThe system shall support issue comments authored by agents or users. | Must | The system shall support issue comments authored by agents or users. |
| FR-06MustThe system shall support attachments (upload allowlist, inline vs download serving, range requests for video) and link them to issues/comments. | Must | The system shall support attachments (upload allowlist, inline vs download serving, range requests for video) and link them to issues/comments. |
| FR-07ShouldThe system shall support documents (markdown, append-only revisions) linked to issues by workflow key, with board lock/unlock. | Should | The system shall support documents (markdown, append-only revisions) linked to issues by workflow key, with board lock/unlock. |
| FR-08ShouldThe system shall support work products (artifact-backed and workspace-file references), labels, first-class blockers (`issue_relations`), and thread interactions (`request_confirmation`, `ask_user_questions`, `suggest_tasks`). | Should | The system shall support work products (artifact-backed and workspace-file references), labels, first-class blockers (issue_relations), and thread interactions (request_confirmation, ask_user_questions, suggest_tasks). |
| FR-09ShouldThe system shall enforce the non-terminal liveness rule: agent-owned non-terminal issues must have a live, waiting, or explicit recovery path. | Should | The system shall enforce the non-terminal liveness rule: agent-owned non-terminal issues must have a live, waiting, or explicit recovery path. |
| FR-10MayThe system shall support work modes `standard`, `ask`, and `planning`. | May | The system shall support work modes standard, ask, and planning. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustCheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. must be race-free under concurrent claims. | Must | Correctness | CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. must be race-free under concurrent claims. |
| NFR-02MustAll issue mutations write `activity_log`. | Must | Auditability | All issue mutations write activity_log. |
| NFR-03ShouldStandard issue CRUD p95 < 250 ms at 1k tasks/company. | Should | Performance | Standard issue CRUD p95 < 250 ms at 1k tasks/company. |
Constraints
- Terminal states are
doneandcancelled. in_progressrequires an assignee and setsstarted_at;done/cancelledset completion timestamps.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-03MustThe system shall provide atomic checkout that sets assignee, status `in_progress`, and execution locks via a single guarded SQL update, returning `409` on concurrent claims.
- Given two concurrent checkout requests for the same
todoissue - When both execute
- Then exactly one succeeds and the other gets
409with current owner/status
- Given two concurrent checkout requests for the same
- FR-06MustThe system shall support attachments (upload allowlist, inline vs download serving, range requests for video) and link them to issues/comments.
- Given a video attachment
- When a browser requests a byte range
- Then the server responds
206withContent-RangeandAccept-Ranges: bytes
- NFR-01MustCheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. must be race-free under concurrent claims.
- Given the checkout race regression test
- When run
- Then it passes (release-gate item)
Conflicts
None identified yet.
Open Questions
- Exact scope of the non-terminal liveness recovery actions and when issue-backed recovery is used vs source-scoped actions (see
doc/execution-semantics.md).
Specification: TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). System (Issues)
Overview
Issues are company-scoped tasks with a strict status state machine, single-assignee ownership, and atomic checkout. Rich collaboration (comments, documents, work products, attachments, labels, blockers, thread interactions) is layered on top. Execution locks and checkout/execution-run fields prevent double-work. A non-terminal liveness rule keeps work from silently stalling.
Architecture
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration./BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. ──► /api/issues (CRUD, checkout, release, force-release)
│
▼
issues (status, assignee, checkout/execution locks, parent_id, goal_id)
├── issue_comments
├── issue_documents ← documents / document_revisions
├── issue_attachments ← assets
├── issue_work_products
├── issue_relations (blockers)
├── issue_thread_interactions / issue_approvals
└── activity_log (every mutation)
Data Models
issues (core fields)
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| company_id | uuid | FK, not null | Scoping |
| project_id / goal_id / parent_id | uuid | FK, null | Traceability + hierarchy |
| title / description | text | - | Content |
| status | enum | not null | backlog \| todo \| in_progress \| in_review \| done \| blocked \| cancelled |
| priority | enum | - | critical \| high \| medium \| low |
| assignee_agent_id | uuid | FK, null | Single assignee |
| checkout_run_id / execution_run_id / execution_locked_at | - | null | Atomic checkout/execution locks |
| work_mode | text | default standard |
standard \| ask \| planning |
| issue_number / identifier | - | - | Per-company human id |
API Contracts
POST /issues/:issueId/checkout
Atomic checkout. Request: { agentId, expectedStatuses }. Single guarded SQL update; 409 on conflict.
POST /issues/:issueId/release | /issues/:issueId/admin/force-release
Release locks; force-release is board-only and writes issue.admin_force_release activity.
Documents, comments, attachments
GET/PUT /issues/:issueId/documents/:key (+lock/unlock/revisions), POST/GET /issues/:issueId/comments, POST /companies/:companyId/issues/:issueId/attachments, GET /attachments/:attachmentId/content, DELETE /attachments/:attachmentId.
Error Responses
| Status | Code | Description |
|---|---|---|
| 409 | CONFLICT | CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. conflict or invalid transition |
| 422 | RULE_VIOLATION | Semantic rule violation (e.g. in_progress without assignee) |
Sequences
Atomic checkout
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. → checkout(expectedStatuses) → UPDATE issues SET status=in_progress, assignee, locks WHERE id AND status IN(?) AND (assignee IS NULL OR assignee=agent) → rowcount 0 ? 409 : ok
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | Single guarded SQL update | Race-free without app-level locks |
| Communication | Tasks + comments only | No separate chat system (V1 decision) |
Risks and Unknowns
- Non-terminal liveness enforcement touches scheduler, watchdogs, and recovery actions; semantics are detailed in
doc/execution-semantics.md.
Out of Scope
- ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env./issue-level privacy ACLs (Pro/Enterprise).
requirements
- Exact scope of the non-terminal liveness recovery actions and when issue-backed recovery is used vs source-scoped actions (see
doc/execution-semantics.md).
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. Execution & Adapters
Overview
Agents do not run inside Paperclip; they are invoked via heartbeats that call an adapter. The scheduler wakes agents on their heartbeat schedule or on event triggers, the execution service resolves workspace/secrets/skills and invokes the adapter, and runs are tracked with status, context snapshots, events, and audit trails. Adapters cover process spawning, HTTP/webhook, local CLI sessions, the OpenClaw gateway, and external plugins.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | See run status, logs, costs; cancel runs; detect stuck/orphaned runs |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Receive heartbeats, execute, report status and cost events |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall invoke agents on per-agent schedules (`enabled`, `intervalSec` >= 30, `maxConcurrentRuns` clamped 1..50). | Must | The system shall invoke agents on per-agent schedules (enabled, intervalSec >= 30, maxConcurrentRuns clamped 1..50). |
| FR-02MustThe scheduler shall skip invocation when the agent is paused/terminated, a run is active, or the hard budget limit is hit. | Must | The scheduler shall skip invocation when the agent is paused/terminated, a run is active, or the hard budget limit is hit. |
| FR-03Mustrunning \ | Must | The system shall track heartbeat runs with status queued \ | running \ | succeeded \ | failed \ | cancelled \ | timed_out and invocation source scheduler \ | manual \ | callback. |
| FR-04MustThe process adapter shall spawn a child process, stream stdout/stderr to run logs, set status on exit/timeout, and cancel via SIGTERM then SIGKILL after a grace period. | Must | The process adapter shall spawn a child process, stream stdout/stderr to run logs, set status on exit/timeout, and cancel via SIGTERM then SIGKILL after a grace period. |
| FR-05MustThe HTTP adapter shall invoke via outbound request (2xx accepted, non-2xx failed) with optional async callback completion. | Must | The HTTP adapter shall invoke via outbound request (2xx accepted, non-2xx failed) with optional async callback completion. |
| FR-06ShouldThe system shall support context delivery modes `thin` (IDs/pointers) and `fat` (assignments, goal summary, budget snapshot, recent comments). | Should | The system shall support context delivery modes thin (IDs/pointers) and fat (assignments, goal summary, budget snapshot, recent comments). |
| FR-07ShouldThe system shall support built-in local CLI adapters (claude, codex, gemini, opencode, pi, cursor), the OpenClaw gateway, and external adapter plugins. | Should | The system shall support built-in local CLI adapters (claude, codex, gemini, opencode, pi, cursor), the OpenClaw gateway, and external adapter plugins. |
| FR-08ShouldThe system shall detect and recover orphaned/stuck runs automatically. | Should | The system shall detect and recover orphaned/stuck runs automatically. |
| FR-09MayThe system shall support an optional cheap-model profile lane restricted to status-only recovery coordination. | May | The system shall support an optional cheap-model profile lane restricted to status-only recovery coordination. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustHeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. invoke acknowledgement < 2 s for the process adapter. | Must | Reliability | HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. invoke acknowledgement < 2 s for the process adapter. |
| NFR-02ShouldRuns must produce structured logs, cost events, session state, and audit trails. | Should | Observability | Runs must produce structured logs, cost events, session state, and audit trails. |
Constraints
- Separate queue infrastructure is not required for V1; a lightweight in-process scheduler/worker handles heartbeat triggers, stuck-run detection, and budget checks.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-02MustThe scheduler shall skip invocation when the agent is paused/terminated, a run is active, or the hard budget limit is hit.
- Given an agent at its hard budget limit
- When its schedule fires
- Then no new run is invoked and the skip is recorded
- FR-04MustThe process adapter shall spawn a child process, stream stdout/stderr to run logs, set status on exit/timeout, and cancel via SIGTERM then SIGKILL after a grace period.
- Given a running process-adapter run
- When it is cancelled
- Then SIGTERM is sent and SIGKILL follows after the grace period
- NFR-01MustHeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. invoke acknowledgement < 2 s for the process adapter.
- Given a process-adapter heartbeat
- When invoked
- Then acknowledgement returns within 2 s
Conflicts
None identified yet.
Open Questions
- What are the exact stuck-run detection thresholds and orphan-recovery heuristics?
Specification: HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. Execution & Adapters
Overview
A lightweight in-process scheduler wakes agents; the heartbeat execution service resolves workspace, injects secrets, loads skills, and invokes the agent's adapter. Adapters implement a common interface (invoke, status, cancel). Built-ins cover process, http, local CLI, and the OpenClaw gateway; external adapters are loaded as plugins with zero hardcoded core imports.
Architecture
Scheduler ──► heartbeat service ──► adapter.invoke(agent, context)
(skip rules) (workspace, secrets, skills) │
├─ process: spawn, stream, SIGTERM/SIGKILL
├─ http: outbound req, callback
├─ local CLI: claude/codex/gemini/opencode/pi/cursor
├─ openclaw gateway
└─ external plugin
heartbeat_runs (status, context_snapshot) + heartbeat_run_events
Data Models
heartbeat_runs
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| company_id / agent_id | uuid | FK, not null | Scoping |
| invocation_source | enum | - | scheduler \| manual \| callback |
| status | enum | - | queued \| running \| succeeded \| failed \| cancelled \| timed_out |
| started_at / finished_at | timestamptz | null | Timing |
| error | text | null | Failure detail |
| external_run_id | text | null | AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). run id |
| context_snapshot | jsonb | null | Invocation context |
Supporting tables: heartbeat_run_events, heartbeat_run_watchdog_decisions, agent_wakeup_requests, agent_runtime_state, agent_task_sessions.
API Contracts
POST /agents/:agentId/heartbeat/invoke
Triggers a heartbeat run (manual source). Returns the run record.
AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). interface
interface AgentAdapter {
invoke(agent: AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration., context: InvocationContext): Promise<InvokeResult>;
status(run: HeartbeatRun): Promise<RunStatus>;
cancel(run: HeartbeatRun): Promise<void>;
}
Error Responses
| Status | Code | Description |
|---|---|---|
| 409 | CONFLICT | AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. not invokable (paused/terminated/budget-blocked/active run) |
Sequences
Scheduled heartbeat
Scheduler tick → skip rules check → heartbeat service → adapter.invoke → run status + events + cost events → activity_log
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Scheduler | In-process worker | No queue infra needed for V1 |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). loading | Dynamic plugin registry | Zero hardcoded adapter imports; pure dynamic loading |
Risks and Unknowns
- Cheap-model profile lane must be tightly constrained to status-only recovery to avoid deliverable work on a low-cost model.
Out of Scope
- Cloud-grade orchestration or external queue infrastructure.
requirements
- What are the exact stuck-run detection thresholds and orphan-recovery heuristics?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Governance & Approvals
Overview
Governance ensures nothing ships without board sign-off and that the board can intervene anywhere. It covers board approval workflows for hires and CEO strategy, execution policies with review/approval stages, decision tracking, budget hard-stops, agent pause/resume/terminate, full audit logging, and the scoped task-watchdog capacity for watched issue subtrees.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Approve/reject hires and CEO strategy; override any decision; pause/resume/terminate agents |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Proposes strategy that must be approved before delegated execution |
| Watchdog agent | Restore live task paths within a watched subtree (scoped, not board authority) |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01Mustrevision_requested \ | Must | The system shall support approval types hire_agent, approve_ceo_strategy, budget_override_required, request_board_approval with status pending \ | revision_requested \ | approved \ | rejected \ | cancelled. |
| FR-02MustThe system shall block CEO-created delegated work from active execution states until the CEO strategy is approved. | Must | The system shall block CEO-created delegated work from active execution states until the CEO strategy is approved. |
| FR-03MustThe board shall be able to pause/resume/terminate any agent, reassign or cancel any task, edit budgets, and approve/reject/cancel pending approvals at any time. | Must | The board shall be able to pause/resume/terminate any agent, reassign or cancel any task, edit budgets, and approve/reject/cancel pending approvals at any time. |
| FR-04MustEvery governance mutation shall write an auditable `activity_log` entry. | Must | Every governance mutation shall write an auditable activity_log entry. |
| FR-05ShouldThe system shall support execution policies with review/approval stages and decision tracking. | Should | The system shall support execution policies with review/approval stages and decision tracking. |
| FR-06ShouldThe system shall support a scoped task watchdog that may only restore live task paths inside one watched subtree, may resolve eligible `request_confirmation` plan confirmations, and is explicitly denied board/governance/secret/cross-company authority. | Should | The system shall support a scoped task watchdog that may only restore live task paths inside one watched subtree, may resolve eligible request_confirmation plan confirmations, and is explicitly denied board/governance/secret/cross-company authority. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustWatchdogs must not resolve board approvals, force-release locks, cancel active runs, or cross company boundaries. | Must | Security | Watchdogs must not resolve board approvals, force-release locks, cancel active runs, or cross company boundaries. |
| NFR-02MustWatchdog mutations must record watchdog id, source issue, run id, and stop fingerprint. | Must | Auditability | Watchdog mutations must record watchdog id, source issue, run id, and stop fingerprint. |
Constraints
- Watchdog authority is derived from persisted configuration and run context; custom instructions/prompt text cannot expand it.
- The watched subtree excludes
task_watchdog-origin issues and their descendants.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-02MustThe system shall block CEO-created delegated work from active execution states until the CEO strategy is approved.
- Given a CEO that drafted delegated tasks
- When strategy has not been approved
- Then those tasks cannot transition to active execution states
- NFR-01MustWatchdogs must not resolve board approvals, force-release locks, cancel active runs, or cross company boundaries.
- Given a task watchdog run
- When it attempts to approve a hire/budget approval or touch a company outside the watched subtree
- Then the action is denied and no probe issue/comment is created
Conflicts
None identified yet.
Open Questions
- Which interaction families beyond eligible
request_confirmationplan confirmations will watchdogs resolve in future iterations?
Specification: Governance & Approvals
Overview
Governance is enforced through the approvals table, execution policies, budget hard-stops, board override authority, and the scoped task-watchdog contract. BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. approvals are transactional (no lost decisions). Watchdogs are a narrow, persisted-configuration-derived capacity confined to one watched issue subtree.
Architecture
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. ──► /api/approvals (approve/reject/cancel)
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. ──► approvals(hire_agent | approve_ceo_strategy | request_board_approval)
│
▼
approvals table → activity_log
Watchdog ──► scoped mutations within watched subtree (comments, child issues, status,
blockers, eligible request_confirmation) → activity (watchdog metadata)
Data Models
approvals
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| company_id | uuid | FK, not null | Scoping |
| type | enum | - | hire_agent \| approve_ceo_strategy \| budget_override_required \| request_board_approval |
| requested_by_agent_id / requested_by_user_id | uuid | null | Requester |
| status | enum | - | pending \| revision_requested \| approved \| rejected \| cancelled |
| payload | jsonb | not null | ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. content |
| decision_note | text | null | Decision rationale |
| decided_by_user_id / decided_at | - | null | Decision attribution |
Supporting tables: approval_comments, issue_approvals, issue_execution_decisions, issue_watchdogs, heartbeat_run_watchdog_decisions, issue_recovery_actions.
API Contracts
GET/POST /companies/:companyId/approvals, POST /approvals/:approvalId/approve | /reject
ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. listing, creation, and decisions.
Error Responses
| Status | Code | Description |
|---|---|---|
| 403 | UNAUTHORIZED | Non-board actor attempting board-only decision |
| 409 | CONFLICT | Decision on an already-terminal approval |
Sequences
Hire approval
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. → approvals(hire_agent, pending) → BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. approve (transactional) → create agent + optional key → activity_log
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. writes | Transactional | No lost approval decisions (reliability target) |
| Watchdog scope | Persisted-config-derived, subtree-scoped | Safety: prompts cannot expand authority |
Risks and Unknowns
- Ensuring watchdog capability discovery comes only from wake metadata/denials (no probe issues) requires careful server enforcement and tests.
Out of Scope
- Multi-board governance or RBAC granularity for humans.
requirements
- Which interaction families beyond eligible
request_confirmationplan confirmations will watchdogs resolve in future iterations?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Budget & Cost Control
Overview
Paperclip tracks token and cost usage and enforces budgets to prevent runaway spend. Cost events are ingested per agent/issue/project/goal/provider/model, rolled up across dimensions, and checked against monthly UTC budgets. At the hard limit (100%) the agent is auto-paused and new invocations/checkout are blocked; a soft alert fires at 80%. The board can override by raising budgets or explicitly resuming.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Set company/agent budgets; monitor spend; override hard stops |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Report cost events for its own runs |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall ingest cost events (agent, issue, provider, model, input/output tokens, cost cents, occurred_at) with ownership checks. | Must | The system shall ingest cost events (agent, issue, provider, model, input/output tokens, cost cents, occurred_at) with ownership checks. |
| FR-02MustThe system shall validate non-negative token counts and `costCents >= 0`. | Must | The system shall validate non-negative token counts and costCents >= 0. |
| FR-03MustThe system shall support company and agent monthly budgets and optional project budgets. | Must | The system shall support company and agent monthly budgets and optional project budgets. |
| FR-04MustAt the hard limit (100%), the system shall set agent status to `paused`, block new checkout/invocation, and emit a high-priority activity event. | Must | At the hard limit (100%), the system shall set agent status to paused, block new checkout/invocation, and emit a high-priority activity event. |
| FR-05MustThe system shall roll up spend by company, agent, project, goal, and issue (read-time aggregation acceptable for V1). | Must | The system shall roll up spend by company, agent, project, goal, and issue (read-time aggregation acceptable for V1). |
| FR-06ShouldThe system shall surface a soft alert at the 80% threshold. | Should | The system shall surface a soft alert at the 80% threshold. |
| FR-07ShouldThe board shall be able to override a hard stop by raising the budget or explicitly resuming the agent. | Should | The board shall be able to override a hard stop by raising the budget or explicitly resuming the agent. |
| FR-08ShouldThe system shall expose a dashboard payload with month-to-date spend and budget utilization. | Should | The system shall expose a dashboard payload with month-to-date spend and budget utilization. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustRollups are aggregations of cost events and are never manually edited. | Must | Correctness | Rollups are aggregations of cost events and are never manually edited. |
| NFR-02ShouldCost summary queries should stay within latency targets; materialized rollups deferred. | Should | Performance | Cost summary queries should stay within latency targets; materialized rollups deferred. |
Constraints
- Budget period is a monthly UTC calendar window.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-04MustAt the hard limit (100%), the system shall set agent status to `paused`, block new checkout/invocation, and emit a high-priority activity event.
- Given an agent that reaches 100% of its monthly budget
- When spend crosses the limit
- Then the agent is paused, new invocations are blocked, and a high-priority activity event is emitted
- FR-04MustAt the hard limit (100%), the system shall set agent status to `paused`, block new checkout/invocation, and emit a high-priority activity event. (cont.)
- Given a budget-paused agent
- When a checkout is attempted
- Then it is rejected
- NFR-01MustRollups are aggregations of cost events and are never manually edited.
- Given the cost rollup queries
- When inspected
- Then they are pure aggregations of
cost_eventswith no manual overrides
Conflicts
None identified yet.
Open Questions
- Should materialized rollups be added if read latency exceeds targets at scale?
Specification: Budget & Cost Control
Overview
Cost events are the atomic input; all spend figures are aggregations. Budgets are monthly UTC windows scoped to company and agent (project optional). Enforcement runs in the heartbeat scheduler/checkout path: at the hard limit the agent is paused and invocations are blocked. A soft threshold warns at 80%.
Architecture
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. → POST /cost-events → cost_events (validated) → rollups (read-time aggregation)
Scheduler/checkout → budget check → hard limit? → pause agent + block + activity
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → PATCH /budgets, resume → override
Data Models
cost_events
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| company_id | uuid | FK, not null | Scoping |
| agent_id | uuid | FK, not null | Spending agent |
| issue_id / project_id / goal_id | uuid | FK, null | Attribution |
| provider / model | text | not null | Cost source |
| input_tokens / output_tokens | int | not null, default 0 | Usage |
| cost_cents | int | not null | Cost |
| occurred_at | timestamptz | not null | When it happened |
Supporting tables: budget_policies, budget_incidents, finance_events.
API Contracts
POST /companies/:companyId/cost-events
Ingest a cost event with ownership checks and validation.
GET /companies/:companyId/costs/summary | /by-agent | /by-project
Read-time aggregate rollups.
PATCH /companies/:companyId/budgets | PATCH /agents/:agentId/budgets
Set company/agent budgets.
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Negative tokens or cost |
| 403 | UNAUTHORIZED | AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. reporting cost for another company's entity |
Sequences
Hard-stop auto-pause
cost event ingest → spend crosses 100% → agent.status=paused → block checkout/invocation → high-priority activity
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Rollups | Read-time aggregation | Simplicity for V1; materialize later only if needed |
| Enforcement point | Scheduler + checkout path | Catches both scheduled and manual work |
Risks and Unknowns
- Concurrent cost ingestion near the threshold must not double-spend or miss the pause.
Out of Scope
- Revenue/expense accounting beyond model/token costs.
requirements
- Should materialized rollups be added if read latency exceeds targets at scale?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Routines & Schedules
Overview
Routines are recurring task definitions that fire on cron, webhook, or API triggers. Each routine execution creates a tracked issue and wakes the assigned agent, so regular work (customer support, reports, social) happens without manual kick-offs. Routines carry concurrency and catch-up policies, secret-aware env overlays, and revision history.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Configure recurring jobs, triggers, and concurrency policy |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Wake on routine execution and work the generated issue |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support routines with cron, webhook, and API triggers. | Must | The system shall support routines with cron, webhook, and API triggers. |
| FR-02MustEach routine execution shall create a tracked issue and wake the assigned agent. | Must | Each routine execution shall create a tracked issue and wake the assigned agent. |
| FR-03MustThe system shall support concurrency and catch-up policies per routine. | Must | The system shall support concurrency and catch-up policies per routine. |
| FR-04ShouldThe system shall support routine revisions and snapshotted routine env (secret-aware binding format). | Should | The system shall support routine revisions and snapshotted routine env (secret-aware binding format). |
| FR-05ShouldThe routine env overlay shall apply after project env and before Paperclip runtime-owned keys, resolving secret refs against the routine binding target. | Should | The routine env overlay shall apply after project env and before Paperclip runtime-owned keys, resolving secret refs against the routine binding target. |
| FR-06ShouldThe system shall track routine runs. | Should | The system shall track routine runs. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01ShouldMissed routine executions follow the configured catch-up policy. | Should | Reliability | Missed routine executions follow the configured catch-up policy. |
| NFR-02ShouldRoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. executions are visible as issues and runs. | Should | Auditability | RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. executions are visible as issues and runs. |
Constraints
- RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent.-owned secrets do not require direct bindings on the executing agent (resolved against the routine binding target).
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-02MustEach routine execution shall create a tracked issue and wake the assigned agent.
- Given a cron-triggered routine
- When the schedule fires
- Then a tracked issue is created and the assigned agent is woken
Conflicts
None identified yet.
Open Questions
- What are the exact concurrency and catch-up semantics when executions overlap?
Specification: Routines & Schedules
Overview
Routines are recurring definitions stored with their triggers, env, and revision history. A trigger fires a routine run that materializes an issue (with routine-scoped env overlay) and wakes the assigned agent. Routines are first-class company-scoped entities.
Architecture
Trigger (cron/webhook/API) → routine run → create issue (routine env overlay) → wake assigned agent
│
└─► routine_runs + activity_log
routine_revisions (snapshotted env) ← routine_triggers ← routines (company-scoped)
Data Models
routines / routine_revisions / routine_triggers / routine_runs
| Field | Type | Constraints | Description |
|---|---|---|---|
| routines.id / company_id | uuid | FK, not null | Scoping |
| routines.env | jsonb | - | Secret-aware env binding |
| routine_triggers | - | - | cron / webhook / API trigger config |
| routine_revisions | - | - | Snapshotted routine state |
| routine_runs | - | - | Per-execution tracking |
API Contracts
/api/routines (CRUD + triggers)
RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. management and trigger configuration. Route handler: server/src/routes/routines.ts, service: server/src/services/routines.ts.
Sequences
RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. execution
trigger fires → routine run → issue created (routine env overlay after project env, before runtime keys) → wake agent → routine_runs + activity_log
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Env overlay order | routine env after project env, before runtime-owned keys | Predictable precedence; routine-owned secrets resolve without agent bindings |
Risks and Unknowns
- Overlapping executions and catch-up behavior need precise documented semantics.
Out of Scope
- External calendar/scheduling integrations beyond cron/webhook/API.
requirements
- What are the exact concurrency and catch-up semantics when executions overlap?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Workspaces & Runtime
Overview
Workspaces give agents the right working directory and runtime context. ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. workspaces hold shared project state; execution workspaces are isolated git worktrees (often operator branches) where an agent runs. Runtime services (dev servers, preview URLs) and workspace operations (commands, diffs, uploads) support the execution. Environments and leases bind secret-aware env to execution targets.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Manage project workspaces, environments, runtime services |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Check out an execution workspace, run commands, publish diffs |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support project workspaces and isolated execution workspaces (git worktrees). | Must | The system shall support project workspaces and isolated execution workspaces (git worktrees). |
| FR-02MustThe system shall support workspace operations (commands, diffs, large uploads, git publishing). | Must | The system shall support workspace operations (commands, diffs, large uploads, git publishing). |
| FR-03MustThe system shall resolve execution workspace per issue (preference + settings fields on issues). | Must | The system shall resolve execution workspace per issue (preference + settings fields on issues). |
| FR-04ShouldThe system shall support runtime services (dev servers, preview URLs) and their lifecycle. | Should | The system shall support runtime services (dev servers, preview URLs) and their lifecycle. |
| FR-05ShouldThe system shall support environments with secret-aware env bindings and leases. | Should | The system shall support environments with secret-aware env bindings and leases. |
| FR-06ShouldThe system shall base fresh worktrees on `origin/master` and refresh unstarted reuses. | Should | The system shall base fresh worktrees on origin/master and refresh unstarted reuses. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01ShouldWorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. command authorization must scope commands to the workspace and agent. | Should | Security | WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. command authorization must scope commands to the workspace and agent. |
| NFR-02ShouldLarge workspace uploads and git publishing must succeed without truncation. | Should | Reliability | Large workspace uploads and git publishing must succeed without truncation. |
Constraints
- WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. runtime services are optional and provider-dependent (e.g. Daytona sandbox leases).
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-01MustThe system shall support project workspaces and isolated execution workspaces (git worktrees).
- Given an issue with an execution workspace preference
- When the agent checks out
- Then an isolated execution workspace is resolved/created for the run
Conflicts
None identified yet.
Open Questions
- Which sandbox providers are supported and how are leases reused (e.g. Daytona)?
Specification: Workspaces & Runtime
Overview
Workspaces split into project workspaces (shared project state) and execution workspaces (isolated git worktrees per run). Runtime services run dev servers/preview URLs; environments bind secret-aware env to execution targets via leases. WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. operations expose commands, diffs, and uploads to agents under authorization.
Architecture
IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. (execution_workspace_*) ──► execution_workspaces (git worktree)
│
ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. workspace ──────────► project_workspaces
Environments (secret-aware env) ──► environment_leases ──► execution target
Runtime services ──► workspace_runtime_services (dev servers, preview URLs)
WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. operations ──► commands, diffs, uploads (authz-gated)
Data Models
execution_workspaces / project_workspaces / workspace_runtime_services / workspace_operations / environments / environment_leases
| Field | Type | Constraints | Description |
|---|---|---|---|
| execution_workspaces.id / company_id | uuid | FK, not null | Scoping |
| issues.execution_workspace_id/preference/settings | - | - | Per-issue workspace resolution |
| environments | - | - | Secret-aware env binding |
| environment_leases | - | - | Env-to-target leases |
API Contracts
/api/execution-workspaces, environment-selection, environments, workspace-command-authz, workspace-runtime-service-authz
WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs./runtime management and authorization. Routes under server/src/routes/, services under server/src/services/execution-workspaces.ts, environments.ts, etc.
Error Responses
| Status | Code | Description |
|---|---|---|
| 403 | UNAUTHORIZED | Command not authorized for this workspace/agent |
Sequences
Execution workspace checkout
checkout → resolve execution_workspace (preference/settings) → create/reuse worktree (base origin/master) → run agent → operations/diffs/uploads (authz)
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Isolation | Git worktrees per execution | Reproducible, isolated agent working directories |
Risks and Unknowns
- Sandbox provider lease reuse (e.g. Daytona) and large-upload reliability need careful handling.
Out of Scope
- Cloud sandbox marketplaces beyond supported providers.
requirements
- Which sandbox providers are supported and how are leases reused (e.g. Daytona)?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. System
Overview
The plugin system lets operators extend Paperclip without forking it. Plugins are instance-wide, out-of-process workers with capability-gated host services, job scheduling, tool exposure, UI contributions, webhooks, and isolated database namespaces. The local/self-hosted early plugin runtime is in scope for V1; the cloud marketplace and packaged public distribution remain out of scope. External adapter plugins are loaded through this same flow with zero hardcoded adapter imports in the loader.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Install/configure plugins, manage state and jobs, view logs |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. author | Build external plugins (SDK + scaffolder) and external adapters |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support installing and configuring instance-wide plugins. | Must | The system shall support installing and configuring instance-wide plugins. |
| FR-02MustThe plugin loader shall have zero hardcoded adapter imports and load external adapters purely dynamically. | Must | The plugin loader shall have zero hardcoded adapter imports and load external adapters purely dynamically. |
| FR-03MustThe system shall expose capability-gated host services to plugins (tools, jobs, webhooks, UI contributions). | Must | The system shall expose capability-gated host services to plugins (tools, jobs, webhooks, UI contributions). |
| FR-04Must`createServerAdapter()` shall include all optional adapter fields (especially `detectModel`). | Must | createServerAdapter() shall include all optional adapter fields (especially detectModel). |
| FR-05ShouldThe system shall support plugin database namespaces with migrations. | Should | The system shall support plugin database namespaces with migrations. |
| FR-06ShouldThe system shall support plugin jobs, logs, webhooks, and managed resources. | Should | The system shall support plugin jobs, logs, webhooks, and managed resources. |
| FR-07ShouldExternal adapter plugins shall be installable via the AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. manager and `~/.paperclip/adapter-plugins.json` (including `file:` entries for local dev). | Should | External adapter plugins shall be installable via the AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. manager and ~/.paperclip/adapter-plugins.json (including file: entries for local dev). |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustPluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. capabilities must be gated; a plugin must not exceed its granted capabilities. | Must | Security | PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. capabilities must be gated; a plugin must not exceed its granted capabilities. |
| NFR-02ShouldBuilt-in UI parsers for adapters must be removed when fully externalized to avoid shadowing plugin parsers. | Should | Maintainability | Built-in UI parsers for adapters must be removed when fully externalized to avoid shadowing plugin parsers. |
Constraints
- Cloud-grade plugin marketplace/distribution is out of scope for V1.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
- FR-02MustThe plugin loader shall have zero hardcoded adapter imports and load external adapters purely dynamically.
- Given the plugin loader
- When inspected
- Then there are no hardcoded adapter imports; all adapters load dynamically
- NFR-01MustPluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. capabilities must be gated; a plugin must not exceed its granted capabilities.
- Given a plugin attempting a capability it was not granted
- When the call is made
- Then it is denied
Conflicts
None identified yet.
Open Questions
- What is the full capability taxonomy granted to plugins, and how are new capabilities added safely?
Specification: PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. System
Overview
Plugins are out-of-process workers registered instance-wide. A capability-gated host exposes services (tools, jobs, webhooks, UI contributions, database namespaces) to plugins. The adapter plugin loader is the dynamic-loading path for external adapters and external adapter plugins. An SDK and scaffolder (create-paperclip-plugin) support authoring.
Architecture
Operator ──► /api/plugins (install/config/state)
│
▼
plugins table + plugin_config/state/entities/jobs/logs/webhooks
│
▼
plugin-loader (dynamic) ──► external adapters (zero hardcoded imports)
Host services (capability-gated) ◄── plugin worker ──► plugin_database namespaces/migrations
SDK (packages/plugins/sdk) + create-paperclip-plugin scaffolder
Data Models
plugins and plugin support tables
| Field | Type | Constraints | Description |
|---|---|---|---|
| plugins.id / company/instance scope | - | - | PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. registration |
| plugin_config / plugin_state | - | - | Config and runtime state |
| plugin_entities / plugin_jobs / plugin_logs / plugin_webhooks | - | - | PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions.-owned artifacts |
| plugin_database (namespaces/migrations) | - | - | Isolated plugin DB |
| plugin_managed_resources / plugin_company_settings | - | - | Managed resources and per-company settings |
API Contracts
/api/plugins, /api/plugin-ui-static
PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. installation, configuration, state, jobs, logs, webhooks, and UI static assets. Route: server/src/routes/plugins.ts.
Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). loading
External adapters via ~/.paperclip/adapter-plugins.json; createServerAdapter() includes all optional fields. Loader: server/src/adapters/plugin-loader.ts, store: server/src/services/adapter-plugin-store.ts.
Sequences
External adapter install
operator → AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). manager → adapter-plugins.json entry → plugin-loader dynamic load → createServerAdapter (all fields) → adapter registered
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Loader purity | Zero hardcoded adapter imports | Enables fully external adapters without core changes |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). registration | Include all optional fields (detectModel) |
Avoid silent capability loss for external adapters |
Risks and Unknowns
- Built-in UI parsers can shadow external plugin parsers; removing built-ins when externalized needs coordination.
Out of Scope
- Cloud-grade plugin marketplace and packaged public distribution.
requirements
- What is the full capability taxonomy granted to plugins, and how are new capabilities added safely?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Secrets Management
Overview
Paperclip manages secrets (API keys, tokens, credentials) centrally rather than storing them in plaintext in agent configs or project files. Secrets are versioned, bound to agents and projects via config paths, backed by pluggable provider vaults (local encrypted, AWS Secrets Manager, GCP, Vault), and every access is audited. The system supports inline env secret references in agent/project/routine configs and resolves them at runtime against the appropriate binding target.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Configure secret providers, create/rotate/revoke secrets, bind secrets to agents/projects, view access audit log |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Consume secrets at runtime via env injection; never see plaintext in configs |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support creating, reading, updating, and deleting company-scoped secrets with a name, key, provider, and status. | Must | The system shall support creating, reading, updating, and deleting company-scoped secrets with a name, key, provider, and status. |
| FR-02MustThe system shall support versioned secrets with SHA256 fingerprinting of secret material. | Must | The system shall support versioned secrets with SHA256 fingerprinting of secret material. |
| FR-03MustThe system shall support binding secrets to agents, projects, and other targets via config paths with JSON schema-defined secret references. | Must | The system shall support binding secrets to agents, projects, and other targets via config paths with JSON schema-defined secret references. |
| FR-04MustEvery secret resolution and access attempt shall be recorded as a `secret_access_event` for auditability. | Must | Every secret resolution and access attempt shall be recorded as a secret_access_event for auditability. |
| FR-05MustThe system shall support a pluggable provider architecture: local encrypted storage (default), AWS Secrets Manager, GCP, and HashiCorp Vault. | Must | The system shall support a pluggable provider architecture: local encrypted storage (default), AWS Secrets Manager, GCP, and HashiCorp Vault. |
| FR-06MustSecret values shall never be returned in API responses after creation; only metadata and status are readable. | Must | Secret values shall never be returned in API responses after creation; only metadata and status are readable. |
| FR-07ShouldThe system shall support inline secret reference syntax (`${{ secrets.my-secret-key }}`) in agent configs, project env, and routine env. | Should | The system shall support inline secret reference syntax (${{ secrets.my-secret-key }}) in agent configs, project env, and routine env. |
| FR-08ShouldThe system shall resolve secret references against the routine binding target when used in routine env (routine-owned secrets). | Should | The system shall resolve secret references against the routine binding target when used in routine env (routine-owned secrets). |
| FR-09ShouldThe system shall support bulk secret binding operations and env overlay resolution for execution contexts. | Should | The system shall support bulk secret binding operations and env overlay resolution for execution contexts. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustSecret material must be encrypted at rest in the provider vault. | Must | Security | Secret material must be encrypted at rest in the provider vault. |
| NFR-02MustEvery secret read event must log who accessed which secret key at what time, attributed to an agent or user. | Must | Auditability | Every secret read event must log who accessed which secret key at what time, attributed to an agent or user. |
| NFR-03MustPlaintext secrets must never be persisted in logs, activity entries, or run context snapshots. | Must | Security | Plaintext secrets must never be persisted in logs, activity entries, or run context snapshots. |
| NFR-04ShouldSecret resolution at invocation time must not add more than 500ms overhead. | Should | Performance | Secret resolution at invocation time must not add more than 500ms overhead. |
Constraints
- Provider config is instance-wide (not per-company for V1).
- Inline secret references use a specific syntax and are distinct from direct secret bindings.
- Secrets are company-scoped: agent/project/routine within company A cannot access company B's secrets.
Acceptance Criteria
- FR-01MustThe system shall support creating, reading, updating, and deleting company-scoped secrets with a name, key, provider, and status.
- Given a board operator with a company
- When they create a secret with name, key, and provider
- Then the secret row exists with status
activeand metadata is returned - And the secret value itself is never returned in any API response
- FR-02MustThe system shall support versioned secrets with SHA256 fingerprinting of secret material.
- Given an existing active secret
- When a new version is created
- Then a
company_secret_versionsrow exists with SHA256 fingerprint
- FR-04MustEvery secret resolution and access attempt shall be recorded as a `secret_access_event` for auditability.
- Given any secret access
- When the value is resolved
- Then a
secret_access_eventis recorded with actor, secret key, and timestamp
- FR-06MustSecret values shall never be returned in API responses after creation; only metadata and status are readable.
- Given a secret API response payload
- When inspected
- Then no field contains the plaintext secret value
- NFR-01MustSecret material must be encrypted at rest in the provider vault.
- Given the provider storage
- When inspected at the storage layer
- Then secret material is encrypted
- NFR-03MustPlaintext secrets must never be persisted in logs, activity entries, or run context snapshots.
- Given server logs after a secret resolution
- When inspected
- Then no plaintext secret values are present
Conflicts
None identified yet.
Open Questions
- What is the full list of supported secret providers for V1 beyond local encrypted and AWS Secrets Manager?
- How are secret references resolved when multiple bindings overlap for the same config path (priority/precedence order)?
Specification: Secrets Management
Overview
Secrets are company-scoped, versioned, and provider-backed. A pluggable provider architecture (local encrypted, AWS Secrets Manager, GCP, Vault) stores the material. Bindings attach secrets to agents/projects/routines via config paths. Inline secret references in JSON configs are resolved at runtime. Every access is audited via secret_access_events.
Architecture
User → /api/secrets (CRUD + versions + bindings)
│
▼
company_secrets (name, key, provider, status)
│
├── company_secret_versions (SHA256 fingerprint)
├── company_secret_bindings (target: agent/project, config path)
├── company_secret_provider_configs (vault config)
└── secret_access_events (audit)
│
▼
Provider layer: local-encrypted | aws-secrets-manager | gcp | vault
│
▼
Runtime resolution: inline ${{ secrets.ref }} → resolved value → env injection
Data Models
company_secrets
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | Secret identifier |
| company_id | uuid | FK companies, not null | Scoping |
| name | text | not null | Human-readable name |
| key | text | not null | Machine key for references |
| provider | text | not null | Provider type |
| status | text | not null | active \| deprecated \| destroyed |
| version | int | not null, default 1 | Current version number |
company_secret_versions
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| secret_id | uuid | FK, not null | Parent secret |
| version | int | not null | Monotonic version |
| sha256 | text | not null | Fingerprint of material |
| created_by / created_at | - | - | Attribution |
company_secret_bindings
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| secret_key | text | not null | Reference key |
| target_type | enum | not null | agent \| project \| routine |
| target_id | uuid | FK, not null | Scoped target |
| config_path | text[] | not null | JSON path for resolution |
API Contracts
POST /companies/:companyId/secrets
Request: { name, key, provider, value }
Response (201): { id, name, key, provider, status, version } — value NOT returned.
GET/PATCH/DELETE /companies/:companyId/secrets/:secretId
Standard CRUD. GET never returns value.
POST /companies/:companyId/secrets/:secretId/versions
Create new version of existing secret.
GET /companies/:companyId/secrets/:secretId/bindings, POST /companies/:companyId/secrets/bindings
Binding management.
GET /companies/:companyId/secrets/access-events
Audit log of secret accesses.
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Missing provider type or invalid value |
| 403 | UNAUTHORIZED | Actor may not access this company's secrets |
| 404 | NOT_FOUND | Secret not found |
| 409 | CONFLICT | Duplicate secret key within company |
Sequences
Secret creation and binding
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → POST /secrets (value) → store in provider vault → return metadata (no value)
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → POST /bindings (secretKey, targetType, targetId, configPath) → binding row
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. → runtime resolution → resolve bindings + inline refs → fetch from provider → env injection → ${{ secrets.ref }} replaced
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Provider architecture | Pluggable with registry | Supports local dev, AWS, GCP, Vault without hardcoding |
| Inline refs | ${{ secrets.key }} syntax in JSONB configs |
Usable in agent config, project env, routine env |
| Audit | Dedicated secret_access_events table |
Immutable trail for compliance |
| Material storage | Provider vault only (not in business DB) | Material is the provider's concern; DB holds metadata only |
Risks and Unknowns
- Vault provider may not be available in all deployment modes; fallback behavior must be graceful.
- Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. resolution ordering in nested env overlays (project env → routine env → runtime keys) needs clear documentation.
Out of Scope
- Automatic secret rotation or expiry notification.
- Cross-company secret sharing.
requirements
- What is the full list of supported secret providers for V1 beyond local encrypted and AWS Secrets Manager?
- How are secret references resolved when multiple bindings overlap for the same config path (priority/precedence order)?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Auth & Access Control
Overview
Paperclip supports two deployment modes: local_trusted (implicit board, loopback) and authenticated (session-based with user profiles). Access control spans board-level management, company membership and roles, agent API keys (hashed at rest), principal permission grants, instance user roles, invite/join flows, CLI authentication, and a fine-grained authorization engine that gates actions on resources. The authorization layer is cross-cutting infrastructure used by every route handler.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Manage users, API keys, invites; configure deployment mode and instance settings |
| Human user | Authenticate, manage profile, accept invites, request company access |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Authenticate via bearer API key for company-scoped operations |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support two deployment modes: `local_trusted` and `authenticated`. | Must | The system shall support two deployment modes: local_trusted and authenticated. |
| FR-02MustIn `authenticated` mode, users shall authenticate with sessions and have user profiles. | Must | In authenticated mode, users shall authenticate with sessions and have user profiles. |
| FR-03MustAgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys shall be hashed at rest with bcrypt or equivalent; plaintext shown once at creation. | Must | AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys shall be hashed at rest with bcrypt or equivalent; plaintext shown once at creation. |
| FR-04MustThe system shall enforce company access boundaries: request-scoped `company_id` context checked on every protected route. | Must | The system shall enforce company access boundaries: request-scoped company_id context checked on every protected route. |
| FR-05MustThe system shall support board API keys for programmatic board-level access. | Must | The system shall support board API keys for programmatic board-level access. |
| FR-06MustThe system shall support CLI authentication challenges. | Must | The system shall support CLI authentication challenges. |
| FR-07MustThe authorization middleware shall gate actions (create/read/update/delete/approve/etc.) on resources (company/agent/issue/etc.) per actor (board/user/agent). | Must | The authorization middleware shall gate actions (create/read/update/delete/approve/etc.) on resources (company/agent/issue/etc.) per actor (board/user/agent). |
| FR-08ShouldThe system shall support instance user roles for multi-user deployments. | Should | The system shall support instance user roles for multi-user deployments. |
| FR-09ShouldThe system shall support company membership management with roles and invites. | Should | The system shall support company membership management with roles and invites. |
| FR-10ShouldThe system shall support join requests for users requesting access to a company. | Should | The system shall support join requests for users requesting access to a company. |
| FR-11ShouldThe system shall support principal permission grants for fine-grained access beyond role-based defaults. | Should | The system shall support principal permission grants for fine-grained access beyond role-based defaults. |
| FR-12ShouldThe system shall support API key revocation and usage tracking (last_used_at). | Should | The system shall support API key revocation and usage tracking (last_used_at). |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustAgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys must not access other companies' data. | Must | Security | AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys must not access other companies' data. |
| NFR-02MustHashed keys must use a strong, salted algorithm (bcrypt). | Must | Security | Hashed keys must use a strong, salted algorithm (bcrypt). |
| NFR-03MustAll user/access mutations (invite, role change, key create/revoke) write `activity_log`. | Must | Auditability | All user/access mutations (invite, role change, key create/revoke) write activity_log. |
| NFR-04ShouldAuth middleware must complete in under 10ms p95. | Should | Performance | Auth middleware must complete in under 10ms p95. |
Constraints
local_trustedmode grants implicit board access without authentication.authenticatedmode requires session-based auth with user resolution.- AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. keys are scoped to exactly one company.
Acceptance Criteria
- FR-01MustThe system shall support two deployment modes: `local_trusted` and `authenticated`.
- Given a
local_trusteddeployment - When any request is made from localhost
- Then it is treated as board-level without explicit auth
- Given a
- FR-03MustAgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys shall be hashed at rest with bcrypt or equivalent; plaintext shown once at creation.
- Given a new agent API key creation
- When the key is created
- Then the hash is stored and the plaintext key is returned exactly once
- FR-04MustThe system shall enforce company access boundaries: request-scoped `company_id` context checked on every protected route.
- Given an agent API key for company A
- When a request targets company B's endpoint
- Then the request is rejected with 403/404
- FR-09ShouldThe system shall support company membership management with roles and invites.
- Given a company owner
- When they invite a user
- Then the user receives an invitation and can accept to become a member
- NFR-01MustAgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys must not access other companies' data.
- Given the authorization middleware
- When processing any API request
- Then company boundaries are enforced before any business logic runs
Conflicts
None identified yet.
Open Questions
- What is the full taxonomy of principal permission grants and how do they compose with role-based defaults?
- How are instance user roles and company membership roles reconciled for cross-company board users?
Specification: Auth & Access Control
Overview
Auth is mode-dependent. In local_trusted mode all local requests are implicit board; in authenticated mode the system uses session-based auth with user profiles, company memberships, and role-based access. The authorization engine enforces fine-grained action-on-resource gates. AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API keys are hashed at rest and scoped to one company.
Architecture
Request → authz middleware (assertBoard, assertCompanyAccess, assertAgent)
│
├─ auth mode check (local_trusted vs authenticated)
├─ bearer token / session resolution
├─ company_id scoping
└─ permission check (action on resource)
│
▼
Route handler (company-scoped context)
Data Models
auth / user
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | User ID |
| text | unique | User email | |
| display_name | text | - | Display name |
board_api_keys / agent_api_keys
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| key_hash | text | not null | Hashed key material |
| name | text | not null | Human label |
| last_used_at / revoked_at | timestamptz | null | Usage tracking |
company_memberships
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| company_id | uuid | FK, not null | Scoping |
| user_id | uuid | FK, not null | Member |
| role | text | not null | owner \| admin \| member |
principal_permission_grants
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| principal_type / principal_id | - | - | Who gets the grant |
| permission | text | - | Action/resource pair |
API Contracts
POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me
Session management.
POST /companies/:companyId/invites, POST /invites/:inviteId/accept
Invite flow.
POST /cli-auth/challenge, POST /cli-auth/respond
CLI authentication.
POST /agents/:agentId/keys, POST /agents/:agentId/keys/:keyId/revoke
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. API key management.
Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Not authenticated |
| 403 | FORBIDDEN | Authenticated but not authorized for this action/resource |
| 404 | NOT_FOUND | Resource not found (company-scoped) |
Sequences
Authenticated request flow
Request → authz middleware → session cookie → resolve user → resolve company context → check permission → route handler or 403
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Auth modes | local_trusted + authenticated |
Supports both single-user and multi-user deployments |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. keys | Hashed at rest (bcrypt) | Standard practice for credential storage |
| Authz engine | Middleware-based action/resource gates | Consistent cross-cutting enforcement before route logic |
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. scoping | Request-level company_id context |
Prevents cross-company data access at framework level |
Risks and Unknowns
- Permission grant composition with role-based defaults has not been battle-tested in production.
- Session management and token refresh semantics need hardening for production.
Out of Scope
- Multi-board governance or role-based human permission granularity (Pro/Enterprise).
- OAuth2/OIDC federation for V1.
- SAML/SSO enterprise integration.
requirements
- What is the full taxonomy of principal permission grants and how do they compose with role-based defaults?
- How are instance user roles and company membership roles reconciled for cross-company board users?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. Skills
Overview
Skills are reusable, versioned bundles of agent capabilities that can be installed into a company and assigned to agents. The system includes a skills catalog for browsing available skills, per-company skill installation with version pinning, and team/agent skill assignments. Skills may include prompts, tools, MCPModel Context Protocol (served by `packages/mcp-server`) configurations, and other capability definitions. Operator-authored custom skills are also supported alongside catalog skills.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Browse catalog, install/pin skills to company, assign skills to agents/teams, manage custom skills |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Consume assigned skills at runtime via heartbeat context |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support a skills catalog listing available skills with name, description, version, and metadata. | Must | The system shall support a skills catalog listing available skills with name, description, version, and metadata. |
| FR-02MustThe system shall support installing a skill into a company with version pinning. | Must | The system shall support installing a skill into a company with version pinning. |
| FR-03MustThe system shall support assigning installed skills to individual agents or teams. | Must | The system shall support assigning installed skills to individual agents or teams. |
| FR-04MustThe system shall include default skill bundles for common agent capabilities. | Must | The system shall include default skill bundles for common agent capabilities. |
| FR-05ShouldThe system shall support operator-authored custom skills alongside catalog skills. | Should | The system shall support operator-authored custom skills alongside catalog skills. |
| FR-06ShouldThe system shall support skill versioning and upgrades within a company. | Should | The system shall support skill versioning and upgrades within a company. |
| FR-07ShouldThe system shall support a teams catalog for pre-configured agent team templates. | Should | The system shall support a teams catalog for pre-configured agent team templates. |
| FR-08ShouldThe system shall resolve skill selections at heartbeat runtime, injecting only assigned skills. | Should | The system shall resolve skill selections at heartbeat runtime, injecting only assigned skills. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01ShouldCustom skills must be validated before installation to prevent malicious content. | Should | Security | Custom skills must be validated before installation to prevent malicious content. |
| NFR-02ShouldSkill resolution at heartbeat time must not add more than 200ms overhead. | Should | Performance | Skill resolution at heartbeat time must not add more than 200ms overhead. |
Constraints
- Skills are company-scoped: each company has its own installed skill set.
- Default skills ship with the product; custom skills are operator-created.
- Team catalog entries may reference multiple skills and agents.
Acceptance Criteria
- FR-01MustThe system shall support a skills catalog listing available skills with name, description, version, and metadata.
- Given a board operator
- When they view the skills catalog
- Then available skills are listed with name, description, and version
- FR-02MustThe system shall support installing a skill into a company with version pinning.
- Given a company
- When a skill is installed
- Then the skill is available for assignment within that company
- FR-03MustThe system shall support assigning installed skills to individual agents or teams.
- Given an installed skill
- When it is assigned to an agent
- Then the agent receives that skill's capabilities at next heartbeat
Conflicts
None identified yet.
Open Questions
- What is the exact skill definition format (prompts, tools, MCPModel Context Protocol (served by `packages/mcp-server`), or a combination)?
- How do skill version upgrades handle backward compatibility?
- What is the team catalog's relationship to the org chart (are teams static templates or dynamic groupings)?
Specification: CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. Skills
Overview
Skills are versioned capability bundles. A central catalog lists available skills; companies install them with version pinning and assign them to agents or teams. At heartbeat runtime, the skill selection service resolves the set of skills active for the agent and injects them into the invocation context. The teams catalog provides pre-configured agent templates that bundle skills and agent configurations together.
Architecture
Catalog ──► GET /api/catalog/skills (public skill definitions)
│
CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. ──► POST /api/companies/:companyId/skills (install + pin version)
│
▼
company_skills (skill_id, company_id, version)
│
▼
agent skill assignments (agent_skills / runtime_skill_selections)
│
▼
HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. runtime → skill resolution → inject into context
Data Models
company_skills
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| company_id | uuid | FK, not null | Scoping |
| skill_id | text | not null | Catalog skill identifier |
| version | text | not null | Pinned version |
| config | jsonb | null | Per-install configuration |
runtime_skill_selections
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | - |
| agent_id | uuid | FK, not null | Target agent |
| skill_id | text | not null | Skill reference |
| enabled | boolean | not null | Active/inactive |
API Contracts
GET /api/companies/:companyId/skills-catalog
Browse available skills.
POST /api/companies/:companyId/skills
Install a skill for the company.
POST /api/companies/:companyId/skills-catalog/install-from-catalog
Install from catalog directly.
GET/DELETE /api/companies/:companyId/skills/:skillId
Manage installed skills.
GET /api/catalog/teams, POST /api/companies/:companyId/teams-catalog
Teams catalog management.
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Invalid skill reference or version |
| 404 | NOT_FOUND | Skill not found in catalog |
Sequences
Skill installation and assignment
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → browse catalog → install skill (pin version) → company_skills row
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → assign skill to agent → runtime_skill_selections row
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. heartbeat → resolve agent's enabled skills → inject into invocation context → agent executes with skill capabilities
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Skill resolution | Runtime selection join at heartbeat | Skills are evaluated per invocation; no agent-side state |
| Version pinning | CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation.-specific version per skill | Companies upgrade on their own schedule |
| Catalog source | Built-in default skills + operator custom | Supports both out-of-box and tailored capability sets |
Risks and Unknowns
- Skill definition format is evolving; backward compatibility during catalog updates must be managed.
- Custom skill validation is critical for security but the validation rules are not fully defined.
- The relationship between the teams catalog and the org chart
/reports_totree needs documentation.
Out of Scope
- Public skill marketplace or community contributions (ClipHub).
- Skill dependency resolution (skills requiring other skills).
requirements
- What is the exact skill definition format (prompts, tools, MCP, or a combination)?
- How do skill version upgrades handle backward compatibility?
- What is the team catalog's relationship to the org chart (are teams static templates or dynamic groupings)?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. Hierarchy
Overview
Goals provide the company-wide alignment hierarchy that ties every task back to business mission. Each goal is a node in a tree (company root goal, team goals, agent goals) with a level, status, and optional owner agent. Goals are the first step in the Paperclip workflow: a board operator defines the company mission as a root goal and decomposes it down the org tree, giving every task a traceable purpose.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Create, edit, and restructure goal hierarchy; link goals to projects and issues |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Work within goal-aligned tasks; see goal context in heartbeat invocations |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Propose strategy that maps to goals (requires board approval) |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01Mustteam | Must | The system shall support CRUD of company-scoped goals with title, description, level (company | team | task), and status (planned | active | completed | cancelled). |
| FR-02MustThe system shall support a goal hierarchy via `parent_id` (nullable root) that forms a tree, with all goals scoped to the same company. | Must | The system shall support a goal hierarchy via parent_id (nullable root) that forms a tree, with all goals scoped to the same company. |
| FR-03MustThe system shall track goal ownership via `owner_agent_id`. | Must | The system shall track goal ownership via owner_agent_id. |
| FR-04MustGoals shall link to projects and issues: issues carry `goal_id`, projects carry `goal_id`, and the goal chain is traceable from task to company root. | Must | Goals shall link to projects and issues: issues carry goal_id, projects carry goal_id, and the goal chain is traceable from task to company root. |
| FR-05ShouldThe system shall support listing goals by company with ordering. | Should | The system shall support listing goals by company with ordering. |
| FR-06ShouldThe system shall create a default root company goal on company creation. | Should | The system shall create a default root company goal on company creation. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustAll goal mutations must write `activity_log` entries. | Must | Auditability | All goal mutations must write activity_log entries. |
| NFR-02ShouldGoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. CRUD must meet the p95 < 250 ms latency target. | Should | Performance | GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. CRUD must meet the p95 < 250 ms latency target. |
Constraints
- Goals are company-scoped; cross-company goal references are not supported.
- A goal hierarchy is expected to be shallow (company root, team, task levels).
Acceptance Criteria
- FR-01Mustteam
- Given a company
- When a board operator creates a goal with title, level, and status
- Then a goal row exists scoped to that company
- FR-02MustThe system shall support a goal hierarchy via `parent_id` (nullable root) that forms a tree, with all goals scoped to the same company.
- Given a root goal
- When a child goal is created with
parent_idpointing to the root - Then the goal tree is correctly navigable from root to leaf
- FR-04MustGoals shall link to projects and issues: issues carry `goal_id`, projects carry `goal_id`, and the goal chain is traceable from task to company root.
- Given a goal
- When an issue or project is created with that
goal_id - Then the goal chain is traceable from the issue to the company root goal
- NFR-01MustAll goal mutations must write `activity_log` entries.
- Given any goal mutation (create, update, delete)
- When the mutation completes
- Then an
activity_logentry is written
Conflicts
None identified yet.
Open Questions
- Should goal deletion cascade to child goals (soft delete with orphan marking)?
- What is the exact default root goal creation behavior on company creation?
Specification: GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. Hierarchy
Overview
Goals are company-scoped tree nodes with level, status, and owner.
They form the alignment chain from company mission down to individual tasks.
The goals table uses parent_id for hierarchy and level for semantic tiering.
Projects and issues link to goals via goal_id foreign keys, enabling cost rollups and progress tracking by goal.
Architecture
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based./AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. ──► /api/goals (CRUD)
│
▼
goals table (company_id, parent_id, level, status, owner_agent_id)
│
├── issues.goal_id (task-to-goal link)
├── projects.goal_id (project-to-goal link)
└── activity_log (goal mutations)
Data Models
goals
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK, defaultRandom | GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. identifier |
| company_id | uuid | FK companies, not null | Scoping |
| title | text | not null | GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. name |
| description | text | null | Optional description |
| level | text | not null, default task |
company | team | task |
| status | text | not null, default planned |
planned | active | completed | cancelled |
| parent_id | uuid | FK goals, null | Parent goal (null = root) |
| owner_agent_id | uuid | FK agents, null | Responsible agent |
| created_at / updated_at | timestamptz | not null | Timestamps |
API Contracts
GET /companies/:companyId/goals
List goals for a company.
POST /companies/:companyId/goals
Create a goal. Request body includes title, description, level, status, parentId, ownerAgentId.
GET /goals/:goalId
Get a single goal by ID.
PATCH /goals/:goalId
Update goal fields.
DELETE /goals/:goalId
Delete a goal (soft delete optional, hard delete board-only).
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Validation error on goal fields |
| 403 | UNAUTHORIZED | Caller lacks company access |
| 404 | NOT_FOUND | GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. not found |
Sequences
Create a goal hierarchy
Hirer → POST /companies/:id/goals (root level=company) → goals row
Hirer → POST /companies/:id/goals (parent=root, level=team) → child goal
IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. → issue.goal_id = childGoal.id → traceable chain: issue → childGoal → rootGoal
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Hierarchy model | Adjacency list (parent_id) |
Simple, well-understood for shallow trees |
| Level enum | company | team | task |
Matches the org hierarchy semantic tiers |
| Linking method | Foreign keys (goal_id on issues/projects) | Direct traceability without join tables |
Risks and Unknowns
- Deep goal hierarchies may cause slow recursive queries; materialized paths or closure tables may be needed at scale.
- The relationship between goal level and org tree (
reports_to) level needs precise documentation.
Out of Scope
- GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company.-based budget allocation (V1 uses agent/company budgets only).
- Automatic goal progress calculation from subtask completion.
requirements
- Should goal deletion cascade to child goals (soft delete with orphan marking)?
- What is the exact default root goal creation behavior on company creation?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Projects
Overview
Projects are company-scoped groupings that organize work around a specific initiative. Each project carries a name, description, status, lead agent, target date, environment config, and execution workspace policy. Projects link to goals for strategic alignment and support workspaces with runtime services for agent execution. Projects are a core organizational entity visible throughout the board UI and agent API.
Stakeholders
| Stakeholder | Interest |
|---|---|
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. operator | Create and manage projects, assign lead agents, set targets, configure environments and workspaces |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | Work within project context; access project env, workspace, and runtime services |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall support CRUD of company-scoped projects with name, description, status, lead agent, and target date. | Must | The system shall support CRUD of company-scoped projects with name, description, status, lead agent, and target date. |
| FR-02Mustactive | Must | Projects shall support status lifecycle (backlog | active | paused | completed | archived). |
| FR-03MustProjects shall link to a goal via `goal_id` for strategic alignment. | Must | Projects shall link to a goal via goal_id for strategic alignment. |
| FR-04MustThe system shall support project workspaces (named working directories with repo URL, CWD, runtime config, and metadata). | Must | The system shall support project workspaces (named working directories with repo URL, CWD, runtime config, and metadata). |
| FR-05MustThe system shall support project execution workspace policy (how execution worktrees are created for issues within the project). | Must | The system shall support project execution workspace policy (how execution worktrees are created for issues within the project). |
| FR-06ShouldThe system shall support project memberships tracking which users/agents have joined a project (for sidebar visibility). | Should | The system shall support project memberships tracking which users/agents have joined a project (for sidebar visibility). |
| FR-07ShouldThe system shall support project runtime services (dev servers, preview URLs) with desired state management. | Should | The system shall support project runtime services (dev servers, preview URLs) with desired state management. |
| FR-08ShouldThe system shall support project env configuration with secret ref resolution (project-level env overlay). | Should | The system shall support project env configuration with secret ref resolution (project-level env overlay). |
| FR-09ShouldThe system shall track project budget summaries (aggregate spend across project issues and agents). | Should | The system shall track project budget summaries (aggregate spend across project issues and agents). |
| FR-10MayThe system shall support plugin-managed projects (plugins can declare and manage project-level resources). | May | The system shall support plugin-managed projects (plugins can declare and manage project-level resources). |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustAll project mutations must write `activity_log` entries. | Must | Auditability | All project mutations must write activity_log entries. |
| NFR-02MustProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. env and secrets must be scoped to the project's company. | Must | Security | ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. env and secrets must be scoped to the project's company. |
| NFR-03ShouldProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. CRUD and workspace operations must meet latency targets. | Should | Performance | ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. CRUD and workspace operations must meet latency targets. |
Constraints
- Projects are company-scoped; cross-company project access is not permitted.
- A project links to exactly one goal (optional).
- ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. workspace runtime services are provider-dependent and may not be available in all deployment modes.
Acceptance Criteria
- FR-01MustThe system shall support CRUD of company-scoped projects with name, description, status, lead agent, and target date.
- Given a company
- When a project is created with name, status, and lead agent
- Then a project row exists scoped to the company
- FR-04MustThe system shall support project workspaces (named working directories with repo URL, CWD, runtime config, and metadata).
- Given a project
- When a project workspace is created with repo URL and CWD
- Then the workspace is available for agent execution
- FR-07ShouldThe system shall support project runtime services (dev servers, preview URLs) with desired state management.
- Given a project workspace
- When runtime services are configured with desired state
- Then services are started/stopped to match the desired state
- NFR-01MustAll project mutations must write `activity_log` entries.
- Given any project mutation
- When the mutation completes
- Then an
activity_logentry is written
Conflicts
None identified yet.
Open Questions
- How do project env overlays compose with agent env and routine env at runtime?
- What is the exact relationship between project workspaces and execution workspaces (git worktrees)?
- Are plugin-managed projects fully supported in V1 or deferred?
Specification: Projects
Overview
Projects are first-class company-scoped entities with status lifecycle, goal linkage, env configuration, workspaces, runtime services, and budget summaries.
The projects service (server/src/services/projects.ts, 1215 lines) handles CRUD, workspace management, runtime service orchestration, goal linking, and plugin-managed project resolution.
ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. workspaces provide named working directories with repo integration; project execution workspace policy governs how execution worktrees are created for issues within the project.
Architecture
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based./AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. ──► /api/projects (CRUD + workspaces + runtime)
│
▼
projects (company_id, goal_id, status, lead_agent_id, env)
│
├── project_goals (goal links)
├── project_memberships (user/agent join state)
├── project_workspaces (named working directories)
│ └── workspace_runtime_services (dev servers, preview URLs)
├── issues.project_id (issue-to-project link)
└── activity_log (project mutations)
Data Models
projects
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK, defaultRandom | ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. identifier |
| company_id | uuid | FK companies, not null | Scoping |
| goal_id | uuid | FK goals, null | Strategic alignment |
| name | text | not null | ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. name |
| description | text | null | Optional description |
| status | text | not null, default backlog |
backlog | active | paused | completed | archived |
| lead_agent_id | uuid | FK agents, null | Responsible agent |
| target_date | date | null | Target completion date |
| color | text | null | UI color |
| icon | text | null | UI icon |
| env | jsonb | null | AgentEnvConfig (secret-aware env) |
| execution_workspace_policy | jsonb | null | Policy for execution worktree creation |
| archived_at / paused_at | timestamptz | null | Status timestamps |
| created_at / updated_at | timestamptz | not null | Timestamps |
project_workspaces
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. identifier |
| project_id | uuid | FK projects, not null | Parent project |
| name | text | not null | Human name |
| source_type | text | null | git, local, etc. |
| cwd | text | null | Working directory |
| repo_url / repo_ref / default_ref | text | null | Git source config |
| runtime_config | jsonb | null | WorkspaceRuntimeConfig |
| is_primary | boolean | default false | Primary workspace flag |
| visibility | text | default company |
Visibility scope |
API Contracts
GET /companies/:companyId/projects, POST /companies/:companyId/projects, GET /projects/:projectId, PATCH /projects/:projectId
Standard project CRUD. Create/update accept goal_id, status, lead_agent_id, target_date, color, icon, env.
ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. workspace endpoints
POST /projects/:projectId/workspaces, GET/PATCH /projects/:projectId/workspaces/:workspaceId for workspace management.
ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. runtime service control
Runtime service desired state management and control via workspace runtime endpoints.
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Validation error |
| 403 | UNAUTHORIZED | Caller lacks company access |
| 404 | NOT_FOUND | ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. not found |
Sequences
Create project with workspace
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → POST /projects (name, goal_id, lead_agent_id) → project row
BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. → POST /projects/:id/workspaces (name, repo_url, cwd) → workspace row
AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. → issue within project → resolve execution workspace per policy → agent runs in workspace context
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. env | JSONB with secret ref syntax | Consistent with other env config patterns in Paperclip |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. model | Named project workspaces + execution worktree policy | Separates shared project state from isolated agent execution |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. linking | Direct goal_id FK on projects | Simple traceability without a join table |
| Runtime services | Desired-state model (start/stop to match config) | Declarative lifecycle management |
Risks and Unknowns
- Env overlay precedence (project env → routine env → runtime keys) needs clear documentation.
- ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. workspace isolation and concurrency semantics when multiple agents work in the same project.
- PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions.-managed project features may expand the project data model significantly.
Out of Scope
- Cross-company project sharing or federation.
- ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env.-level access control lists beyond company scoping (deferred to Pro/Enterprise).
requirements
- How do project env overlays compose with agent env and routine env at runtime?
- What is the exact relationship between project workspaces and execution workspaces (git worktrees)?
- Are plugin-managed projects fully supported in V1 or deferred?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| CompanyFirst-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. | First-order business entity; all business records are company-scoped. One deployment can run many companies with full data isolation. |
| BoardThe human operator(s) with full control across all companies in a deployment. In `local_trusted` mode this is implicit; in authenticated mode it is session-based. | The human operator(s) with full control across all companies in a deployment. In local_trusted mode this is implicit; in authenticated mode it is session-based. |
| Board API keyOptional key for board-level access (separate from agent API keys). | Optional key for board-level access (separate from agent API keys). |
| AgentAn AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. | An AI employee registered in the org tree with a role, title, reporting line, budget, and adapter configuration. |
| CEO agentTop-level management agent that proposes strategy (requires board approval before executing delegated work). | Top-level management agent that proposes strategy (requires board approval before executing delegated work). |
| Org chart / org treeStrict reporting tree via `reports_to` (nullable root); no multi-manager reporting, no cycles. | Strict reporting tree via reports_to (nullable root); no multi-manager reporting, no cycles. |
| GoalA node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. | A node in the company → team → agent → task alignment hierarchy; at least one root company-level goal per company. |
| ProjectA company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. | A company-scoped grouping that may link to a goal and carry lead agent, target date, and secret-aware env. |
| IssueThe core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. | The core task entity. Carries company/project/goal/parent links, single assignee, atomic checkout locks, comments, documents, work products, and attachments. |
| TaskUsed interchangeably with "issue" in agent/operator contexts (the task system is the issues table). | Used interchangeably with "issue" in agent/operator contexts (the task system is the issues table). |
| HeartbeatA scheduled or triggered wakeup that invokes an agent's adapter to do work. | A scheduled or triggered wakeup that invokes an agent's adapter to do work. |
| Heartbeat runA tracked execution record (`heartbeat_runs`) with status, context snapshot, and events. | A tracked execution record (heartbeat_runs) with status, context snapshot, and events. |
| AdapterTranslates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). | Translates a heartbeat into a concrete runtime invocation (process, HTTP, CLI session, gateway, or external plugin). |
| CheckoutThe atomic operation that claims an issue for execution; sets `assignee_agent_id`, `status=in_progress`, and execution locks. Returns `409` on concurrent claims. | The atomic operation that claims an issue for execution; sets assignee_agent_id, status=in_progress, and execution locks. Returns 409 on concurrent claims. |
| Execution lockFields (`checkout_run_id`, `execution_run_id`, `execution_locked_at`) that prevent double-work on an issue. | Fields (checkout_run_id, execution_run_id, execution_locked_at) that prevent double-work on an issue. |
| Work modeHow an issue is executed: `standard` (autonomous), `ask` (answer-only), or `planning` (plan-only). | How an issue is executed: standard (autonomous), ask (answer-only), or planning (plan-only). |
| Work productA typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). | A typed deliverable attached to an issue (e.g. artifact with an attachment, or a workspace-file reference). |
| DocumentEditable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (`plan`, `design`, `notes`). | Editable text-first artifact (markdown) with append-only revisions, linked to issues by workflow key (plan, design, notes). |
| ApprovalA governance request (`hire_agent`, `approve_ceo_strategy`, budget override, `request_board_approval`) the board approves/rejects. | A governance request (hire_agent, approve_ceo_strategy, budget override, request_board_approval) the board approves/rejects. |
| Execution policyA review/approval stage policy governing how an issue is executed. | A review/approval stage policy governing how an issue is executed. |
| RoutineA recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. | A recurring task definition with cron/webhook/API triggers; each execution creates a tracked issue and wakes the assigned agent. |
| WorkspaceEither a project workspace or an isolated execution workspace (git worktree) where an agent runs. | Either a project workspace or an isolated execution workspace (git worktree) where an agent runs. |
| Task watchdogA scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. | A scoped execution capacity for one watched issue subtree that restores live task paths; not board authority and not active-run output monitoring. |
| PluginInstance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. | Instance-wide out-of-process extension with capability-gated host services, jobs, tools, and UI contributions. |
| Company portabilityExport/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. | Export/import of entire organizations (agents, skills, projects, routines, issues) with secret scrubbing and collision handling. |
Technical Terms
| Term | Definition |
|---|---|
| Control planeThe Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). | The Paperclip server + UI that orchestrates agents (as opposed to the execution services/adapters that run them). |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL used as the dev default when DATABASE_URL is unset. |
| DrizzleThe TypeScript ORM used for schema, migrations, and DB clients. | The TypeScript ORM used for schema, migrations, and DB clients. |
| Adapter pluginAn external adapter loaded dynamically via `~/.paperclip/adapter-plugins.json` (no hardcoded core imports). | An external adapter loaded dynamically via ~/.paperclip/adapter-plugins.json (no hardcoded core imports). |
| Context mode`thin` (send IDs/pointers; agent fetches via API) vs `fat` (include assignments, goal summary, budget snapshot, recent comments). | thin (send IDs/pointers; agent fetches via API) vs fat (include assignments, goal summary, budget snapshot, recent comments). |
| Cheap model profileOptional low-cost model lane (`modelProfiles.cheap`) usable only for status-only recovery coordination, never deliverable work. | Optional low-cost model lane (modelProfiles.cheap) usable only for status-only recovery coordination, never deliverable work. |
| Request depthCounter incremented as work is delegated down the org tree. | Counter incremented as work is delegated down the org tree. |
| Activity logImmutable audit trail for every mutating action (actor_type, action, entity, details). | Immutable audit trail for every mutating action (actor_type, action, entity, details). |
| Budget hard stopAt 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. | At 100% of monthly UTC budget, the agent is paused and new invocations/checkout are blocked. |
| Secrets providerA pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). | A pluggable vault backend for storing secret material (local encrypted, AWS Secrets Manager, GCP, HashiCorp Vault). |
| Secret bindingAn association between a secret key and a target (agent, project, or routine) with a config path for resolution. | An association between a secret key and a target (agent, project, or routine) with a config path for resolution. |
| Inline secret referenceThe `${{ secrets.key }}` syntax used in JSONB configs to reference a secret that is resolved at runtime. | The ${{ secrets.key }} syntax used in JSONB configs to reference a secret that is resolved at runtime. |
| Board chat / Conference roomAn experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSE and persisted to a standing issue. | An experimental board-level chat assistant that spawns a Claude subprocess with the board skills prompt, streamed via SSEServer-Sent Events (deferred realtime transport) and persisted to a standing issue. |
| Company membershipA user's role-scoped association with a company (`owner \ | A user's role-scoped association with a company (owner \| admin \| member). |
| Principal permission grantA fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). | A fine-grained permission override granting a specific action on a specific resource to a principal (user or agent). |
| GreptileAutomated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. | Automated code-review service used in CI; PRs must reach 5/5 with no open P2+ comments. |
| Low-trust presetA containment control for hostile automated work (not general project/issue privacy). | A containment control for hostile automated work (not general project/issue privacy). |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| SDLCSoftware Development Lifecycle (the `.sdlc/` artifact pipeline) | Software Development Lifecycle (the .sdlc/ artifact pipeline) |
| MCPModel Context Protocol (served by `packages/mcp-server`) | Model Context Protocol (served by packages/mcp-server) |
| OTELOpenTelemetry (opt-in tracing instrumentation) | OpenTelemetry (opt-in tracing instrumentation) |
| SLI / SLOService Level Indicator / Service Level Objective | Service Level Indicator / Service Level Objective |
| SSEServer-Sent Events (deferred realtime transport) | Server-Sent Events (deferred realtime transport) |
| ACLAccess Control List (Pro/Enterprise work-object privacy, deferred for V1) | Access Control List (Pro/Enterprise work-object privacy, deferred for V1) |
| RICEReach, Impact, Confidence, Effort (issue prioritization scoring) | Reach, Impact, Confidence, Effort (issue prioritization scoring) |
| JWTJSON Web Token (short-lived run tokens) | JSON Web Token (short-lived run tokens) |
| PGliteEmbedded PostgreSQL (see Technical Terms) | Embedded PostgreSQL (see Technical Terms) |
| CSPContent Security Policy | Content Security Policy |