roam_process_batch_actions
Execute multiple Roam Research block operations (create, update, move, delete) in a single batch to manage knowledge graphs efficiently.
Instructions
Executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Actions are executed in the provided order. For creating nested blocks, you can use a temporary client-side UID in a parent block and refer to it in a child block within the same batch. For actions on existing blocks, a valid block UID is required. Note: Roam-flavored markdown, including block embedding with ((UID)) syntax, is supported within the string property for create-block and update-block actions. For actions on existing blocks or within a specific page context, it is often necessary to first obtain valid page or block UIDs. Tools like roam_fetch_page_by_title or other search tools can be used to retrieve these UIDs before executing batch actions. For simpler, sequential outlines, roam_create_outline is often more suitable.
IMPORTANT: Before using this tool, ensure that you have loaded into context the 'Roam Markdown Cheatsheet' resource.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| actions | Yes | An array of action objects to execute in order. |
Implementation Reference
- src/tools/operations/batch.ts:7-37 (handler)Core handler implementation: transforms input actions into Roam SDK batch format and executes them.async processBatch(actions: any[]): Promise<any> { const batchActions: RoamBatchAction[] = actions.map(action => { const { action: actionType, ...rest } = action; const roamAction: any = { action: actionType }; if (rest.location) { roamAction.location = { 'parent-uid': rest.location['parent-uid'], order: rest.location.order, }; } const block: any = {}; if (rest.string) block.string = rest.string; if (rest.uid) block.uid = rest.uid; if (rest.open !== undefined) block.open = rest.open; if (rest.heading !== undefined && rest.heading !== null && rest.heading !== 0) { block.heading = rest.heading; } if (rest['text-align']) block['text-align'] = rest['text-align']; if (rest['children-view-type']) block['children-view-type'] = rest['children-view-type']; if (Object.keys(block).length > 0) { roamAction.block = block; } return roamAction; }); return await roamBatchActions(this.graph, {actions: batchActions}); }
- src/server/roam-server.ts:330-338 (registration)Registers the tool handler in the MCP server switch statement for tool calls.case BASE_TOOL_NAMES.PROCESS_BATCH_ACTIONS: { const { actions } = request.params.arguments as { actions: any[]; }; const result = await this.toolHandlers.processBatch(actions); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; }
- src/tools/schemas.ts:490-555 (schema)Input schema and metadata definition for the tool, including description and validation rules.[toolName(BASE_TOOL_NAMES.PROCESS_BATCH_ACTIONS)]: { name: toolName(BASE_TOOL_NAMES.PROCESS_BATCH_ACTIONS), description: 'Executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Actions are executed in the provided order. For creating nested blocks, you can use a temporary client-side UID in a parent block and refer to it in a child block within the same batch. For actions on existing blocks, a valid block UID is required. Note: Roam-flavored markdown, including block embedding with `((UID))` syntax, is supported within the `string` property for `create-block` and `update-block` actions. For actions on existing blocks or within a specific page context, it is often necessary to first obtain valid page or block UIDs. Tools like `roam_fetch_page_by_title` or other search tools can be used to retrieve these UIDs before executing batch actions. For simpler, sequential outlines, `roam_create_outline` is often more suitable.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.', inputSchema: { type: 'object', properties: { actions: { type: 'array', description: 'An array of action objects to execute in order.', items: { type: 'object', properties: { "action": { type: 'string', description: 'The specific action to perform.', enum: ['create-block', 'update-block', 'move-block', 'delete-block'] }, "uid": { type: 'string', description: 'The UID of the block to target for "update-block", "move-block", or "delete-block" actions.' }, "string": { type: 'string', description: 'The content for the block, used in "create-block" and "update-block" actions.' }, "open": { type: "boolean", description: "Optional: Sets the open/closed state of a block, used in 'update-block' or 'create-block'. Defaults to true." }, "heading": { type: "integer", description: "Optional: The heading level (1, 2, or 3) for 'create-block' or 'update-block'.", enum: [1, 2, 3] }, "text-align": { type: "string", description: "Optional: The text alignment for 'create-block' or 'update-block'.", enum: ["left", "center", "right", "justify"] }, "children-view-type": { type: "string", description: "Optional: The view type for children of the block, for 'create-block' or 'update-block'.", enum: ["bullet", "document", "numbered"] }, "location": { type: 'object', description: 'Specifies where to place a block, used in "create-block" and "move-block" actions.', properties: { "parent-uid": { type: 'string', description: 'The UID of the parent block or page.' }, "order": { type: ['integer', 'string'], description: 'The position of the block under its parent (e.g., 0, 1, 2) or a keyword ("first", "last").' } } } }, required: ['action'] } } }, required: ['actions'] } },
- src/tools/tool-handlers.ts:140-142 (helper)Wrapper method in ToolHandlers class that delegates to BatchOperations.processBatch.async processBatch(actions: any[]) { return this.batchOps.processBatch(actions); }
- src/tools/schemas.ts:25-25 (registration)Constant mapping base name to prefixed tool name used in schema and registration.PROCESS_BATCH_ACTIONS: 'roam_process_batch_actions',