{"record":{"id":"550ef62340f15428","repo":"can1357/oh-my-pi","slug":"model-output-is-missing-required-fields-identifie","errorCode":null,"errorMessage":"Model output is missing required fields (identifier, whenToUse, systemPrompt)","messagePattern":"Model output is missing required fields \\(identifier, whenToUse, systemPrompt\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/components/agents-hub.ts","lineNumber":182,"sourceCode":"\tconst fenceMatch = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n\tif (fenceMatch?.[1]) return fenceMatch[1].trim();\n\tconst start = raw.indexOf(\"{\");\n\tconst end = raw.lastIndexOf(\"}\");\n\tif (start >= 0 && end >= start) return raw.slice(start, end + 1).trim();\n\treturn raw.trim();\n}\n\nfunction parseGeneratedAgentSpec(raw: string): GeneratedAgentSpec {\n\tconst parsed = JSON.parse(extractJsonObject(raw)) as Partial<GeneratedAgentSpec>;\n\tif (!parsed || typeof parsed !== \"object\") {\n\t\tthrow new Error(\"Model output is not a JSON object\");\n\t}\n\tif (\n\t\ttypeof parsed.identifier !== \"string\" ||\n\t\ttypeof parsed.whenToUse !== \"string\" ||\n\t\ttypeof parsed.systemPrompt !== \"string\"\n\t) {\n\t\tthrow new Error(\"Model output is missing required fields (identifier, whenToUse, systemPrompt)\");\n\t}\n\tconst identifier = parsed.identifier.trim();\n\tconst whenToUse = parsed.whenToUse.trim();\n\tconst systemPrompt = parsed.systemPrompt.trim();\n\tif (!IDENTIFIER_PATTERN.test(identifier)) {\n\t\tthrow new Error(\"Generated identifier is invalid (must be lowercase kebab-case, 2+ words)\");\n\t}\n\tif (!whenToUse.toLowerCase().startsWith(\"use this agent when\")) {\n\t\tthrow new Error(\"Generated whenToUse must start with 'Use this agent when...'\");\n\t}\n\tif (!systemPrompt) {\n\t\tthrow new Error(\"Generated systemPrompt is empty\");\n\t}\n\treturn { identifier, whenToUse, systemPrompt };\n}\n\nfunction matchAgent(agent: HubAgent, query: string): boolean {\n\tconst text = `${agent.name} ${agent.description} ${SOURCE_LABEL[agent.source]} ${agent.overrideModel ?? \"\"}`;","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/components/agents-hub.ts#L164-L200","documentation":"After confirming the model output is a JSON object, parseGeneratedAgentSpec verifies the three required string fields: identifier, whenToUse, and systemPrompt. If any is missing or not a string, this error is thrown. It enforces the schema contract for generated agent definitions before the spec is persisted.","triggerScenarios":"#runAgentCreationArchitect receives parsed JSON that is an object but lacks one/all of identifier, whenToUse, systemPrompt, or has one typed as non-string (e.g. null, number, nested object).","commonSituations":"Model returns partial JSON when it hits output limits (long systemPrompt truncated away); model uses alternate key names like 'name'/'description'; model omits fields it deemed optional.","solutions":["Retry the architect generation — partial output is often transient, especially if truncation was the cause.","Use a model with a larger output budget or ask for a more concise systemPrompt so all fields fit.","Reinforce the exact key names and types in the architect prompt (identifier/whenToUse/systemPrompt, all strings)."],"exampleFix":"// before (model output)\n{\"identifier\":\"code-reviewer\",\"description\":\"reviews code\"}\n// after\n{\"identifier\":\"code-reviewer\",\"whenToUse\":\"Use this agent when reviewing pull requests\",\"systemPrompt\":\"You are a code reviewer...\"}","handlingStrategy":"validation","validationCode":"function specFieldsPresent(o: Record<string, unknown>): boolean {\n  return typeof o.identifier === \"string\" && typeof o.whenToUse === \"string\" && typeof o.systemPrompt === \"string\";\n}\nconst parsed = JSON.parse(raw);\nif (!specFieldsPresent(parsed)) retryArchitect();","typeGuard":"function isGeneratedAgentSpec(v: unknown): v is GeneratedAgentSpec {\n  return typeof v === \"object\" && v !== null && !Array.isArray(v) &&\n    typeof (v as any).identifier === \"string\" &&\n    typeof (v as any).whenToUse === \"string\" &&\n    typeof (v as any).systemPrompt === \"string\";\n}","tryCatchPattern":"try {\n  const spec = parseGeneratedAgentSpec(raw);\n} catch (err) {\n  if (err.message.startsWith(\"Model output is missing required fields\")) {\n    return retryArchitect({ missingFieldsHint: true });\n  } throw err;\n}","preventionTips":["Include the exact key names and string types in the architect prompt.","Keep the systemPrompt request concise to avoid output truncation dropping fields.","Validate with a schema (zod/arktype) before consuming model JSON."],"tags":["llm-output","schema","validation","agents"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}