{"record":{"id":"19f9af34e6f107cd","repo":"Yeachan-Heo/oh-my-codex","slug":"trimmed-is-reserved-by-codex-built-in-agent","errorCode":null,"errorMessage":"\\\"${trimmed}\\\" is reserved by Codex built-in agents","messagePattern":"\\\\\"(.+?)\\\\\" is reserved by Codex built-in agents","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/agents.ts","lineNumber":51,"sourceCode":"  name: string;\n  description: string;\n  model?: string;\n}\n\nfunction isReservedNativeAgentName(name: string): boolean {\n  return RESERVED_NATIVE_AGENT_NAMES.has(name.trim());\n}\n\nfunction normalizeAgentName(name: string): string {\n  const trimmed = name.trim();\n  if (!trimmed) {\n    throw new Error('agent name must not be empty');\n  }\n  if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(trimmed)) {\n    throw new Error(`invalid agent name: ${name}`);\n  }\n  if (isReservedNativeAgentName(trimmed)) {\n    throw new Error(`\"${trimmed}\" is reserved by Codex built-in agents`);\n  }\n  return trimmed;\n}\n\nfunction resolveAgentsDir(scope: AgentScope, cwd = process.cwd()): string {\n  return scope === 'project' ? projectCodexAgentsDir(cwd) : codexAgentsDir();\n}\n\nfunction parseScopeArg(args: string[]): AgentScope | undefined {\n  for (let i = 0; i < args.length; i += 1) {\n    const arg = args[i];\n    if (arg === '--scope') {\n      const value = args[i + 1];\n      if (value === 'user' || value === 'project') return value;\n      throw new Error('Expected --scope user|project');\n    }\n    if (arg === '--scope=user') return 'user';\n    if (arg === '--scope=project') return 'project';","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/agents.ts#L33-L69","documentation":"The name, while syntactically valid, collides with a reserved Codex built-in agent name (RESERVED_NATIVE_AGENT_NAMES). Creating a user agent with one of these names would shadow or conflict with the built-in, so it is refused.","triggerScenarios":"addNativeAgent('review'), addNativeAgent('plan') or any other name in the reserved set (typically short built-in verbs like review/plan).","commonSituations":"Users trying to override or customize a built-in agent by creating a same-named native agent.","solutions":["Pick a different, more specific name (e.g. review-strict instead of review)","Check the reserved names list in src/cli/agents.ts (RESERVED_NATIVE_AGENT_NAMES)","Customize built-in behavior via supported configuration instead of shadowing the name"],"exampleFix":"# before\nomx agent add review\n\n# after\nomx agent add review-strict","handlingStrategy":"validation","validationCode":"// Mirror RESERVED_NATIVE_AGENT_NAMES before calling add\nimport { isReservedNativeAgentName } from './agents';\nif (isReservedNativeAgentName(candidate)) {\n  candidate = `${candidate}-custom`; // de-conflict\n}","typeGuard":"const isReservable = (n: string): boolean => !RESERVED_NATIVE_AGENT_NAMES.has(n.trim());","tryCatchPattern":"try { await addNativeAgent(name); } catch (e) { if (/reserved by Codex built-in/.test(String(e))) name = `${name}-x`; else throw e; }","preventionTips":["Prefix custom agents with a project or team qualifier","Never try to shadow built-in agent names"],"tags":["cli","agents","reserved-name","validation"],"backgroundTag":"reserved-name-conflict","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}