{"record":{"id":"d44c9dd17c463e4e","repo":"Budibase/budibase","slug":"agent-id-is-required","errorCode":null,"errorMessage":"Agent _id is required","messagePattern":"Agent _id is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agents/utils.ts","lineNumber":190,"sourceCode":"\nexport async function buildPromptAndTools(\n  agent: Agent,\n  operation?: AgentOperation,\n  options: BuildPromptAndToolsOptions = {}\n): Promise<{\n  systemPrompt: string\n  tools: ToolSet\n  toolDisplayNames: Record<string, string>\n  toolSources: Record<string, string | undefined>\n}> {\n  const {\n    baseSystemPrompt,\n    includeGoal = true,\n    fallbackPromptInstructions,\n  } = options\n  const agentId = agent._id\n  if (!agentId) {\n    throw new Error(\"Agent _id is required\")\n  }\n  const hasKnowledgeBases = operation?.knowledgeBases?.some(Boolean) ?? false\n\n  const allTools = await getAvailableTools(agent.aiconfig)\n  const toolConfigs = operation?.enabledTools || []\n  const enabledToolNames = new Set(toolConfigs.map(config => config.toolName))\n  const configuredTools = allTools.filter(\n    tool => enabledToolNames.has(tool.name) && !isHelperTool(tool)\n  )\n  let enabledTools = options.toolSecurityEnabled\n    ? configuredTools\n    : addLegacyHelperTools(configuredTools, allTools)\n\n  if (options.toolSecurityEnabled && options.executionContext) {\n    const executionContext = options.executionContext\n    const visibilityByTable = new Map<string, Promise<boolean>>()\n    enabledTools = await Promise.all(\n      enabledTools.map(async tool => {","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agents/utils.ts#L172-L208","documentation":"buildPromptAndTools requires the agent document to have an _id so prompt/tool results can be keyed to a stable agent identifier. When agent._id is absent (an unsaved or partially constructed Agent object) it throws a plain Error early, before loading tools and building the prompt.","triggerScenarios":"Calling buildPromptAndTools (directly or via promptAndTools/result/legacyResult/securedResult) with an Agent instance lacking _id - e.g. an agent created in memory but not yet saved, or deserialized from a payload that stripped _id.","commonSituations":"Building agents via API POST before persisting and then immediately trying to run them; mapping over agent records and dropping _id; test fixtures without _id.","solutions":["Save the agent first so it has an _id, then pass the persisted document to buildPromptAndTools.","Validate agent._id before invoking any prompt/tool entry points.","Fix data-mapping code that reconstructs Agent objects and omits _id."],"exampleFix":"// before\nawait promptAndTools(draftAgent, operation) // throws\n// after\nconst saved = await sdk.agents.create(draftAgent)\nif (!saved._id) throw new Error(\"Agent must be saved\")\nawait promptAndTools(saved, operation)","handlingStrategy":"type-guard","validationCode":"if (!agent._id) {\n  throw new Error(\"Persist the agent before building prompt and tools\")\n}\nawait buildPromptAndTools(agent, operation, options)","typeGuard":"const isPersistedAgent = (agent: Agent): agent is Agent & { _id: string } =>\n  typeof agent._id === \"string\" && agent._id.length > 0","tryCatchPattern":"try {\n  const { prompt, tools } = await promptAndTools(agent, operation)\n} catch (err) {\n  if ((err as Error).message === \"Agent _id is required\") {\n    // save the agent then retry with the persisted document\n  }\n}","preventionTips":["Only pass agents loaded via getOrThrow/fetch (which always have _id) into run/prompt entry points.","Don't reconstruct Agent objects for prompts from request bodies; re-read from the DB.","Ensure test fixtures include realistic _id values."],"tags":["validation","agents","missing-id"],"backgroundTag":"missing-required-id","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}