Edit, validate, debug, publish, and inspect ReachAI Workflow drafts through the Workflow AI Coding REST API. Use when asked to create or modify a workflow graph, add/update/delete nodes or edges, validate GraphSpec, dry-run or debug-run a workflow, inspect trace/run output, check release readiness, publish a validated draft, or work on PAGE_ASSISTANT workflows from Cursor/Codex.
npx skills add https://github.com/w8123/EnterpriseAgentFramework --skill workflow-ai-coding
Treat the ReachAI platform repository and live API responses as the source of truth. Do not edit runtime_workflow or runtime_workflow_resource_binding rows directly. All graph and binding changes go through Workflow AI Coding REST endpoints under /api/workflows/.../ai-coding.
凡是写入 ReachAI 或展示给业务用户的名称、标题、描述、说明、System Prompt、节点名称、审计原因、进度和结果,默认使用清晰的简体中文。不要仅因 API、Schema 或字段名为英文就生成英文业务文案。Token、MCP、AI、Agent、Supervisor、Workflow、Tool、API、SDK 等熟知专业术语,以及 keySlug、toolName、代码、路径、枚举值、协议字段和技术标识可保留英文;必要时使用“中文名称(英文术语)”。不要翻译或改写技术标识。
Core mental model:
GraphSpec is runtime semantics; canvas_json is layout only.layout.autoLayout=true. The layered policy uses LR flow, 88px inter-layer boundary gaps, 56px same-layer gaps, and cycle-safe component packing. Before reporting back, confirm canvas_json.nodes[].position is non-overlapping and aligned; do not patch GraphSpec only and skip canvas synchronization.START and END are Studio-only virtual canvas nodes. They never appear in GraphSpec nodes or edges.graphSpec.entryNodeId to a real node id and list every terminal node in graphSpec.exitNodeIds.POST /api/workflows/{workflowId}/ai-coding/publish; publish still runs release validation and creates an ACTIVE runtime_workflow_version.GET .../context before patching or publishing. Use the latest workflow.updatedAt as baseRevision when saving and publishing.DRAFT, through PUT .../resource-bindings with the latest baseRevision. They are immutable after the first publish.nodeTypes[].enabledVariants; for INTERACTION, only PRESENT_OUTPUT is currently open. Do not infer that COLLECT_INPUT, USER_CHOICE, CONFIRM_ACTION or other pause/resume variants are available merely because the INTERACTION type appears in the catalog.dryRun=true. Only set dryRun=false after validation passes.Authentication: Workflow AI Coding endpoints use aiCodingKey only (no platform Bearer). Obtain the project-level key from ReachAI 项目详情 → AI Coding 接入秘钥. Send it on every request as header X-ReachAI-AiCoding-Key; do not put the key in generated URLs, scripts, logs, or browser runtime code. Missing key returns 401; invalid or disabled key returns 403. API base URL depends on deployment; use the base URL in the current project or task handoff context.
Do not use platform login cookies or Bearer tokens for /api/workflows//ai-coding/.
When calling Workflow AI Coding APIs from Windows, prevent Chinese text from being stored as ????:
pwsh). [Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
.json files saved as UTF-8.curl.exe, not the PowerShell curl alias: curl.exe -X POST $url -H "X-ReachAI-AiCoding-Key: $AI_CODING_KEY" -H "Content-Type: application/json; charset=utf-8" --data-binary "@request.json"
Invoke-RestMethod, send UTF-8 bytes rather than a plain string body: $json = Get-Content .\request.json -Raw -Encoding utf8
$bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($json)
Invoke-RestMethod -Method Post -Uri $url -ContentType "application/json; charset=utf-8" -Body $bodyBytes
POST /api/workflows/ai-coding/workflowsGET /api/workflows/{workflowId}/ai-coding/contextPUT .../resource-bindingsPOST /api/workflows/{workflowId}/ai-coding/patch with dryRun=truePOST /api/workflows/{workflowId}/ai-coding/validate with mode=PROPOSEDPOST /api/workflows/{workflowId}/ai-coding/patch with dryRun=false and matching baseRevisionPOST .../run with dryRun=true firstPOST .../run with real input when safeGET .../runs?limit=&days=GET .../runs/{traceId}GET .../versions10. Re-read context, then publish when release validation is valid: POST .../publish with the latest workflow.updatedAt as baseRevision
11. Report: changed nodes/edges, validation result, traceId, release readiness, published version, and any remaining issues
For any branch that returns structured business data, do not stop at an ANSWER that serializes the object as Markdown. Add a downstream display-only INTERACTION/PRESENT_OUTPUT node. Use list_card for list/page results, output_card/card/detail for one object, an explicit dataExpression such as nodeOutput.read_table, and presentation.mode=card_only or text_and_card. Browser acceptance must observe both the real ui.requested SSE event and the rendered card DOM.
POST /api/workflows/ai-coding/workflows
Required body fields:
namekeySlug (slug format enforced by platform)projectIdprojectCode (must match the registered project for projectId; comparison is case-insensitive)Optional:
description, workflowKind (default GENERAL), executionEngine (default GRAPH_SPEC)defaultModelInstanceIdgraphSpec, canvas, extraresourceBindings; required for PAGE_ASSISTANTreason (audit note)Returns full WorkflowAiCodingContextResponse.
Example:
{
"name": "订单页面助手",
"keySlug": "orders-page-assistant",
"projectId": 7,
"projectCode": "orders",
"workflowKind": "PAGE_ASSISTANT",
"resourceBindings": [
{
"resourceType": "PAGE",
"resourceKey": "orders.list",
"bindingRole": "TARGET"
}
],
"reason": "为 AI Coding 创建初始草稿"
}
PAGE_ASSISTANT requires exactly one TARGET PAGE binding. Add other in-scope pages as RELATED bindings. Do not encode page ownership in extra or invent page keys.
PUT /api/workflows/{workflowId}/ai-coding/resource-bindings
Use this only to repair or complete the resource scope of a DRAFT before its first publish. Send the latest context workflow.updatedAt as required baseRevision, plus the complete replacement resourceBindings list. PAGE_ASSISTANT still requires exactly one TARGET PAGE. The operation advances workflow.updatedAt; re-read context before any following save. Once status is ACTIVE, bindings are immutable and the platform rejects the request.
GET /api/workflows/{workflowId}/ai-coding/context
Returns workflow metadata, graphSpec, canvas, release validation, node type catalog, runtime hints, page-assistant context with first-class resourceBindings, availableModels, availableTools, warnings.
Use workflow.updatedAt as patch and publish baseRevision.
When building LLM nodes, pick modelInstanceId from availableModels[].id only. When building TOOL nodes, pick tools from availableTools[] (toolId / keySlug / displayName). Never invent internal ids. If either array is empty and warnings contains MODEL_CATALOG_UNAVAILABLE, CAPABILITY_CATALOG_UNAVAILABLE, NO_ACTIVE_LLM, or NO_PROJECT_TOOLS, fix the dependency/warning first; empty+warning means “unavailable or missing”, not “safe to guess”.
Generic Workflow create defaults to workflowKind=GENERAL. A business-page Workflow must send "workflowKind":"PAGE_ASSISTANT" and its resourceBindings explicitly. Attach GENERAL or PAGE_ASSISTANT with:
Risk and routing are evaluated at the attached Workflow-tool boundary, not per
intent branch inside one graph. If the business experience must support both
page operations and an explicit page-independent API query (for example,
"use the business API and do not operate the page"), create two published
Workflows:
PAGE_ASSISTANT, attached asPAGE_ACTION;
GENERAL Workflow andattach it with riskLevel=READ.
Do not hide a read-only API route inside a PAGE_ASSISTANT and then claim that
the Agent can select it independently. The Supervisor guard sees the attached
Workflow's declared risk, so a mixed graph cannot provide branch-sensitive
routing evidence.
POST /api/ai-coding/projects/{projectId}/agent-supervisor/workflow-tools/attach
Body uses workflowId plus optional agentKeySlug (preferred) or internal agentId (mutually exclusive). Prefer omitting agent identifiers so the project default page-copilot keySlug is used. Attachment is additive by default. Set replaceWorkflowId only after reading the current attached catalog and selecting the exact predecessor to supersede; ReachAI requires the same project and workflowKind, and for PAGE_ASSISTANT also the same exact TARGET PAGE. It replaces that one entry and preserves every other Workflow. Never infer replacement from pageKey or name. Invalid targets return ai-coding-error.v1 with WORKFLOW_REPLACEMENT_INVALID and do not publish a new config. The Page Assistant-specific endpoint /api/workflows/{id}/page-assistant/attach-tool accepts PAGE_ASSISTANT only and returns WORKFLOW_KIND_NOT_SUPPORTED for GENERAL.
POST /api/workflows/{workflowId}/ai-coding/validate
Modes:
CURRENT (default): validate stored draftPROPOSED: validate supplied graphSpec; required when sending graphSpecDo not send graphSpec with mode=CURRENT.
POST /api/workflows/{workflowId}/ai-coding/patch
Important fields:
operations: list of patch opsdryRun: default true; set false only to persistbaseRevision: use latest workflow.updatedAt when savinglayout.autoLayout: default true; false preserves existing positions while still synchronizing canvas nodes/edges and placing new nodeslayout.direction: LRlayout.columnGap: default 88 (card-boundary gap)layout.rowGap: default 56 (same-layer card-boundary gap)reason: audit note on saveSupported ops:
ADD_NODEUPDATE_NODEDELETE_NODEADD_EDGEUPDATE_EDGEDELETE_EDGESET_ENTRY_NODESET_EXIT_NODESExample preview:
{
"dryRun": true,
"operations": [
{
"op": "ADD_NODE",
"node": {
"id": "answer",
"type": "ANSWER",
"name": "生成回答"
}
},
{
"op": "SET_ENTRY_NODE",
"entryNodeId": "answer"
},
{
"op": "SET_EXIT_NODES",
"exitNodeIds": ["answer"]
}
]
}
Save draft:
{
"dryRun": false,
"baseRevision": "2026-06-16T10:00:00",
"reason": "添加回答节点",
"operations": [ ... ]
}
On save failure:
baseRevision mismatch → re-read context, retry with fresh updatedAtPOST /api/workflows/{workflowId}/ai-coding/run
Fields:
messageinputruntimeContextdryRunSafety gates:
HTTP_REQUEST, TOOL, MCP_CALL, KNOWLEDGE_WRITE) require runtimeContext.confirmSideEffects=truePAGE_ACTION nodes require page bridge context (embedSessionId, pageBridge, pageContext, or bridgeGlobal)Example safe dry run:
{
"dryRun": true,
"message": "hello"
}
Example execute with side effects:
{
"message": "hello",
"runtimeContext": {
"confirmSideEffects": true
}
}
GET /api/workflows/{workflowId}/ai-coding/versions
Returns:
draftDirty flagWhen releaseValidation.valid=true, re-read context and call POST /api/workflows/{workflowId}/ai-coding/publish with a semantic version such as v1.0.0 plus the latest workflow.updatedAt as baseRevision. A 409 means the working copy changed and no version was created; re-read context, validate again, and retry. If that version already exists, read /versions and choose the next version. Use only this canonical publish endpoint.
GET /api/workflows/{workflowId}/ai-coding/runs?limit=20&days=7
GET /api/workflows/{workflowId}/ai-coding/runs/{traceId}
Use these after debug runs to inspect node outputs, spans, tool calls, guard decisions, workflow path, and repair hints.
If a freshly returned traceId is not visible, first rely on /run.nodeOutputs for immediate debugging and report the trace lookup gap with the exact traceId.
When workflowKind=PAGE_ASSISTANT, also use:
GET .../page-assistant/catalogPOST .../page-assistant/validatePOST .../page-assistant/smoke-testRead references/page-assistant.md before editing PAGE_ACTION nodes.
references/graphspec.mdreferences/workflow-apis.mdreferences/page-assistant.mdreferences/safety.mdEnd with:
valid, key errors/warnings)/versionsversion, versionId, status) or the validation/version-conflict reason publish was not completedTake w8123/workflow-ai-coding from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.