bytedance/deer-flow · error · HTTPException

Custom-agent management API is disabled. Set agents_api.enab

Error message

Custom-agent management API is disabled. Set agents_api.enabled=true to expose agent and user-profile routes over HTTP.

What it means

403 from `_require_agents_api_enabled`, called at the top of every agent and user-profile route. The custom-agent management API is opt-in: unless `agents_api.enabled=true` is set in config, the routes exist but refuse all requests. This is a deliberate off-by-default posture for an HTTP surface that writes agent configs.

Source

Thrown at backend/app/gateway/routers/agents.py:109

    Raises:
        HTTPException: 422 if the name is invalid.
    """
    if not AGENT_NAME_PATTERN.match(name):
        raise HTTPException(
            status_code=422,
            detail=f"Invalid agent name '{name}'. Must match ^[A-Za-z0-9-]+$ (letters, digits, and hyphens only).",
        )


def _normalize_agent_name(name: str) -> str:
    """Normalize agent name to lowercase for filesystem storage."""
    return name.lower()


def _require_agents_api_enabled() -> None:
    """Reject access unless the custom-agent management API is explicitly enabled."""
    if not get_agents_api_config().enabled:
        raise HTTPException(
            status_code=403,
            detail=("Custom-agent management API is disabled. Set agents_api.enabled=true to expose agent and user-profile routes over HTTP."),
        )


def _validate_model_exists(model: str | None) -> None:
    """Reject an agent ``model`` that is not a configured profile.

    Mirrors the ``update_agent`` harness tool: without this, an unknown model
    silently falls back to the default at runtime and the user sees confusing
    repeated warnings on every later turn instead of an actionable error here.
    ``None``/empty means "use the global default" and is always allowed.

    Best-effort: if the app config cannot be loaded (e.g. no ``config.yaml`` on
    disk in a bare/test deployment), skip the check rather than failing the
    write — the runtime still falls back to the default for an unknown model.
    """
    if not model:

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Edit config.yaml and set `agents_api.enabled: true`, then restart the Gateway
  2. If you did not intend to expose this API, keep it disabled and use the in-chat `update_agent` tools instead
  3. After enabling, verify with a GET `/agents` call before wiring the frontend

Example fix

# config.yaml — before
agents_api:
  enabled: false
# after
agents_api:
  enabled: true
Defensive patterns

Strategy: validation

Validate before calling

// Probe once at client startup
const probe = await fetch(`${base}/api/agents`, { credentials: 'include' });
if (probe.status === 403 && /disabled/.test(await probe.text())) {
  agentsApiEnabled = false; // hide agent-management UI
}

Try / catch

try { return await api.listAgents(); }
catch (e) {
  if (e.status === 403 && /agents_api.enabled/.test(e.detail)) return { agents: [], disabled: true };
  throw e;
}

Prevention

When it happens

Trigger: Calling any `/agents*` or `/user-profile` endpoint on a default deployment where `agents_api.enabled` was never set; a config.yaml regenerated from the example template that leaves the flag commented out.

Common situations: Fresh installs assuming the agent CRUD API is available; upgrading to a version that gated the API behind config; test environments booting with minimal config.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/c827f67166566bf5. Report an issue: GitHub.