Workflows
@evolve-framework/authoring-workflows is an opt-in addon for the
authoring stack. The chrome, the chat panel, the MCP endpoint, the
push-to-CMS flow — none of that depends on this package. Install it
only when you have a use case for headless, long-running content
production that doesn’t fit the interactive chat surface.
When you want this
Section titled “When you want this”Reach for the workflows addon when content production needs to run without an editor sitting in front of a chat panel. Concrete cases:
- Bulk page generation: 200 SEO landing pages overnight from a CSV of keywords.
- Campaign hubs: one brief expands into a hub page plus a fan-out of child pages, all landing as drafts ready for editorial review.
- Scheduled content: a workflow triggered by a cron or external system that generates content at a specific time.
- External integration: another system (PIM, planning tool, marketing automation) posts a brief and waits for a draft.
If your need is “a human editor opens the chat panel and asks for a
page”, you don’t need this — /chat already does that, and
/mcp extends it to headless AI clients in the same
interactive shape.
How it fits
Section titled “How it fits”graph LR
Trigger["External trigger<br/>API / MCP / chrome"] --> Routes
Routes["/workflows/*"] --> Engine["Inngest engine"]
Engine --> Flows["Flow definitions"]
Flows --> Callbacks["Host callbacks<br/>generatePage, savePage, ..."]
Callbacks --> AI["AI providers"]
Callbacks --> CMS["CMS via gateway"]
Engine --> Redis[("Redis<br/>run state + audit")]
The package mounts its routes on the same Fastify host as
authoring-server, adding:
POST /workflows/runs— trigger a run via shared bearer token or editor session.GET /workflows/runs[/:id]— read run status and trace.GET /workflows/definitions— list available flows.POST /workflows/compile— turn a natural-language brief into a typed workflow definition via the AI provider.
The actual content production happens through host-injected callbacks — the workflows package owns orchestration (Inngest steps, retries, run state in Redis, audit trace), the host owns the domain-specific operations (AI generation, CMS writes, tool context). That keeps the package CMS-agnostic and lets each project plug in its own AI orchestrator.
Install
Section titled “Install”pnpm add @evolve-framework/authoring-workflowsPeer deps: @evolve-framework/authoring-server and
@evolve-framework/authoring-core (same major). Optional:
@evolve-framework/authoring-ai-providers (only needed for the
natural-language compiler and the default flows).
You also need a running Inngest (self-hosted or the dev server) and Redis. Both already standard for most Evolve deployments.
Mount on the same Fastify host as authoring-server, after
mountAuthoringEditor so the session signer is initialised:
import { mountWorkflows } from "@evolve-framework/authoring-workflows";import { readSessionFromRequest } from "@evolve-framework/authoring-server";
mountWorkflows(app, { triggerToken: config.WORKFLOW_TRIGGER_TOKEN, redisUri: config.REDIS_URL, inngestEventKey: config.INNGEST_EVENT_KEY, inngestSigningKey: config.INNGEST_SIGNING_KEY,
// Editor-cookie validator for chrome-driven "+ New run". validateEditorSession: async (req) => (await readSessionFromRequest(req)) !== null,
// Host-injected operations — see workflow-callbacks.ts. generatePageFromBrief, savePageDraft, planCampaign, buildToolContext,});The reference monorepo wires the callbacks against
@evolve-framework/authoring-server/lib and
@evolve-framework/authoring-ai-providers in
backend/services/authoring/src/workflow-callbacks.ts. Copy that as
a starting point and adapt to your AI surface.
Configuration
Section titled “Configuration”| Field | Required | Purpose |
|---|---|---|
triggerToken |
yes (or validateEditorSession) |
Shared bearer for external systems hitting POST /workflows/runs. Set to null to disable the external trigger. |
redisUri |
yes | Run records, draft inventory, audit log. |
inngestEventKey |
yes | Inngest event key (self-hosted or dev server). |
inngestSigningKey |
yes | Inngest signing key. |
inngestServeHost |
optional | Override the URL the SDK self-reports. Set to http://host.docker.internal:<port> when Inngest runs in Docker. |
validateEditorSession |
optional | Editor-cookie validator for the chrome’s “+ New run” button. |
generatePageFromBrief |
optional | Host AI orchestrator. Omit on viewer-only hosts. |
savePageDraft |
optional | Host CMS writer. |
planCampaign |
optional | Host campaign planner. |
buildToolContext |
optional | Host factory for the DSL runner’s tool context. |
The package refuses to serve /workflows/* when neither
triggerToken nor validateEditorSession is configured — at least
one credential path must be defined.
Chrome integration
Section titled “Chrome integration”The chrome detects the workflows surface through the
features.workflows binding:
<AuthoringChromeMount bindings={{ /* ... */ features: { workflows: process.env.AUTHORING_WORKFLOWS === "true", }, }}>Turn it off (or omit the binding) on hosts that don’t run the addon and the workflows UI disappears from the chrome.
OpenAPI
Section titled “OpenAPI”The package exports an AUTHORING_WORKFLOWS_OPENAPI_FRAGMENT that
spreads into your @fastify/swagger config alongside
AUTHORING_SERVER_OPENAPI_FRAGMENT. The workflows tag and the
trigger-token bearer scheme show up automatically in your API docs.
Security
Section titled “Security”The workflows endpoints can land drafts in your CMS through service-account auth — treat them with the same care as any other write surface:
- Rotate
triggerTokenvia env reload + redeploy. - Apply network-level isolation when exposing
/workflows/runsto untrusted networks. - Inngest signs all inbound requests via
inngestSigningKey.
The full security contract lives in the
security RFC
in the platform repo (available once the authoring branch lands on main).
Where to next
Section titled “Where to next”- MCP endpoint — the interactive headless surface, the natural counterpart to workflows.
- Packages — the wider package surface.

