Build a webhook Workflow
Say your site's support form POSTs a JSON submission somewhere. This guide wires that POST to a three-step pipeline: a cheap model call triages the submission, a filter drops anything that isn't a real bug, and a tool step files the rest in Linear — deterministically, with no Agent in the loop at all.
Before you start
- A workspace-scoped Linear connection, healthy enough to have cached its tool list — tool steps run on workspace connections.
- Familiarity with how a Workflow's trigger and steps fit together — see Workflows.
- A way to send a JSON POST for testing (
curlis enough).
Steps
- Create a Workflow and open the workflow editor. Describing the job to the copilot composer will draft all of this for you; the steps below are the direct route.
- On the Trigger card, pick Webhook. The draft shows a note that the token card goes live at publish — there's nothing to copy yet. Every top-level key of whatever JSON gets POSTed will be addressable as
@trigger.<key>. - Add an Infer step, slugged
triage: thequickpreset, a prompt referencing@trigger.email,@trigger.subject, and@trigger.body, and a declared output schema — say{is_bug, title, summary}— so the next steps get fields rather than prose. - Add a Filter step on the condition
@steps.triage.result.is_bugis true. A top-level filter that comes up false skips every remaining step and the run still counts as succeeded — a non-bug submission is a successful triage, not a failure. - Add a Tool step: the Linear connection, its create-issue tool from the searchable picker, args templated from
@steps.triage.result.titleand@steps.triage.result.summaryplus@trigger.emailfor attribution. Test step runs it for real against a sample scope — real side effects included, so expect a real test issue. - Click Publish. It's instant — a Workflow builds nothing — and publish is what unlocks the token: a runnable pipeline is required before it goes through.
- The trigger's live Ingress token card now appears. Click Generate token. The plaintext token appears exactly once, in an amber card: "Copy this now — we store only a hash, so it won't be shown again." The card also shows the live ingress URL. Copy the token now — there is no way to retrieve it again later, only to rotate it for a new one.
Send a request to the ingress URL from step 7:
curl -X POST https://your-domain.example/t/whk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
-H 'content-type: application/json' \
-d '{"email":"user@example.com","subject":"Login broken","body":"Cannot sign in since this morning."}'
What you should see
The response to that curl is only an acknowledgement — {"accepted": true, "runId": …} — never the result. Open the Workflow's Runs tab: a new run replays the pipeline as a step timeline — the triage step with its rendered prompt and structured output, the filter's verdict, and the tool step with the created issue in its output. A submission the triage judged not-a-bug shows the filter false and the tool step skipped, with the run still succeeded.
Operational notes
- Request bodies are capped at 256 KiB — larger requests are rejected before a run starts.
- Both the token and the caller's IP are rate-limited independently; sending too fast gets a
429with aRetry-Afterheader rather than queuing. - A POST that arrives while a previous run of this Workflow is still live is skipped, not queued — the response still says 2xx, with
{"accepted": false, "reason": "overlap_skipped"}, since the caller did nothing wrong. - If you lose the token, there's no way to reveal it again — mint a new one instead. Rotating immediately invalidates the old token; every caller still using it starts failing until it switches to the new one.
If it doesn't work
401on the request — the token is wrong, expired, or was rotated out from under you. Mint a fresh one and update the caller.413on the request — the body is over the 256 KiB cap. Trim the payload; the platform doesn't accept partial or streamed bodies.429on the request — you're sending faster than the per-token or per-IP limit allows. Back off for the number of seconds in theRetry-Afterheader.- The tool step fails with a tool or argument error — the tool name or arg shape doesn't match what the Linear server actually exposes. Re-pick the tool from the picker (it reads the server's own list) and re-check the args against its schema; a tool error is the server answering, so it's never retried for you.
See Triggers for how the other trigger kinds compare, limits & defaults for the platform's other ceilings, and troubleshooting for anything not covered above.