Skip to content

list_agents() returns non-agent directories in /list-apps endpoint #4647

@markadelnawar

Description

@markadelnawar

🔴 Required Information

Describe the Bug:
The /list-apps endpoint returns directories that are not valid agents. Any subdirectory inside the agents directory (e.g. tmp/, data/, utils/) is returned in the response, even when it contains no agent definition (root_agent.yaml, agent.py, or __init__.py). This affects both the ADK web UI (where non-agent directories appear in the agent selector) and any production deployment depending on this API to list available agents.

Steps to Reproduce:

  1. Create a project directory with a valid agent and some non-agent subdirectories:
my_project/
├── my_agent/
│   ├── __init__.py
│   └── agent.py       # valid agent
├── utils/              # not an agent
├── data/               # not an agent
└── tmp/                # not an agent
  1. Run adk web . from my_project/
  2. Open the web UI
  3. Observe that utils, data, and tmp appear in the agent selector alongside my_agent

Expected Behavior:
Only directories containing a valid agent definition should appear in the agent list.

Observed Behavior:
All non-hidden subdirectories are listed regardless of whether they contain an agent. Selecting a non-agent directory results in a loading error.

Environment Details:

  • ADK Library Version: 1.26.0
  • Desktop OS: macOS (Darwin 25.2.0)
  • Python Version: 3.12.10

Model Information:

  • Are you using LiteLLM: N/A
  • Which model is being used: N/A (issue is in agent discovery, not model interaction)

🟡 Optional Information

Regression:
No, this has been the behavior since list_agents() was introduced. PR #3430 (closing #3429) added a list_agents_detailed() endpoint that filters properly by loading each agent, but the web UI frontend never adopted it and still calls the plain /list-apps endpoint.

Logs:
N/A - no error on the backend, the non-agent directories are simply returned in the API response.

Screenshots / Video:
(non-agent directories listed) ( from the adk web)
Image

Additional Context:
The root cause is in AgentLoader.list_agents() which only filters by os.path.isdir(), hidden directory prefix, and __pycache__. It does not verify the directory contains a recognized agent structure (root_agent.yaml, agent.py, or __init__.py).

Related:

Minimal Reproduction Code:

from pathlib import Path
from google.adk.cli.utils.agent_loader import AgentLoader
import tempfile

with tempfile.TemporaryDirectory() as tmp:
 (Path(tmp) / "real_agent").mkdir()
 (Path(tmp) / "real_agent" / "__init__.py").write_text("from google.adk.agents.base_agent import BaseAgent\nclass A(BaseAgent):\n  def __init__(self): super().__init__(name='a')\nroot_agent = A()")
 (Path(tmp) / "not_an_agent").mkdir()

 loader = AgentLoader(tmp)
 print(loader.list_agents())
 # Returns: ['not_an_agent', 'real_agent']
 # Expected: ['real_agent']

How often has this issue occurred?:

  • Always (100%)

Metadata

Metadata

Labels

web[Component] This issue will be transferred to adk-web

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions