Skip to content

fix: generatedAgentConfigs unconditionally set — default agents polluted as "generated" #353

@YizukiAme

Description

@YizukiAme

Problem

In lib/server/classroom-generation.ts, generatedAgentConfigs is set on the Stage object unconditionally — regardless of whether agentMode is 'default' or 'generate':

// L216-227: agents resolved based on agentMode
if (agentMode === 'generate') {
  agents = await generateAgentProfiles(requirement, lang, aiCall);
} else {
  agents = getDefaultAgents();  // returns default-1 ~ default-6
}

// L306: unconditional — always set, even for default agents
generatedAgentConfigs: agents.map((a, i) => ({ ... }))

When agentMode === 'default', generatedAgentConfigs contains the 6 default agents (default-1 ~ default-6).

On the client side, saveGeneratedAgents() saves them to IndexedDB with isGenerated: true, overwriting the original isDefault: true entries in the Agent Registry.

Consequence

If a user navigates from a server-generated (default-mode) classroom to another classroom in the same SPA session:

  1. loadGeneratedAgentsForStage(newClassroomId) clears all isGenerated agents from the Registry
  2. The default agents (default-1 ~ default-6) were overwritten as isGenerated in step 1 of the previous load — so they get deleted
  3. The original isDefault entries are gone (only restored on full page refresh via zustand persist merge)

Practical impact is low (page refresh fixes it), but it's a latent correctness issue.

Related: Stage missing agentIds for default mode

When using default agents, the Stage object also doesn't set the agentIds field. The client-side fallback in page.tsx (L96) defaults to ['default-1', 'default-2', 'default-3'] — only 3 of the 6 defaults. This is currently masked by the unconditional generatedAgentConfigs, but would become visible if the above is fixed.

Suggested Fix

const stage: Stage = {
  // ...
  // Only embed agent configs for LLM-generated agents
  ...(agentMode === 'generate' ? {
    generatedAgentConfigs: agents.map((a, i) => ({
      id: a.id, name: a.name, role: a.role,
      persona: a.persona || '',
      avatar: AGENT_DEFAULT_AVATARS[i % AGENT_DEFAULT_AVATARS.length],
      color: AGENT_COLOR_PALETTE[i % AGENT_COLOR_PALETTE.length],
      priority: a.role === 'teacher' ? 10 : a.role === 'assistant' ? 7 : 5,
    }))
  } : {
    agentIds: agents.map(a => a.id)  // default mode: just record IDs
  }),
};

Context

Discovered during review of #336. The unconditional setting was introduced in that PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions