Budibase/budibase · error · Error
Agent _id is required
Error message
Agent _id is required
What it means
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.
Source
Thrown at packages/server/src/sdk/workspace/ai/agents/utils.ts:190
export async function buildPromptAndTools(
agent: Agent,
operation?: AgentOperation,
options: BuildPromptAndToolsOptions = {}
): Promise<{
systemPrompt: string
tools: ToolSet
toolDisplayNames: Record<string, string>
toolSources: Record<string, string | undefined>
}> {
const {
baseSystemPrompt,
includeGoal = true,
fallbackPromptInstructions,
} = options
const agentId = agent._id
if (!agentId) {
throw new Error("Agent _id is required")
}
const hasKnowledgeBases = operation?.knowledgeBases?.some(Boolean) ?? false
const allTools = await getAvailableTools(agent.aiconfig)
const toolConfigs = operation?.enabledTools || []
const enabledToolNames = new Set(toolConfigs.map(config => config.toolName))
const configuredTools = allTools.filter(
tool => enabledToolNames.has(tool.name) && !isHelperTool(tool)
)
let enabledTools = options.toolSecurityEnabled
? configuredTools
: addLegacyHelperTools(configuredTools, allTools)
if (options.toolSecurityEnabled && options.executionContext) {
const executionContext = options.executionContext
const visibilityByTable = new Map<string, Promise<boolean>>()
enabledTools = await Promise.all(
enabledTools.map(async tool => {View on GitHub (pinned to a81a902e9a)
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.
Example fix
// before
await promptAndTools(draftAgent, operation) // throws
// after
const saved = await sdk.agents.create(draftAgent)
if (!saved._id) throw new Error("Agent must be saved")
await promptAndTools(saved, operation) Defensive patterns
Strategy: type-guard
Validate before calling
if (!agent._id) {
throw new Error("Persist the agent before building prompt and tools")
}
await buildPromptAndTools(agent, operation, options) Type guard
const isPersistedAgent = (agent: Agent): agent is Agent & { _id: string } =>
typeof agent._id === "string" && agent._id.length > 0 Try / catch
try {
const { prompt, tools } = await promptAndTools(agent, operation)
} catch (err) {
if ((err as Error).message === "Agent _id is required") {
// save the agent then retry with the persisted document
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Query ID or Revision is missing
- Cannot generate query tool bindings without a query ID
- Knowledge base id not set
- Error getting status
- Unable to retrieve prod DB - no workspace ID.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/d44c9dd17c463e4e.
Report an issue: GitHub.