Files
PaperClipAI/server/src/services/native-runtime/runner-api-reference.ts
T
DottaandPaperclip d034ba7491 fix(interactions): derive question storage from canonical forms (#14946)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents request human input through durable issue interactions.
> - A question form has a canonical presentation and a compatibility
storage format.
> - The creation API required agents to write both formats.
> - Tool guidance told agents to split text and choice questions across
those formats.
> - This pull request accepts one complete canonical form and derives
storage fields on the server.
> - The benefit is a complete question card with stable answer and retry
behavior.

## Linked Issues or Issue Description

Related work: Refs #13630 and #14430. PR #13630 addresses the display of
historical partial forms. This change fixes creation and keeps the check
that rejects conflicting new forms.

**What happened?**

A question save supplied three compatibility questions and one canonical
text question. The API correctly rejected the incomplete canonical form.
The Runner's tool description encouraged this split. Sending only a
complete canonical form also failed because the API required
compatibility questions.

**Expected behavior**

An agent sends one complete `payload.questionSet` with every text and
choice question. Paperclip derives `payload.questions` for storage and
answer compatibility. Existing legacy requests remain valid. Explicitly
conflicting dual forms remain invalid.

**Steps to reproduce**

1. Call `paperclip_request_human_input` with `interactionKind:
"questions"`.
2. Send `payload: { version: 1, questionSet: ... }` with a required text
question and a required choice question.
3. The old API rejects the missing compatibility questions. With this
change, it stores both questions and preserves the canonical form.
4. Retry with the same idempotency key. Confirm that only one
interaction exists.
5. Submit both answers. Confirm that the normal resolver and
continuation rules apply.

**Paperclip version or commit**

The branch is based on `cf8ad63c8`. The problem affects the native
Runner and the interaction creation API.

**Deployment mode**

Server deployment with the native Paperclip Runner. Integration tests
use the real interaction service and an embedded test database.

## What Changed

- Add one shared canonical-to-storage projection. Reuse it for native
harness question requests.
- Accept canonical-only question creation at the shared validator and
server boundary.
- Export the input type and update the plugin SDK and its RPC contract.
- Advertise a typed, complete question form in the live and scenario
tool schemas.
- Enforce canonical text and custom-answer constraints before ordinary
or native resolution. Preserve harmless display whitespace.
- Run regex matching in isolated workers with a deadline and resource
limits. Both answer paths await the result before persistence. Saved
native delivery uses the validated answer without taking another worker
slot.
- Update agent guidance and generated Runner contracts.
- Test mixed forms, option-ID collisions, retries, answers, legacy
requests, and conflicting forms.

## Verification

- Interaction service, HTTP route, native bridge, and Runner authority
suites: 221 tests passed after correcting an obsolete tool-description
assertion.
- Shared validator, plugin SDK, CLI, and UI compatibility suites: 67
tests passed.
- Runner core tool-contract suite: 20 tests passed. AJV validates live
and scenario schemas.
- Final review regressions: 172 shared, service, native bridge, and
authority tests passed. These cover text length, pattern, numeric
limits, whitespace, custom option IDs, and historical pending cards.
- Runner session suites: 67 tests passed. Published example tests: 4
tests passed.
- Server typecheck and the shared/server builds passed after the
compatibility fixes.
- Final delivery verification: 35 response-delivery tests passed. The
native delivery regression proves saved answers do not enter pattern
workers; server typecheck and build passed.
- Pattern security and answer-flow verification: 205 tests passed after
repairing the child fixture loader. These cover pathological matching,
event-loop responsiveness, worker concurrency, slot cleanup, HTTP
routes, native delivery, and the full helper in a child process.
- `pnpm -r typecheck` passed on the bounded-worker revision.
- `pnpm build` passed on the bounded-worker revision.
- All 55 GitHub checks passed on `fe457af`; four optional jobs were
skipped. An unchanged Cursor adapter test timed out once in CI, passed
locally, and passed on one failed-job rerun.
- Reviewers can send the canonical-only mixed form above and verify that
the saved interaction contains both canonical and compatibility
questions.

## Risks

- The creation API accepts a new input shape. Stored rows and answer
contracts keep the existing shape.
- The shared projection must preserve synthetic free-text option IDs.
Collision and native round-trip tests cover this behavior.
- Historical partial rows remain readable. New conflicting dual forms,
including written-answer mismatches, remain rejected.
- Existing pending cards retain the written-answer paths offered by
their stored options. Canonical text constraints still apply.
- Ordinary answers now enforce declared canonical constraints before
persistence. Invalid answers leave the card pending.
- Regex validation has a one-second deadline and a four-worker capacity
limit. A complex pattern or capacity error leaves the card pending with
a validation error.
- No database migration or change to company authorization is required.

## Model Used

- OpenAI GPT-6 through Codex. The session exposes the GPT-6 model
family; its exact runtime model identifier and context window size are
not exposed. Used reasoning, tool use, and code 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>
2026-10-02 14:21:11 -05:00

797 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,
"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,
"questionSet": {
"schema": "paperclip.question_set.v1",
"questions": [
{
"id": "responsibility",
"prompt": "What should the new agent be responsible for?",
"answerMode": "single_select",
"required": true,
"customAnswer": {
"enabled": 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"
}
};