Skip to content

fix(config,server): reject zero-agent configs & guard GET /api/agents (#3588)#3589

Draft
aheritier wants to merge 3 commits into
mainfrom
fix/3588-reject-zero-agent-config
Draft

fix(config,server): reject zero-agent configs & guard GET /api/agents (#3588)#3589
aheritier wants to merge 3 commits into
mainfrom
fix/3588-reject-zero-agent-config

Conversation

@aheritier

Copy link
Copy Markdown
Contributor

Summary

Fixes #3588 — a config with no agents caused two problems:

  1. GET /api/agents panicked on every request. The handler evaluated
    c.Agents.First().Description before the len==0 guard that was meant to
    protect it, and latest.Agents.First() panics on an empty slice. With no
    echo Recover middleware, each request died with an empty reply and
    stack-trace log spam.
  2. validateConfig never required at least one agent, so agent-less configs
    loaded successfully in the first place.

This is finding B1 from the internal codebase audit.

What changed

  • Handler guard (defense in depth): getAgents now checks
    len(cfg.Agents) == 0 before any First() access; the per-source
    summarization is extracted into a small, directly testable
    agentsAPIEntry helper. The endpoint can no longer panic.
  • Load-time validation: validateConfig now rejects a config with no
    agents first, before providers/models/toolsets, with a clear, actionable
    error: "at least one agent must be configured (add an entry under
    'agents')"
    . Validation runs after migration to latest, so the rule
    applies to every supported config version (v0–v12).
  • Schema enforcement: agent-schema.json now marks agents as
    required at the root and keeps minProperties: 1, so both an omitted
    agents key and an explicit agents: {} are schema-invalid.
  • Docs: confirmed the agents/overview docs already state that at least one
    agent is required; the schema and runtime now match.

Notes

  • latest.Agents.First() keeps its panic (frozen vN packages untouched, per
    config-versioning discipline). Its production callers are all guarded, and
    configs can no longer load without agents, so the optional
    (AgentConfig, bool) signature change was skipped as pure churn.

Testing

  • pkg/server/agents_test.goagentsAPIEntry with an empty config is
    NotPanics.
  • pkg/server/server_test.go + testdata/no_agents.yaml — end-to-end handler
    test: an agent-less source returns a clean 200 listing only the valid
    agent, not a panic.
  • pkg/config/validation_test.go — agent-less config is rejected with the
    expected message.
  • pkg/config/schema_test.goTestJsonSchemaRejectsZeroAgents pins both
    the required and minProperties constraints (each fails if its constraint
    is removed).
  • All regression tests verified to fail against the pre-fix code.
  • task dev (lint + 19 custom cops + tests + build) green;
    TestJsonSchemaWorksForExamples / TestSchemaMatchesGoTypes still pass.

Behavior change

Configs with no agents previously loaded (and then broke GET /api/agents);
they are now rejected at load time. Worth a release note.

Opened as a draft pending final maintainer review.

agent-schema.json added agents.minProperties:1 (rejecting an explicit
agents: {}) but never required the agents property itself, so a config
that omits agents entirely (e.g. just version: "12") was still schema
valid — contradicting validateConfig's "at least one agent must be
configured" rule and the docs.

Add root-level required: [agents] alongside the existing
minProperties: 1, so both the omitted-agents and empty-map shapes are
schema-invalid.

Pin the invariant with direct schema-negative tests
(TestJsonSchemaRejectsZeroAgents) asserting the schema rejects both
shapes; previously neither was covered, so removing either constraint
silently passed. Also tighten doc_yaml_test.go's looksLikeFullConfig
heuristic to require an "agents" key before schema-validating a doc
snippet as a full config, since many docs show partial models/
permissions/providers fragments without agents that are no longer
schema-valid as standalone full configs.

Refs #3588
@aheritier aheritier added area/api For features/issues/fixes related to the usage of the cagent API area/config For configuration parsing, YAML, environment variables area/docs Documentation changes kind/fix PR fixes a bug (maps to fix:). Use on PRs only. labels Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api For features/issues/fixes related to the usage of the cagent API area/config For configuration parsing, YAML, environment variables area/docs Documentation changes kind/fix PR fixes a bug (maps to fix:). Use on PRs only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GET /api/agents panics on a zero-agent config; validateConfig doesn't require ≥1 agent

1 participant