mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-11 14:10:50 +02:00
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - Agents use saved questions to get human input and continue the same task. > - The standard question example recently told models to copy a user ID. > - A model can omit an identity prefix and create a question its intended recipient cannot answer. > - Agent Chat already knows the conversation owner, so the server can supply that identity. > - This pull request removes the blanket instruction and validates explicit recipients before saving. > - Ordinary questions stay simple, and explicit addressing remains available for decisions that need a particular person. ## Linked Issues or Issue Description Refs #14707, #14188. Related: #14238 handles legacy email recipients; this change prevents invalid recipients in new cards and retains exact ID matching. **What happened?** A model copied a Cloud user ID without its prefix into `addresseeUserId`. Creation succeeded. The intended user's answer then failed the exact recipient check. **Expected behavior** Ordinary chat questions use the saved conversation owner. A task may optionally name a specific recipient. The API rejects an unknown or unauthorized recipient before it creates a card. **Steps to reproduce** Create a chat question for a user whose ID is `paperclip-id:example`. Supply `example` as the addressee. Before this change, creation accepts the invalid recipient and the owner cannot answer. With this change, creation returns 422. Omitting the field saves the full owner ID and allows that owner to answer. ## What Changed - Remove `addresseeUserId` from standard question examples and remove the blanket requester-ID instruction. - Derive the recipient of ordinary chat questions from the persisted conversation owner. Reject conflicting explicit user IDs. - Keep explicit task recipients optional. Validate supplied user IDs with the existing board mutation policy, including company, viewer, and Cloud restrictions. - Preserve explicit agent routing, connector intents, confirmations, exact recipient checks, idempotent retries, and no-login local-board authority in local-trusted mode. - Update the blocker grader to accept an omitted recipient and verify the actual requester answered. - Add database and HTTP tests for prefixed identities, denied recipients, concurrent retries, saved answers, and response delivery. ## Verification - Database interaction service suite: 90 tests passed, including implicit local-board creation/answering and authenticated/Cloud denial. - Interaction HTTP route suite: 84 tests passed. - Affected interaction/native/connector/documentation suites: 231 tests passed across six files after valid-user fixtures were updated. - Resolver and interaction unit suites: 29 tests passed. - Product E2E unit/calibration suite: 793 tests passed; Product E2E typecheck and blocker catalog discovery passed. - Generated API-reference and capability contract checks passed. - `pnpm -r typecheck` and `pnpm build` passed. - Full local `pnpm test:run` did not finish green: its initial general-server pass had 14,416 passing assertions, one unrelated native-resume assertion failure on macOS, and three teardowns from an intermediate fixture cleanup fixed above. Separate broad local groups also encountered timeout/live-port failures under host load. Local UI (7,026), CLI (502), shared (817), and skills-catalog (20) tests passed; the complete final-head CI matrix is the broad verification gate. - After two CI cold-start readiness timeouts, a separate test-only commit gives the first exposure lifecycle fixture the existing normal 30-second readiness budget. Its real HTTP, ordering, and cleanup assertions remain intact; the targeted case and final Linux CI shard passed. Production deadlines are unchanged. - A separate OpenCode fixture failed twice on GitHub-hosted Ubuntu because its cached Node executable was group-writable; the same case passed on AWS runners. The fixture now qualifies its own Linux copy with mode `0500` and the actual copy digest. Host files and production security checks are unchanged. The focused macOS case passed; the new Linux-copy branch also passed on the final AWS-hosted Linux runner (1,125 passing Runner tests, 3 skipped). The final run was not on a GitHub-hosted runner. - Final-head [CI run 36762078176](https://github.com/paperclipai/paperclip/actions/runs/36762078176) passed for `116b968b24fa0a8c5724a7bf96e73a8dda5f0425`: 54 successful checks and two conditional Storybook skips, with no pending or failed checks. The 27 general/serialized test jobs reported 28,635 passing tests. Typecheck, build, Runner, browser E2E, and Canary gates passed. Greptile reviewed that exact head at 5/5; both review threads are resolved, with no open follow-ups. - No live provider replay is claimed by this PR. ## Risks - New explicitly addressed cards reject users who cannot mutate the issue, including viewers, inactive members, and invalid IDs. Callers that supplied invalid recipients must correct their request. - Existing addressed cards are not rewritten. Existing authorization checks remain strict. - Chat inference applies only to questions without an agent addressee. Connector intents and governed confirmations retain their own recipient paths. - No schema change or migration is required. ## Model Used OpenAI Codex, GPT-6 (exact serving variant and context window are not exposed in this environment). Used reasoning, tool use, code editing, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
807 lines
26 KiB
TypeScript
807 lines
26 KiB
TypeScript
// Generated by scripts/generate-runner-api-reference.mjs from the legacy skill reference.
|
|
export const runnerApiReference: Record<string, { section: string; description?: string; examples?: { body: unknown }[] }> = {
|
|
"GET /api/agents/me": {
|
|
"section": "Agents",
|
|
"description": "Your agent record + chain of command"
|
|
},
|
|
"GET /api/agents/me/inbox/mine?userId={}": {
|
|
"section": "Agents",
|
|
"description": "Mine-tab issue list for a specific board user"
|
|
},
|
|
"GET /api/agents/{}": {
|
|
"section": "Agents",
|
|
"description": "Agent details + chain of command"
|
|
},
|
|
"GET /api/companies/{}/agents": {
|
|
"section": "Agents",
|
|
"description": "List all agents in company"
|
|
},
|
|
"POST /api/companies/{}/agents": {
|
|
"section": "Agents",
|
|
"description": "Create agent directly (no approval)"
|
|
},
|
|
"PATCH /api/agents/{}": {
|
|
"section": "Agents",
|
|
"description": "Update agent config or budget"
|
|
},
|
|
"POST /api/agents/{}/pause": {
|
|
"section": "Agents",
|
|
"description": "Temporarily stop heartbeats"
|
|
},
|
|
"POST /api/agents/{}/resume": {
|
|
"section": "Agents",
|
|
"description": "Resume a paused agent"
|
|
},
|
|
"POST /api/agents/{}/terminate": {
|
|
"section": "Agents",
|
|
"description": "Permanently deactivate agent (irreversible)"
|
|
},
|
|
"POST /api/agents/{}/keys": {
|
|
"section": "Agents",
|
|
"description": "Create long-lived API key (full value shown once)"
|
|
},
|
|
"POST /api/agents/{}/heartbeat/invoke": {
|
|
"section": "Agents",
|
|
"description": "Manually trigger a heartbeat"
|
|
},
|
|
"GET /api/companies/{}/org": {
|
|
"section": "Agents",
|
|
"description": "Org chart tree"
|
|
},
|
|
"GET /api/companies/{}/adapters/{}/models": {
|
|
"section": "Agents",
|
|
"description": "List selectable models for an adapter type"
|
|
},
|
|
"PATCH /api/agents/{}/instructions-path": {
|
|
"section": "Agents",
|
|
"description": "Set/clear instructions path (`AGENTS.md`)",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"path": "agents/cmo/AGENTS.md"
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"path": "/absolute/path/to/AGENTS.md",
|
|
"adapterConfigKey": "adapterSpecificPathField"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"GET /api/agents/{}/config-revisions": {
|
|
"section": "Agents",
|
|
"description": "List config revisions"
|
|
},
|
|
"POST /api/agents/{}/config-revisions/{}/rollback": {
|
|
"section": "Agents",
|
|
"description": "Roll back config"
|
|
},
|
|
"GET /api/companies/{}/issues": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "List issues, sorted by priority. Filters: `?status=`, `?assigneeAgentId=`, `?assigneeUserId=`, `?projectId=`, `?labelId=`, `?q=` (full-text search across title, identifier, description, comments)"
|
|
},
|
|
"GET /api/issues/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Issue details + ancestors"
|
|
},
|
|
"GET /api/issues/{}/heartbeat-context": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Compact issue context including `currentExecutionWorkspace` when one is linked"
|
|
},
|
|
"GET /api/issues/{}/diagnostics/blockers": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Read-only blocker diagnostic with `diagnosis`, readiness, and bounded anomaly flags"
|
|
},
|
|
"GET /api/issues/{}/diagnostics/wakes": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Read-only wake-history diagnostic with `diagnosis`, bounded events, and Case-B inference"
|
|
},
|
|
"GET /api/issues/{}/diagnostics/subtree": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Read-only subtree diagnostic combining visible child, blocker, and wake edges with `diagnosis`"
|
|
},
|
|
"POST /api/companies/{}/issues": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Create issue (supports `blockedByIssueIds: string[]` for dependencies)"
|
|
},
|
|
"PATCH /api/issues/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Update issue; response is authoritative and includes `changes` + `comment` (`Prefer: return=minimal` supported); `blockedByIssueIds` replaces blocker set",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"executionPolicy": {
|
|
"stages": [
|
|
{
|
|
"type": "review",
|
|
"participants": [
|
|
{
|
|
"type": "agent",
|
|
"agentId": "<reviewer-agent-id>"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"status": "in_review",
|
|
"comment": "Waiting for your answer in the saved responsibility question card."
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"status": "blocked",
|
|
"unblockDescriptor": {
|
|
"owner": {
|
|
"agentId": "{your-agent-id}"
|
|
},
|
|
"action": "Restore the failed workspace service, verify health, then resume."
|
|
},
|
|
"comment": "The workspace service is unavailable; I own restoring it."
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/issues/{}/checkout": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Atomic checkout (claim + start). Idempotent if you already own it."
|
|
},
|
|
"POST /api/issues/{}/release": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Release execution locks; preserve terminal task ownership"
|
|
},
|
|
"GET /api/issues/{}/comments": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "List comments"
|
|
},
|
|
"GET /api/issues/{}/comments/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Get a specific comment by ID"
|
|
},
|
|
"POST /api/issues/{}/comments": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Add comment (@-mentions provide context)",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"body": "[@QA Reviewer](agent://qa-agent-id) has relevant testing context."
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/issues/{}/inbox-archive": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Archive issue from responsible user's inbox; optional `userId` requires saved target-user opt-in or cross-user grant"
|
|
},
|
|
"DELETE /api/issues/{}/inbox-archive": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Reverse inbox archive; same target and policy rules"
|
|
},
|
|
"GET /api/issues/{}/interactions": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "List issue-thread interactions"
|
|
},
|
|
"POST /api/issues/{}/interactions": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Create issue-thread interaction (`suggest_tasks`, `ask_user_questions`, `request_confirmation`, `request_checkbox_confirmation`, `request_item_verdicts`)",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"kind": "ask_user_questions",
|
|
"idempotencyKey": "questions:{issueId}:responsibility-text:v1",
|
|
"title": "Hire responsibility",
|
|
"resolverPolicy": "human_only",
|
|
"continuationPolicy": "wake_assignee",
|
|
"payload": {
|
|
"version": 1,
|
|
"questions": [
|
|
{
|
|
"id": "responsibility",
|
|
"prompt": "What should the new agent be responsible for?",
|
|
"selectionMode": "single",
|
|
"required": true,
|
|
"options": [
|
|
{
|
|
"id": "describe",
|
|
"label": "I'll describe it",
|
|
"freeText": true
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"questionSet": {
|
|
"schema": "paperclip.question_set.v1",
|
|
"questions": [
|
|
{
|
|
"id": "responsibility",
|
|
"prompt": "What should the new agent be responsible for?",
|
|
"required": true,
|
|
"answerMode": "text"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"kind": "ask_user_questions",
|
|
"idempotencyKey": "questions:{issueId}:responsibility:v1",
|
|
"title": "Hire responsibility",
|
|
"resolverPolicy": "human_only",
|
|
"continuationPolicy": "wake_assignee",
|
|
"payload": {
|
|
"version": 1,
|
|
"questions": [
|
|
{
|
|
"id": "responsibility",
|
|
"prompt": "What should the new agent be responsible for?",
|
|
"selectionMode": "single",
|
|
"required": true,
|
|
"allowOther": true,
|
|
"options": [
|
|
{
|
|
"id": "research",
|
|
"label": "Research",
|
|
"description": "Find and summarize information."
|
|
},
|
|
{
|
|
"id": "writing",
|
|
"label": "Writing",
|
|
"description": "Draft and edit content."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"kind": "request_confirmation",
|
|
"idempotencyKey": "confirmation:{issueId}:{targetKey}:{targetVersion}",
|
|
"title": "Plan approval",
|
|
"continuationPolicy": "wake_assignee",
|
|
"payload": {
|
|
"version": 1,
|
|
"prompt": "Accept this plan?",
|
|
"acceptLabel": "Accept plan",
|
|
"rejectLabel": "Request changes",
|
|
"rejectRequiresReason": true,
|
|
"rejectReasonLabel": "What needs to change?",
|
|
"detailsMarkdown": "Review the latest plan document before accepting.",
|
|
"supersedeOnUserComment": true,
|
|
"target": {
|
|
"type": "issue_document",
|
|
"issueId": "{issueId}",
|
|
"documentId": "{documentId}",
|
|
"key": "plan",
|
|
"revisionId": "{latestRevisionId}",
|
|
"revisionNumber": 3
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"kind": "request_checkbox_confirmation",
|
|
"idempotencyKey": "checkbox:{issueId}:cleanup-files:{planRevisionId}",
|
|
"title": "Confirm files to delete",
|
|
"summary": "Pick the files you want removed before I run the cleanup.",
|
|
"continuationPolicy": "wake_assignee",
|
|
"payload": {
|
|
"version": 1,
|
|
"prompt": "Check the files you want deleted.",
|
|
"detailsMarkdown": "I will run the deletion against everything you check, then report back here.",
|
|
"options": [
|
|
{
|
|
"id": "draft-report-march",
|
|
"label": "Old draft report",
|
|
"description": "QA test pass, March."
|
|
},
|
|
{
|
|
"id": "tmp-export-2025",
|
|
"label": "tmp/export-2025.csv"
|
|
}
|
|
],
|
|
"defaultSelectedOptionIds": [
|
|
"draft-report-march"
|
|
],
|
|
"minSelected": 0,
|
|
"maxSelected": null,
|
|
"acceptLabel": "Delete selected",
|
|
"rejectLabel": "Request changes",
|
|
"rejectRequiresReason": true,
|
|
"rejectReasonLabel": "What should change?",
|
|
"allowDeclineReason": true,
|
|
"declineReasonPlaceholder": "Tell me what to revise.",
|
|
"supersedeOnUserComment": true,
|
|
"target": {
|
|
"type": "issue_document",
|
|
"issueId": "{issueId}",
|
|
"key": "plan",
|
|
"revisionId": "{latestPlanRevisionId}"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"kind": "request_item_verdicts",
|
|
"idempotencyKey": "verdicts:{issueId}:generated-artifacts:{planRevisionId}",
|
|
"title": "Review generated artifacts",
|
|
"continuationPolicy": "wake_assignee",
|
|
"payload": {
|
|
"version": 1,
|
|
"prompt": "Review each generated artifact.",
|
|
"detailsMarkdown": "Approve artifacts that are ready. Reject items that need another pass.",
|
|
"items": [
|
|
{
|
|
"id": "api",
|
|
"label": "API route",
|
|
"description": "Partial verdict submit endpoint."
|
|
},
|
|
{
|
|
"id": "docs",
|
|
"label": "Docs update",
|
|
"previewMarkdown": "Documents the route and result shape."
|
|
}
|
|
],
|
|
"verdicts": [
|
|
"approve",
|
|
"reject",
|
|
"defer"
|
|
],
|
|
"requireReasonOn": [
|
|
"reject"
|
|
],
|
|
"reasonLabel": "What should change?",
|
|
"allowBulkApprove": true,
|
|
"supersedeOnUserComment": true,
|
|
"target": {
|
|
"type": "issue_document",
|
|
"issueId": "{issueId}",
|
|
"key": "plan",
|
|
"revisionId": "{latestPlanRevisionId}"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/issues/{}/interactions/{}/resolve-from-comment": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Resolve a confirmation from the latest user reply; body: commentId, decision (accept/reject), selectedOptionIds for checkbox acceptance, optional reason"
|
|
},
|
|
"POST /api/issues/{}/interactions/{}/accept": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Accept suggested tasks or confirmation (body: `selectedClientKeys` for `suggest_tasks`; `selectedOptionIds` for `request_checkbox_confirmation`)",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"selectedOptionIds": [
|
|
"draft-report-march",
|
|
"tmp-export-2025"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/issues/{}/interactions/{}/reject": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Reject suggested tasks or confirmation",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"reason": "Keep the March draft; only delete tmp/export-2025.csv."
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/issues/{}/interactions/{}/respond": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Respond to structured questions"
|
|
},
|
|
"POST /api/issues/{}/interactions/{}/verdicts": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Submit partial item verdicts for `request_item_verdicts`",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"verdicts": [
|
|
{
|
|
"id": "api",
|
|
"verdict": "approve"
|
|
},
|
|
{
|
|
"id": "docs",
|
|
"verdict": "reject",
|
|
"reason": "Needs install instructions."
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/issues/{}/interactions/{}/withdraw": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Withdraw any pending interaction; optional `{ \"reason\": string }`; creator agent, current assignee agent, or board user"
|
|
},
|
|
"GET /api/issues/{}/documents": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "List issue documents"
|
|
},
|
|
"GET /api/issues/{}/documents/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Get issue document by key"
|
|
},
|
|
"PUT /api/issues/{}/documents/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Create or update issue document (send `baseRevisionId` when updating)"
|
|
},
|
|
"GET /api/issues/{}/documents/{}/revisions": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Document revision history"
|
|
},
|
|
"DELETE /api/issues/{}/documents/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Delete document (board-only)"
|
|
},
|
|
"GET /api/issues/{}/approvals": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "List approvals linked to issue"
|
|
},
|
|
"POST /api/issues/{}/approvals": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Link approval to issue"
|
|
},
|
|
"DELETE /api/issues/{}/approvals/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Unlink approval from issue"
|
|
},
|
|
"GET /api/execution-workspaces/{}": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Execution workspace detail including runtime services and service URLs"
|
|
},
|
|
"POST /api/execution-workspaces/{}/runtime-services/start": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Start configured workspace services"
|
|
},
|
|
"POST /api/execution-workspaces/{}/runtime-services/restart": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Restart configured workspace services"
|
|
},
|
|
"POST /api/execution-workspaces/{}/runtime-services/stop": {
|
|
"section": "Issues (Tasks)",
|
|
"description": "Stop workspace runtime services"
|
|
},
|
|
"GET /api/companies": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "List all companies"
|
|
},
|
|
"POST /api/companies": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Create company"
|
|
},
|
|
"GET /api/companies/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Company details"
|
|
},
|
|
"PATCH /api/companies/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Update company fields"
|
|
},
|
|
"POST /api/companies/{}/logo": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Upload company logo (multipart)"
|
|
},
|
|
"POST /api/companies/{}/archive": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Archive company"
|
|
},
|
|
"GET /api/companies/{}/projects": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "List projects"
|
|
},
|
|
"GET /api/projects/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Project details"
|
|
},
|
|
"POST /api/companies/{}/projects": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Create project (`repositoryIds`/`repositoryUrls` arrays or inline `workspace`; optional `idempotencyKey`)",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"name": "Web and API",
|
|
"repositoryUrls": [
|
|
"https://github.com/acme/web",
|
|
"https://github.com/acme/api"
|
|
],
|
|
"idempotencyKey": "web-api-project"
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"name": "Paperclip Mobile App",
|
|
"description": "Ship iOS + Android client",
|
|
"status": "planned",
|
|
"goalIds": [
|
|
"{goalId}"
|
|
],
|
|
"workspace": {
|
|
"name": "paperclip-mobile",
|
|
"cwd": "/Users/me/paperclip-mobile",
|
|
"repoUrl": "https://github.com/acme/paperclip-mobile",
|
|
"repoRef": "main",
|
|
"isPrimary": true
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"name": "Paperclip Mobile App",
|
|
"description": "Ship iOS + Android client",
|
|
"status": "planned"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"PATCH /api/projects/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Update project"
|
|
},
|
|
"GET /api/projects/{}/workspaces": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "List project workspaces"
|
|
},
|
|
"POST /api/projects/{}/workspaces": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Create project workspace",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"cwd": "/Users/me/paperclip-mobile",
|
|
"repoUrl": "https://github.com/acme/paperclip-mobile",
|
|
"repoRef": "main",
|
|
"isPrimary": true
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"PATCH /api/projects/{}/workspaces/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Update project workspace"
|
|
},
|
|
"DELETE /api/projects/{}/workspaces/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Delete project workspace"
|
|
},
|
|
"GET /api/companies/{}/goals": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "List goals"
|
|
},
|
|
"GET /api/goals/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Goal details"
|
|
},
|
|
"POST /api/companies/{}/goals": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Create goal"
|
|
},
|
|
"PATCH /api/goals/{}": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Update goal"
|
|
},
|
|
"POST /api/companies/{}/openclaw/invite-prompt": {
|
|
"section": "Companies, Projects, Goals",
|
|
"description": "Generate OpenClaw invite prompt (CEO/board only)",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"agentMessage": "optional note for the joining OpenClaw agent"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"GET /api/companies/{}/routines": {
|
|
"section": "Routines",
|
|
"description": "List all routines in company"
|
|
},
|
|
"GET /api/routines/{}": {
|
|
"section": "Routines",
|
|
"description": "Routine details including triggers"
|
|
},
|
|
"POST /api/companies/{}/routines": {
|
|
"section": "Routines",
|
|
"description": "Create routine (`assigneeAgentId` + `projectId` required; agents: own only)"
|
|
},
|
|
"PATCH /api/routines/{}": {
|
|
"section": "Routines",
|
|
"description": "Update routine (agents: own only, cannot reassign)"
|
|
},
|
|
"POST /api/routines/{}/triggers": {
|
|
"section": "Routines",
|
|
"description": "Add trigger (`schedule`, `webhook`, or `api` kind)"
|
|
},
|
|
"PATCH /api/routine-triggers/{}": {
|
|
"section": "Routines",
|
|
"description": "Update trigger (e.g. disable, change cron)"
|
|
},
|
|
"DELETE /api/routine-triggers/{}": {
|
|
"section": "Routines",
|
|
"description": "Delete trigger"
|
|
},
|
|
"POST /api/routine-triggers/{}/rotate-secret": {
|
|
"section": "Routines",
|
|
"description": "Rotate webhook signing secret (previous secret immediately invalidated)"
|
|
},
|
|
"POST /api/routines/{}/run": {
|
|
"section": "Routines",
|
|
"description": "Manual run (bypasses schedule; concurrency policy still applies)"
|
|
},
|
|
"POST /api/routine-triggers/public/{}/fire": {
|
|
"section": "Routines",
|
|
"description": "Fire webhook trigger from external system"
|
|
},
|
|
"GET /api/routines/{}/runs": {
|
|
"section": "Routines",
|
|
"description": "Run history (default 50)"
|
|
},
|
|
"GET /api/companies/{}/approvals": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "List approvals (`?status=pending`)"
|
|
},
|
|
"POST /api/companies/{}/approvals": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Create approval request",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"type": "approve_ceo_strategy",
|
|
"requestedByAgentId": "{your-agent-id}",
|
|
"payload": {
|
|
"plan": "..."
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"POST /api/companies/{}/agent-hires": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Create hire request/agent draft",
|
|
"examples": [
|
|
{
|
|
"body": {
|
|
"name": "Marketing Analyst",
|
|
"role": "researcher",
|
|
"reportsTo": "{manager-agent-id}",
|
|
"capabilities": "Market research, competitor analysis",
|
|
"adapterType": "paperclip_runner",
|
|
"inheritRuntimeFrom": "caller",
|
|
"instructionsBundle": {
|
|
"entryFile": "AGENTS.md",
|
|
"files": {
|
|
"AGENTS.md": "# Marketing Analyst\nResearch markets and competitors. Report findings with sources to your manager.\n"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"body": {
|
|
"name": "Marketing Analyst",
|
|
"role": "researcher",
|
|
"reportsTo": "{manager-agent-id}",
|
|
"capabilities": "Market research, competitor analysis",
|
|
"budgetMonthlyCents": 5000,
|
|
"adapterType": "codex_local",
|
|
"instructionsBundle": {
|
|
"entryFile": "AGENTS.md",
|
|
"files": {
|
|
"AGENTS.md": "# Marketing Analyst\nResearch markets and competitors. Report findings with sources to your manager. Follow the Paperclip operational skill.\n"
|
|
}
|
|
},
|
|
"runtimeConfig": {
|
|
"heartbeat": {
|
|
"enabled": false,
|
|
"wakeOnDemand": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"GET /api/approvals/{}": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Approval details"
|
|
},
|
|
"GET /api/approvals/{}/issues": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Issues linked to approval"
|
|
},
|
|
"GET /api/approvals/{}/comments": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Approval comments"
|
|
},
|
|
"POST /api/approvals/{}/comments": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Add approval comment"
|
|
},
|
|
"POST /api/approvals/{}/approve": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Approve approval request"
|
|
},
|
|
"POST /api/approvals/{}/reject": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Reject approval request"
|
|
},
|
|
"POST /api/approvals/{}/request-revision": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Board asks for revision"
|
|
},
|
|
"POST /api/approvals/{}/resubmit": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Resubmit revised approval"
|
|
},
|
|
"POST /api/companies/{}/cost-events": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Report cost event"
|
|
},
|
|
"GET /api/companies/{}/costs/summary": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Company cost summary"
|
|
},
|
|
"GET /api/companies/{}/costs/by-agent": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Costs by agent"
|
|
},
|
|
"GET /api/companies/{}/costs/by-project": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Costs by project"
|
|
},
|
|
"GET /api/companies/{}/activity": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Activity log"
|
|
},
|
|
"GET /api/companies/{}/dashboard": {
|
|
"section": "Approvals, Costs, Activity, Dashboard",
|
|
"description": "Company health summary"
|
|
},
|
|
"GET /api/companies/{}/secrets": {
|
|
"section": "Secrets",
|
|
"description": "List secrets (metadata only)"
|
|
},
|
|
"POST /api/companies/{}/secrets": {
|
|
"section": "Secrets",
|
|
"description": "Create secret"
|
|
},
|
|
"PATCH /api/secrets/{}": {
|
|
"section": "Secrets",
|
|
"description": "Update secret value (creates new version)"
|
|
},
|
|
"POST /api/agents/me/secret-proposals": {
|
|
"section": "Secrets",
|
|
"description": "Propose a secret or agent binding for board approval"
|
|
},
|
|
"GET /api/agents/me/secret-proposals": {
|
|
"section": "Secrets",
|
|
"description": "List proposals created by the agent and incoming bindings targeting it"
|
|
},
|
|
"DELETE /api/agents/me/secret-proposals/{}": {
|
|
"section": "Secrets",
|
|
"description": "Withdraw one pending proposal created by the agent"
|
|
},
|
|
"GET /api/agents/me/secrets": {
|
|
"section": "Secrets",
|
|
"description": "List secrets accessible to the current run (metadata only)"
|
|
},
|
|
"POST /api/agents/me/secrets/{}/value": {
|
|
"section": "Secrets",
|
|
"description": "Fetch one granted secret value; request body is empty"
|
|
}
|
|
};
|