iflytek/astron-agent · critical · PluginExc

40028

40028

Error message

Failed to call workflow tool

What it means

The agent's workflow plugin fails closed when the internal API key used to authenticate agent->workflow calls cannot be loaded. `credential_from_env_or_file` looks up WORKFLOW_INTERNAL_API_KEY (or a key file), requiring min length 32 and rejecting placeholder values; if nothing valid is found, `RunWorkflowExc` (code 40028, 'Failed to call workflow tool') is raised before any request is made.

Solutions

  1. Set WORKFLOW_INTERNAL_API_KEY to a valid key of at least 32 characters in the agent service environment.
  2. Alternatively set WORKFLOW_INTERNAL_API_KEY_FILE to a readable file containing the key.
  3. Verify the value is not the placeholder distributed with the deployment templates.
  4. Restart the service after changing env/secrets so the per-request load picks up the new value.

Example fix

// before (docker-compose.yml)
agent:
  environment:
    - WORKFLOW_SSE_BASE_URL=http://workflow:8090
// after
agent:
  environment:
    - WORKFLOW_SSE_BASE_URL=http://workflow:8090
    - WORKFLOW_INTERNAL_API_KEY=${WORKFLOW_INTERNAL_API_KEY} # >= 32 chars, from .env/secret
Defensive patterns

Strategy: validation

Validate before calling

import os
key = os.getenv("WORKFLOW_INTERNAL_API_KEY") or (open(os.environ["WORKFLOW_INTERNAL_API_KEY_FILE"]).read().strip() if os.getenv("WORKFLOW_INTERNAL_API_KEY_FILE") else None)
if not key or len(key) < 32 or key.startswith("placeholder"):
    raise SystemExit("WORKFLOW_INTERNAL_API_KEY must be set to a value >= 32 chars at startup")

Type guard

def has_workflow_api_key() -> bool:
    import os
    key = os.getenv("WORKFLOW_INTERNAL_API_KEY")
    return bool(key) and len(key) >= 32

Try / catch

try:
    plugins = await factory.gen(span)
except RunWorkflowExc:
    logger.error("workflow internal API key missing/invalid; check WORKFLOW_INTERNAL_API_KEY(_FILE)")
    raise

Prevention

When it happens

Trigger: Calling `WorkflowPluginRunner.run`/`_build_request_params` or `WorkflowPluginFactory.do_query_workflow_schema` when WORKFLOW_INTERNAL_API_KEY is unset, set below 32 chars, set to the deployment placeholder value, or WORKFLOW_INTERNAL_API_KEY_FILE points to a missing/unreadable file.

Common situations: Local dev environments missing the env var; docker-compose/k8s secrets not mounted; a placeholder like 'changeme-...' left in config; a short test key pasted in; secret file path typo or wrong file permissions.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at core/agent/service/plugin/workflow.py:47

    """Remove internal authentication and signed trace headers from telemetry."""
    trace_safe_headers = redact_trusted_trace_headers(headers)
    return {
        key: value
        for key, value in trace_safe_headers.items()
        if key.lower() != WORKFLOW_INTERNAL_API_KEY_HEADER.lower()
    }


def _configured_workflow_internal_api_key() -> str:
    """Load the deployment key once per request and fail closed if unavailable."""
    internal_api_key = credential_from_env_or_file(
        "WORKFLOW_INTERNAL_API_KEY",
        "WORKFLOW_INTERNAL_API_KEY_FILE",
        min_length=32,
        placeholders=(WORKFLOW_INTERNAL_API_KEY_PLACEHOLDER,),
    )
    if not internal_api_key:
        raise RunWorkflowExc
    return internal_api_key


class _AgentConfig(BaseModel):
    """Workflow-related configuration loaded from environment.

    Tests may monkeypatch this object on the module (see test_plugin_base_link_mcp_workflow),
    so keep the name `agent_config` stable.
    """

    WORKFLOW_SSE_BASE_URL: str = Field(
        default_factory=lambda: os.getenv("WORKFLOW_SSE_BASE_URL", "")
    )
    GET_WORKFLOWS_URL: str = Field(
        default_factory=lambda: os.getenv("GET_WORKFLOWS_URL", "")
    )

View on GitHub (pinned to 5e758547a8)