@copperlineai/paperclip-triggerdev-adapter
v0.2.2
Published
Paperclip adapter that queues agent runs on Trigger.dev and streams realtime run updates back to Paperclip.
Readme
@copperlineai/paperclip-triggerdev-adapter
Paperclip adapter that queues agent heartbeats as Trigger.dev runs and streams run status, stdout, and stderr back into Paperclip.
Use this package when you want Paperclip to hand off work to Trigger.dev instead of running the agent process directly in the Paperclip server environment.
What it does
- Queues a Trigger.dev task for each Paperclip agent heartbeat.
- Sends Paperclip run, agent, issue, runtime, and context data in the Trigger.dev payload.
- Attaches a run-scoped Paperclip credential so the Trigger.dev worker can call back into Paperclip without a long-lived board API key.
- Includes the Paperclip server URL in the payload so Trigger.dev workers can derive the API URL without Paperclip API URL environment variables.
- Optionally waits for the Trigger.dev run to finish and maps terminal Trigger.dev status back to the Paperclip run result.
- Uses Trigger.dev Realtime to mirror child runtime feedback into Paperclip logs and translate OpenCode-style JSON events into Paperclip transcript entries.
Requirements
- Node.js 22 or newer.
- Paperclip with
@paperclipai/adapter-utilsavailable. - Trigger.dev SDK v4.4 or newer.
- A Trigger.dev project with a task that accepts the Paperclip payload. The companion task in this repository uses the default id
paperclip-agent-run. PAPERCLIP_AGENT_JWT_SECRETorBETTER_AUTH_SECRETconfigured on the Paperclip server so Paperclip can mint run-scoped agent credentials.
Installation
npm install @copperlineai/paperclip-triggerdev-adapter @trigger.dev/sdkThe package exposes server, UI, CLI, and UI parser entry points:
import { type, label } from "@copperlineai/paperclip-triggerdev-adapter";
import { createServerAdapter } from "@copperlineai/paperclip-triggerdev-adapter/server";
import { triggerDevUIAdapter } from "@copperlineai/paperclip-triggerdev-adapter/ui";Paperclip configuration
Configure an agent to use the trigger_dev adapter.
Minimum configuration:
{
"type": "trigger_dev",
"config": {
"taskId": "paperclip-agent-run"
},
"env": {
"TRIGGER_SECRET_KEY": "tr_dev_..."
}
}For Trigger.dev Cloud, leave triggerApiUrl unset. For a self-hosted Trigger.dev instance, set triggerApiUrl in adapter config or bind TRIGGER_API_URL in adapter environment.
Adapter configuration reference
| Field | Default | Description |
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| taskId | paperclip-agent-run | Trigger.dev task identifier to queue for each heartbeat. |
| triggerApiUrl | unset | Optional Trigger.dev API endpoint. Leave unset for Trigger.dev Cloud; set for self-hosted Trigger.dev. |
| paperclipServerUrl | server default | Optional Paperclip server URL to pass to the Trigger.dev task. Normally derived from the Paperclip server environment/listen host. |
| triggerOptions | {} | Object passed to tasks.trigger, such as queue, concurrencyKey, ttl, tags, delay, maxAttempts, or metadata. |
| payloadTemplate | {} | Object merged into the default Paperclip payload before queueing. String values may reference {{run.*}}, {{agent.*}}, {{runtime.*}}, {{context.*}}, and {{config.*}}. |
| waitForCompletion | true | Keep the Paperclip run open until the Trigger.dev run reaches a terminal status. |
| subscribe | true | Subscribe to Trigger.dev Realtime run-status updates. When false, the adapter falls back to polling. |
| streamLogs | true | Mirror child runtime stdout and stderr from the Trigger.dev realtime stream into Paperclip. |
| streamKey | paperclip-feedback | Trigger.dev realtime stream key that carries Paperclip stdout and stderr chunks. |
| streamDrainMs | 3000 | How long to keep draining realtime stream chunks after a terminal run status. |
| pollTimeoutMs | 3600000 | Maximum time Paperclip waits for the Trigger.dev run to finish. |
| heartbeatLogIntervalMs | 15000 | Minimum interval between non-terminal realtime status log lines. |
Environment variables
Paperclip adapter environment
| Variable | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| TRIGGER_SECRET_KEY | Yes | Trigger.dev API secret key used to queue and inspect runs. Prefer binding this in the agent adapter environment as a Paperclip Secret. |
| TRIGGER_API_URL | No | Trigger.dev API URL for self-hosted deployments. Prefer triggerApiUrl for non-secret config when possible. |
| GH_TOKEN | No | GitHub token forwarded to the companion Trigger.dev task for private repository checkout. Preferred over GITHUB_TOKEN when both are configured. |
| GITHUB_TOKEN | No | Fallback GitHub token forwarded to the companion Trigger.dev task for private repository checkout. |
Paperclip server-level TRIGGER_SECRET_KEY and TRIGGER_API_URL are still supported as backwards-compatible fallbacks, but per-agent adapter environment values are preferred.
Paperclip server environment
| Variable | Required | Description |
| ---------------------------------------------------- | -------- | ---------------------------------------------------------------------------------- |
| PAPERCLIP_AGENT_JWT_SECRET or BETTER_AUTH_SECRET | Yes | Allows Paperclip to mint run-scoped credentials for the queued Trigger.dev worker. |
Trigger.dev task expectations
The queued Trigger.dev task receives a payload containing Paperclip identifiers, runtime information, adapter configuration, context, paperclipRunCredential, and paperclipServerUrl. The task should:
- Validate the payload.
- Prepare the workspace where the agent should run. For deployable Trigger.dev tasks, do not use Paperclip's local
cwddirectly; treat it as source metadata, create a task-local directory under the task filesystem, and clonecontext.paperclipWorkspace.repoUrlatrepoRefwhen present. If the repository is private, provide a checkout token asGH_TOKENorGITHUB_TOKENin the agent adapter environment, or configure the same variable in the Trigger.dev task environment. Per-agent checkout token values are forwarded as dedicated checkout env only; the full adapter env is not included in the Trigger.dev payload. Per-agent values win over Trigger.dev environment values, andGH_TOKENwins overGITHUB_TOKENwithin each source. - Start the desired Paperclip agent runtime.
- Derive the Paperclip API URL from
paperclipServerUrl. Do not source the Paperclip API URL from Trigger.dev task environment variables. - Expose the run-scoped credential to that runtime as
PAPERCLIP_AUTH_TOKEN. Existing Paperclip skills also expect the same JWT asPAPERCLIP_API_KEY; this is a compatibility alias, not a long-lived board API key. - Append feedback chunks to the realtime stream named by
streamKeywhen you want stdout, stderr, tool use, assistant text, or result events mirrored into Paperclip.
A feedback stream chunk should have this shape:
type PaperclipFeedbackChunk = {
stream: "stdout" | "stderr";
text: string;
source?: string;
timestamp?: string;
};The adapter subscribes with Trigger.dev Realtime, receives these chunks, and writes the original plaintext stdout/stderr lines into Paperclip logs. The package UI parser then translates OpenCode-compatible JSONL into Paperclip transcript entries such as assistant, tool_call, tool_result, stdout, stderr, system, and result. This keeps raw logs readable and keeps the integration installable as an npm adapter package without requiring Paperclip server changes.
For OpenCode-compatible runtimes, write one JSON event per line to text. The adapter forwards those lines directly to Paperclip, so type: "text", type: "tool_use", type: "reasoning", type: "step_finish", and type: "error" render the same way they do for opencode_local. The companion Trigger.dev runner under runner/trigger.dev implements the default paperclip-agent-run task, uses the paperclip-feedback stream key, buffers partial stdout/stderr chunks until newline boundaries, derives the Paperclip API URL from the payload-provided server URL, and forwards the run-scoped credential as PAPERCLIP_AUTH_TOKEN plus the PAPERCLIP_API_KEY compatibility alias.
Example with Trigger options
{
"type": "trigger_dev",
"config": {
"taskId": "paperclip-agent-run",
"triggerOptions": {
"queue": { "name": "paperclip-agents", "concurrencyLimit": 5 },
"tags": ["paperclip", "agent"],
"maxAttempts": 1
},
"waitForCompletion": true,
"subscribe": true,
"streamLogs": true
},
"env": {
"TRIGGER_SECRET_KEY": "tr_dev_..."
}
}Troubleshooting
missing_trigger_secret_key: bindTRIGGER_SECRET_KEYin the agent adapter environment, or configure the Paperclip server-level fallback.missing_paperclip_run_auth_token: setPAPERCLIP_AGENT_JWT_SECRETorBETTER_AUTH_SECRETon the Paperclip server.- No streamed logs: confirm
streamLogsis true and the Trigger.dev task appends chunks to the samestreamKeyconfigured in Paperclip. - Self-hosted Trigger.dev cannot be reached: verify
triggerApiUrlorTRIGGER_API_URLpoints at the Trigger.dev API endpoint reachable from the Paperclip server.
Development
bun install
bun run build:trigger-adapter
bun run --cwd packages/adapters/trigger-dev test