langchain-ai/deepagents · error · ValueError

Async subagent '{name}' has no url configured. ASGI transpor

Error message

Async subagent '{name}' has no url configured. ASGI transport (url=None) requires async invocation.

What it means

AsyncSubAgentsMiddleware's ClientManager raises this when get_sync() is asked for a sync LangGraph client for an async subagent whose spec has no 'url'. A spec without a url uses ASGI in-process transport, which only works with async clients; a sync client cannot be created. This guards call paths that synchronously poll subagent state (status checks, cancels, live fetches).

Source

Thrown at libs/deepagents/deepagents/middleware/async_subagents.py:216

class _ClientCache:
    """Lazily-created, cached Agent Protocol clients keyed by (url, headers)."""

    def __init__(self, agents: dict[str, AsyncSubAgent]) -> None:
        self._agents = agents
        self._sync: dict[tuple[str | None, frozenset[tuple[str, str]]], SyncLangGraphClient] = {}
        self._async: dict[tuple[str | None, frozenset[tuple[str, str]]], LangGraphClient] = {}

    def _cache_key(self, spec: AsyncSubAgent) -> tuple[str | None, frozenset[tuple[str, str]]]:
        """Build a cache key from the agent spec's url and resolved headers."""
        return (spec.get("url"), frozenset(_resolve_headers(spec).items()))

    def get_sync(self, name: str) -> SyncLangGraphClient:
        """Get or create a sync client for the named agent."""
        spec = self._agents[name]
        if spec.get("url") is None:
            msg = f"Async subagent '{name}' has no url configured. ASGI transport (url=None) requires async invocation."
            raise ValueError(msg)
        key = self._cache_key(spec)
        if key not in self._sync:
            self._sync[key] = get_sync_client(
                url=spec.get("url"),
                headers=_resolve_headers(spec),
            )
        return self._sync[key]

    def get_async(self, name: str) -> LangGraphClient:
        """Get or create an async client for the named agent."""
        spec = self._agents[name]
        key = self._cache_key(spec)
        if key not in self._async:
            self._async[key] = get_client(
                url=spec.get("url"),
                headers=_resolve_headers(spec),
            )
        return self._async[key]

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Configure an httpx/HTTP URL in the subagent spec so sync polling is possible
  2. Use the async variants (await check_async_task/cancel_async_task) which use the ASGI-capable async client instead of get_sync
  3. Only start async tasks for url-backed subagents if you plan to sync-poll them

Example fix

// before
async_subagents=[{"name": "researcher", "graph": "researcher"}]
// after
async_subagents=[{"name": "researcher", "url": "http://localhost:8123"}]
Defensive patterns

Strategy: validation

Validate before calling

def can_sync_poll(spec: dict) -> bool:
    return spec.get("url") is not None

Try / catch

try:
    client = clients.get_sync(name)
except ValueError as e:
    # fall back to async status path or skip polling
    logger.warning("sync poll unavailable: %s", e)

Prevention

When it happens

Trigger: Calling check_async_task, update_async_task, cancel_async_task, or _fetch_live_status (which call get_sync) for a subagent defined with no 'url' key (ASGI transport); get_sync itself is public so calling it directly with a url-less spec also triggers.

Common situations: Defining async subagents as in-process graphs (url omitted) and then having the agent synchronously poll or cancel the task; mixing sync tool paths with ASGI-transport subagents; typos like 'urls' or 'base_url' in the subagent spec.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/fea8d63c2be05eab. Report an issue: GitHub.