Summary
GET /api/agents evaluates c.Agents.First().Description BEFORE the switch whose default: branch is meant to handle len(c.Agents)==0 — so the guard is dead code. latest.Agents.First() panics ("no agents configured"), so any registered agent-less config source makes every request to this endpoint fail with an empty reply + stack-trace log spam. Separately, validateConfig never requires at least one agent, so agent-less configs load successfully in the first place.
Evidence
pkg/server/server.go:166 — c.Agents.First().Description is evaluated before the len-switch whose default: branch (~:181) was intended to guard it.
pkg/config/latest/types.go:236 — Agents.First() panics with "no agents configured" on an empty slice.
pkg/config/config.go:230 — validateConfig validates providers/models/toolsets/mcp/rag/commands but never checks len(Agents) >= 1.
- Verified empirically: a version+models-only YAML loads with 0 agents. pkg/server registers no echo Recover middleware, so the handler dies per-request.
- Other
First() call sites are already guarded (cmd/root/agent_picker.go checks len; pkg/team/team.go errors out).
Decision (from audit triage)
Zero-agent configs are NOT legitimate. Fix should therefore do BOTH:
- Hoist the len-check above the
First() call in getAgents so the handler never panics (defense in depth).
- Enforce a ≥1-agent rule in
validateConfig so agent-less configs are rejected at load time with a clear error.
- Optionally change
latest.Agents.First() to return (AgentConfig, bool) — allowed in latest only; frozen vN packages keep the panic and must not be modified.
Acceptance criteria
GET /api/agents never panics, even if somehow given an agent-less config.
- Loading an agent-less config fails validation with a clear, actionable error message.
- Regression tests: (a) handler test with an agent-less source expects a clean response, not a panic; (b) config validation test asserting zero-agent configs are rejected.
- This is a behavior change (previously agent-less configs loaded) — note it in release notes.
Summary
GET /api/agentsevaluatesc.Agents.First().DescriptionBEFORE theswitchwhosedefault:branch is meant to handlelen(c.Agents)==0— so the guard is dead code.latest.Agents.First()panics ("no agents configured"), so any registered agent-less config source makes every request to this endpoint fail with an empty reply + stack-trace log spam. Separately,validateConfignever requires at least one agent, so agent-less configs load successfully in the first place.Evidence
pkg/server/server.go:166—c.Agents.First().Descriptionis evaluated before thelen-switch whosedefault:branch (~:181) was intended to guard it.pkg/config/latest/types.go:236—Agents.First()panics with "no agents configured" on an empty slice.pkg/config/config.go:230—validateConfigvalidates providers/models/toolsets/mcp/rag/commands but never checkslen(Agents) >= 1.First()call sites are already guarded (cmd/root/agent_picker.go checks len; pkg/team/team.go errors out).Decision (from audit triage)
Zero-agent configs are NOT legitimate. Fix should therefore do BOTH:
First()call ingetAgentsso the handler never panics (defense in depth).validateConfigso agent-less configs are rejected at load time with a clear error.latest.Agents.First()to return(AgentConfig, bool)— allowed inlatestonly; frozen vN packages keep the panic and must not be modified.Acceptance criteria
GET /api/agentsnever panics, even if somehow given an agent-less config.