{"record":{"id":"0df41e40ce363806","repo":"iflytek/astron-agent","slug":"40028-failed-to-call-workflow-tool","errorCode":"40028","errorMessage":"Failed to call workflow tool","messagePattern":"Failed to call workflow tool","errorType":"error_code","errorClass":"PluginExc","httpStatus":null,"severity":"critical","filePath":"core/agent/service/plugin/workflow.py","lineNumber":47,"sourceCode":"    \"\"\"Remove internal authentication and signed trace headers from telemetry.\"\"\"\n    trace_safe_headers = redact_trusted_trace_headers(headers)\n    return {\n        key: value\n        for key, value in trace_safe_headers.items()\n        if key.lower() != WORKFLOW_INTERNAL_API_KEY_HEADER.lower()\n    }\n\n\ndef _configured_workflow_internal_api_key() -> str:\n    \"\"\"Load the deployment key once per request and fail closed if unavailable.\"\"\"\n    internal_api_key = credential_from_env_or_file(\n        \"WORKFLOW_INTERNAL_API_KEY\",\n        \"WORKFLOW_INTERNAL_API_KEY_FILE\",\n        min_length=32,\n        placeholders=(WORKFLOW_INTERNAL_API_KEY_PLACEHOLDER,),\n    )\n    if not internal_api_key:\n        raise RunWorkflowExc\n    return internal_api_key\n\n\nclass _AgentConfig(BaseModel):\n    \"\"\"Workflow-related configuration loaded from environment.\n\n    Tests may monkeypatch this object on the module (see test_plugin_base_link_mcp_workflow),\n    so keep the name `agent_config` stable.\n    \"\"\"\n\n    WORKFLOW_SSE_BASE_URL: str = Field(\n        default_factory=lambda: os.getenv(\"WORKFLOW_SSE_BASE_URL\", \"\")\n    )\n    GET_WORKFLOWS_URL: str = Field(\n        default_factory=lambda: os.getenv(\"GET_WORKFLOWS_URL\", \"\")\n    )\n\n","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/agent/service/plugin/workflow.py#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set WORKFLOW_INTERNAL_API_KEY to a valid key of at least 32 characters in the agent service environment.","Alternatively set WORKFLOW_INTERNAL_API_KEY_FILE to a readable file containing the key.","Verify the value is not the placeholder distributed with the deployment templates.","Restart the service after changing env/secrets so the per-request load picks up the new value."],"exampleFix":"// before (docker-compose.yml)\nagent:\n  environment:\n    - WORKFLOW_SSE_BASE_URL=http://workflow:8090\n// after\nagent:\n  environment:\n    - WORKFLOW_SSE_BASE_URL=http://workflow:8090\n    - WORKFLOW_INTERNAL_API_KEY=${WORKFLOW_INTERNAL_API_KEY} # >= 32 chars, from .env/secret","handlingStrategy":"validation","validationCode":"import os\nkey = 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)\nif not key or len(key) < 32 or key.startswith(\"placeholder\"):\n    raise SystemExit(\"WORKFLOW_INTERNAL_API_KEY must be set to a value >= 32 chars at startup\")","typeGuard":"def has_workflow_api_key() -> bool:\n    import os\n    key = os.getenv(\"WORKFLOW_INTERNAL_API_KEY\")\n    return bool(key) and len(key) >= 32","tryCatchPattern":"try:\n    plugins = await factory.gen(span)\nexcept RunWorkflowExc:\n    logger.error(\"workflow internal API key missing/invalid; check WORKFLOW_INTERNAL_API_KEY(_FILE)\")\n    raise","preventionTips":["Add a startup readiness check that fails fast when the key is missing or too short.","Keep the key in a mounted secret, never inline in compose/Helm values committed to git.","Rotate keys without leaving placeholder values in deployment templates.","Document required env vars for every service in its deployment README."],"tags":["configuration","authentication","workflow","env-var"],"backgroundTag":"missing-env-var","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}