iflytek/astron-agent · error · BusinessException

WORKFLOW_SKILL_API_NOT_READY

WORKFLOW_SKILL_API_NOT_READY

Error message

WORKFLOW_SKILL_API_NOT_READY

What it means

exportSkill requires the target bot to have a published API. It fetches BotApiInfoDTO via publishApiService.getApiInfo(botId) and throws WORKFLOW_SKILL_API_NOT_READY when hasPublishedApi(apiInfo) is false — i.e. no published API endpoint exists for the bot, so a callable skill cannot be generated.

Solutions

  1. Publish the bot (e.g. via the market/channel publish flow) and wait until it is on-shelf with an active API, then retry exportSkill.
  2. Check the bot's publish status via the publish-status API before exporting.
  3. Confirm the botId passed is the one that was actually published, not an old or sibling bot.
  4. If publish is stuck in review, contact an admin or check the moderation record for the bot.

Example fix

// before
exportSkill({botId: draftBotId, workflowId: 456}); // bot never published
// after
await publishApi.publishBot({botId: draftBotId, channel: "market"});
await waitForPublishComplete(draftBotId);
exportSkill({botId: draftBotId, workflowId: 456});
Defensive patterns

Strategy: validation

Validate before calling

BotApiInfoDTO apiInfo = publishApiService.getApiInfo(botId);
if (apiInfo == null || apiInfo.getApiUrl() == null) {
    throw new IllegalStateException("bot " + botId + " has no published API; publish it first");
}

Type guard

boolean hasPublishedApi(BotApiInfoDTO apiInfo) {
    return apiInfo != null && StringUtils.isNotBlank(apiInfo.getApiUrl());
}

Try / catch

try {
    return exportSkill(request);
} catch (BusinessException e) {
    if ("WORKFLOW_SKILL_API_NOT_READY".equals(e.getCode())) {
        guideUserToPublishBot(request.getBotId());
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling exportSkill for a botId whose bot has never been published, whose publish is still in review/pending, or whose publish channels were all removed so getApiInfo returns null/empty API info.

Common situations: User tries to export a skill from a draft-only bot; the bot publish is pending moderation; the bot was taken offline (off-shelf) before export; botId points to a different bot than the one actually published.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/3c8ef411398d63e7. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/workflow/impl/WorkflowSkillExportServiceImpl.java:72

            throw new BusinessException(ResponseEnum.PARAMETER_ERROR);
        }

        Workflow workflow = workflowService.getById(request.getWorkflowId());
        if (workflow == null) {
            throw new BusinessException(ResponseEnum.BOT_NOT_EXIST);
        }
        dataPermissionCheckTool.checkWorkflowBelong(workflow, SpaceInfoUtil.getSpaceId());

        String workflowName = StringUtils.defaultIfBlank(request.getWorkflowName(), workflow.getName());
        String workflowDescription =
                StringUtils.defaultIfBlank(request.getWorkflowDescription(), workflow.getDescription());
        if (StringUtils.isBlank(workflowName) || StringUtils.isBlank(workflowDescription)) {
            throw new BusinessException(ResponseEnum.WORKFLOW_SKILL_NAME_DESC_EMPTY);
        }

        BotApiInfoDTO apiInfo = publishApiService.getApiInfo(request.getBotId());
        if (!hasPublishedApi(apiInfo)) {
            throw new BusinessException(ResponseEnum.WORKFLOW_SKILL_API_NOT_READY);
        }

        List<BizInputOutput> inputs = extractWorkflowInputs(workflow);
        SkillMetadata metadata = generateSkillMetadata(workflowName, workflowDescription, workflow.getId());
        String content = buildSkillContent(metadata, workflowName, workflowDescription, apiInfo, inputs);
        return new WorkflowSkillExportResponse(SKILL_FILE_NAME, content, metadata.aiGenerated());
    }

    private boolean hasPublishedApi(BotApiInfoDTO apiInfo) {
        return apiInfo != null
                && StringUtils.isNotBlank(apiInfo.getAppId())
                && StringUtils.isNotBlank(apiInfo.getAppKey())
                && StringUtils.isNotBlank(apiInfo.getAppSecret())
                && StringUtils.isNotBlank(apiInfo.getServiceUrl())
                && StringUtils.isNotBlank(apiInfo.getFlowId());
    }

    private List<BizInputOutput> extractWorkflowInputs(Workflow workflow) {

View on GitHub (pinned to 5e758547a8)