/workfront-actions
Use when writing or fixing the server-side code of a Workfront App Builder extension — the Adobe I/O Runtime action the React SPA calls to do work the browser can't. Reach for this whenever the user is: structuring or editing action code; deciding what shape an action returns so
$ npx -y skills add adobe/skills --skill workfront-actions --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/workfront-actions
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when writing or fixing the server-side code of a Workfront App Builder extension — the Adobe I/O Runtime action the React SPA calls to do work the browser can't. Reach for this whenever the user is: structuring or editing action code; deciding what shape an action returns so
SKILL.md
workfront-actions.SKILL.mdname: workfront-actions
description: "Use when writing or fixing the server-side code of a Workfront App Builder extension — the Adobe I/O Runtime action the React SPA calls to do work the browser can't. Reach for this whenever the user is: structuring or editing action code; deciding what shape an action returns so the frontend can tell success from failure (the {data,error} body); passing the IMS token through and calling an external API from the backend so credentials never reach the browser; calling Workfront's own Public API v21 (search/count, bulk PUT with the updates param, custom DE: field filters); calling Workfront Planning or another Adobe service; or troubleshooting why a deployed action can't read secrets (process.env is empty once deployed — inputs flow .env → config inputs → params). Also covers CommonJS-only structure, require-adobe-auth, and registering actions in app.config.yaml / ext.config.yaml. For generic non-Workfront action templates and SDKs see appbuilder-action-scaffolder."
license: Apache-2.0Workfront Runtime actions
Actions are the **back end** — small functions Adobe runs in its cloud on demand ("serverless"; Adobe I/O Runtime, built on OpenWhisk). The front end (SPA, see `workfront-ui-extension`) calls them via `actionWebInvoke`; they hold the credentials and call external APIs. **The browser must never call Workfront/Adobe APIs directly** — that is the action's job, so login tokens never reach the user's browser.
> For generic action *patterns and templates* (webhook receiver, database CRUD, custom event provider, journaling consumer, large-payload redirect, action sequence, Asset Compute worker) and the App Builder SDKs (State/Files/Events/DB), use **`appbuilder-action-scaffolder`**. This skill is the **Workfront-specific** layer: the `{data,error}` contract, IMS passthrough, and Workfront's own Public API.
Anatomy
actions/<name>/index.js # exports main(params)
- **CommonJS only** — export your function as `exports.main`. (App Builder supports only CommonJS, not ES Modules.)
- Register every action in `app.config.yaml`, or in an extension's `ext.config.yaml` (which compiles into `app.config.yaml`), following the OpenWhisk wskdeploy YAML spec.
async function main (params) {
// ...
return { statusCode: 200, body: { data, error: null } }
}
exports.main = mainResponse shape
Always return `{ data, error }` in the body; the UI checks `error` before using `data`.
return { statusCode: 400, body: { data: null, error: 'missing parameter(s) ...' } }Auth & inputs
- **`require-adobe-auth` is a per-action choice, *off* by default** (the platform default) — decide deliberately, don't blanket-enable it. When `true`, Adobe validates the user's IMS token at the gateway before your code runs.
- Turn it **on** when the action itself is the security boundary (privileged work, or nothing downstream authorizes the caller).
- Leave it **off** when the downstream API enforces its own authorization — e.g. the action just forwards the user's `imsToken` to Workfront/Planning, which rejects bad tokens — or unless explicitly asked to enable it.
- The UI passes `imsToken` (→ `Authorization: Bearer …`) and the Workfront instance URL as **params**; never hardcode them.
- **The IMS org id is in the shared context at `auth.imsOrgID`** (capital `ID` — not `imsOrgId`/`imsOrg`; that casing trap costs hours). The front end reads `sharedContext.get('auth').imsOrgID` and passes it down; the action uses `params.imsOrgId` / the `x-gw-ims-org-id` header. Two traps: (1) **reject the strings `"undefined"`/`"null"`/empty** — an empty front-end value becomes the header string `"undefined"` (→ `401 "Org Id undefined is not in the list of user org Ids"`); (2) with `require-adobe-auth: true` the gateway validates the org header *before* your code runs.
- **Inputs flow `.env` → action `inputs` (in config) → `params`. Do NOT read `process.env` at runtime.** Under `aio app dev` actions run in-process, so `process.env` may *appear* to work locally but will be empty once deployed. Wire keys/secrets as `inputs` and read them from `params`.
Calling external APIs (the pattern)
For any API — Workfront, Planning, Adobe services:
1. Receive `imsToken` plus any `apiKey` / IDs as `params`. 2. `fetch` the **public** REST endpoint with `Authorization: Bearer <imsToken>` (add `x-api-key` / `x-gw-ims-org-id` where required). 3. Map the result to `{ data, error }`. Never log the token.
- **Workfront Planning** → **verify the Workfront MCP is connected, then fetch the v2 endpoint reference and data from it** (details in `references/integrations.md`); if it isn't connected, stop and tell the user to connect the Workfront MCP before continuing. **Other Adobe services** → `references/integrations.md`. Confirm endpoints from the live source rather than guessing.
Workfront Public API v21.0
Workfront's own REST API — the `/attask/api/v21.0` layer. Call it from an action (never from the SPA).
- **wfClient / base URL:** `{workFrontInstanceUrl}/attask/api/v21.0{path}` — a single version constant. `workFrontInstanceUrl` and `imsToken` arrive as **params** (never hardcoded).
- **Search / count** objects (projects, tasks, issues) via the documented query params; map the response into `{ data, error }`.
- **Custom `DE:` fields** need `{field}_Mod=notblank` on search/count, or they are silently omitted from results.
- **Bulk update** with `PUT /{obj}?updates=[...]` (the `updates` array in the query string) — **chunk** requests to stay under the ~8 KB URL-length limit; fall back to per-record `PUT /{obj}/{ID}` when a chunk is still too long.
- Wrap the calls in a small `wfFetch` helper; register the action in `app.config.yaml`; the SPA reaches it via `actionWebInvoke` only.
Time budget
The action the SPA calls via `actionWebInvoke` is a **web action**, so it's bound by Adobe I/O Runtime's **60 s cap** on web/blocking actions — raising `limits.timeo
Read more
name: workfront-actions
description: "Use when writing or fixing the server-side code of a Workfront App Builder extension — the Adobe I/O Runtime action the React SPA calls to do work the browser can't. Reach for this whenever the user is: structuring or editing action code; deciding what shape an action returns so the frontend can tell success from failure (the {data,error} body); passing the IMS token through and calling an external API from the backend so credentials never reach the browser; calling Workfront's own Public API v21 (search/count, bulk PUT with the updates param, custom DE: field filters); calling Workfront Planning or another Adobe service; or troubleshooting why a deployed action can't read secrets (process.env is empty once deployed — inputs flow .env → config inputs → params). Also covers CommonJS-only structure, require-adobe-auth, and registering actions in app.config.yaml / ext.config.yaml. For generic non-Workfront action templates and SDKs see appbuilder-action-scaffolder."
license: Apache-2.0Workfront Runtime actions
Actions are the **back end** — small functions Adobe runs in its cloud on demand ("serverless"; Adobe I/O Runtime, built on OpenWhisk). The front end (SPA, see `workfront-ui-extension`) calls them via `actionWebInvoke`; they hold the credentials and call external APIs. **The browser must never call Workfront/Adobe APIs directly** — that is the action's job, so login tokens never reach the user's browser.
> For generic action *patterns and templates* (webhook receiver, database CRUD, custom event provider, journaling consumer, large-payload redirect, action sequence, Asset Compute worker) and the App Builder SDKs (State/Files/Events/DB), use **`appbuilder-action-scaffolder`**. This skill is the **Workfront-specific** layer: the `{data,error}` contract, IMS passthrough, and Workfront's own Public API.
Anatomy
actions/<name>/index.js # exports main(params)
- **CommonJS only** — export your function as `exports.main`. (App Builder supports only CommonJS, not ES Modules.)
- Register every action in `app.config.yaml`, or in an extension's `ext.config.yaml` (which compiles into `app.config.yaml`), following the OpenWhisk wskdeploy YAML spec.
async function main (params) {
// ...
return { statusCode: 200, body: { data, error: null } }
}
exports.main = mainResponse shape
Always return `{ data, error }` in the body; the UI checks `error` before using `data`.
return { statusCode: 400, body: { data: null, error: 'missing parameter(s) ...' } }Auth & inputs
- **`require-adobe-auth` is a per-action choice, *off* by default** (the platform default) — decide deliberately, don't blanket-enable it. When `true`, Adobe validates the user's IMS token at the gateway before your code runs.
- Turn it **on** when the action itself is the security boundary (privileged work, or nothing downstream authorizes the caller).
- Leave it **off** when the downstream API enforces its own authorization — e.g. the action just forwards the user's `imsToken` to Workfront/Planning, which rejects bad tokens — or unless explicitly asked to enable it.
- The UI passes `imsToken` (→ `Authorization: Bearer …`) and the Workfront instance URL as **params**; never hardcode them.
- **The IMS org id is in the shared context at `auth.imsOrgID`** (capital `ID` — not `imsOrgId`/`imsOrg`; that casing trap costs hours). The front end reads `sharedContext.get('auth').imsOrgID` and passes it down; the action uses `params.imsOrgId` / the `x-gw-ims-org-id` header. Two traps: (1) **reject the strings `"undefined"`/`"null"`/empty** — an empty front-end value becomes the header string `"undefined"` (→ `401 "Org Id undefined is not in the list of user org Ids"`); (2) with `require-adobe-auth: true` the gateway validates the org header *before* your code runs.
- **Inputs flow `.env` → action `inputs` (in config) → `params`. Do NOT read `process.env` at runtime.** Under `aio app dev` actions run in-process, so `process.env` may *appear* to work locally but will be empty once deployed. Wire keys/secrets as `inputs` and read them from `params`.
Calling external APIs (the pattern)
For any API — Workfront, Planning, Adobe services:
1. Receive `imsToken` plus any `apiKey` / IDs as `params`. 2. `fetch` the **public** REST endpoint with `Authorization: Bearer <imsToken>` (add `x-api-key` / `x-gw-ims-org-id` where required). 3. Map the result to `{ data, error }`. Never log the token.
- **Workfront Planning** → **verify the Workfront MCP is connected, then fetch the v2 endpoint reference and data from it** (details in `references/integrations.md`); if it isn't connected, stop and tell the user to connect the Workfront MCP before continuing. **Other Adobe services** → `references/integrations.md`. Confirm endpoints from the live source rather than guessing.
Workfront Public API v21.0
Workfront's own REST API — the `/attask/api/v21.0` layer. Call it from an action (never from the SPA).
- **wfClient / base URL:** `{workFrontInstanceUrl}/attask/api/v21.0{path}` — a single version constant. `workFrontInstanceUrl` and `imsToken` arrive as **params** (never hardcoded).
- **Search / count** objects (projects, tasks, issues) via the documented query params; map the response into `{ data, error }`.
- **Custom `DE:` fields** need `{field}_Mod=notblank` on search/count, or they are silently omitted from results.
- **Bulk update** with `PUT /{obj}?updates=[...]` (the `updates` array in the query string) — **chunk** requests to stay under the ~8 KB URL-length limit; fall back to per-record `PUT /{obj}/{ID}` when a chunk is still too long.
- Wrap the calls in a small `wfFetch` helper; register the action in `app.config.yaml`; the SPA reaches it via `actionWebInvoke` only.
Time budget
The action the SPA calls via `actionWebInvoke` is a **web action**, so it's bound by Adobe I/O Runtime's **60 s cap** on web/blocking actions — raising `limits.timeo
Repo: adobe/skills
Other skills on adobe-skills.
- /aa-conversion-funnel-analysis
Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have the worst leakage. Use this skill when someone describes a journey and asks about conversion rates, drop-off, fallout, or step completion. Trigger for "analyze our checkout funnel,"
Open skill - /aa-executive-briefing
Generates a concise, executive-ready performance summary covering key metrics, trends, and what's driving movement. Use this skill when someone needs to produce a briefing, executive summary, performance narrative, or stakeholder readout — for example, "write an exec summary of
Open skill - /aa-kpi-pulse
Produces a compact KPI digest showing how key metrics changed over a period and what's driving the movement. Use this skill when someone asks for a performance summary, a weekly recap, a morning briefing, a KPI update, or any variation of "how did we do this week/month." Also
Open skill - /aa-segment-performance-comparator
Compares the performance of two or more audience segments across key metrics side by side. Use this skill when someone wants to compare audiences or visitor groups — for example, "how do mobile visitors compare to desktop on conversion," "compare new vs. returning visitors,"
Open skill - /aa-top-movers-watchlist
Identifies which items (pages, campaigns, products, channels, regions) had the biggest increases or decreases for a key metric between two time periods. Use this skill when someone asks "what's up and what's down," "which campaigns moved the most," "top gainers and losers,"
Open skill - /cja-dimension-analysis
Comprehensive dimension analysis and reporting for CJA. Use this skill whenever the user wants to analyze one or more dimensions — including cardinality, distribution/skew, trends, anomalies, data quality errors, comparisons, and forecasting. Also trigger when someone asks "what
Open skill

