AI Integration
BPMN SDK is designed from the ground up to work with AI agents. The compact intermediate format lets a complete process diagram fit in a single LLM prompt, and the builder API produces valid BPMN without requiring the AI to write raw XML.
The Compact Format
Raw BPMN XML is far too verbose for LLMs — a simple three-node process generates ~60 lines. The compact format represents the same information as a small JSON object:
import { Bpmn, compactify, expand } from "@bpmn-sdk/core";
// Parse some BPMN XMLconst definitions = Bpmn.parse(existingXml);
// Convert to compact formatconst compact = compactify(definitions);// compact is ~500 tokens for a typical approval workflow
// Send to your LLM, get back a modified compact objectconst modified = await llm.modify(compact, "Add a parallel notification step after approval");
// Convert back to full BPMNconst updatedDefinitions = expand(modified);const updatedXml = Bpmn.export(updatedDefinitions);Minimal Empty Diagram
When an AI agent needs to start fresh, use Bpmn.makeEmpty() to get a valid starting point
with a single start event:
import { Bpmn } from "@bpmn-sdk/core";
// Returns a valid BPMN XML string — one start event, ready for an agent to extendconst xml = Bpmn.makeEmpty("my-process", "My Process");Prompting Strategy
For best results, give the LLM the compact diagram and a clear instruction. A good system prompt excerpt:
You are a BPMN process designer. The user will describe a business process and you willreturn a CompactDiagram JSON object.
Rules:- Use camelCase IDs- Every service task needs a taskType string (the Zeebe worker subscription)- Use FEEL expressions for gateway conditions (start with "= ")- Always include a start event and at least one end event- Do not add fields that are not part of the CompactDiagram schemaClaude API Example
Using the Anthropic SDK to generate a process from a description:
import Anthropic from "@anthropic-ai/sdk";import { Bpmn, expand } from "@bpmn-sdk/core";import type { CompactDiagram } from "@bpmn-sdk/core";
const anthropic = new Anthropic();
async function generateProcess(description: string): Promise<string> { const response = await anthropic.messages.create({ model: "claude-opus-4-6", max_tokens: 2048, system: `You are a BPMN process designer. Return only valid JSON matching theCompactDiagram schema. No explanation, no markdown — raw JSON only.`, messages: [ { role: "user", content: `Create a BPMN process for: ${description}`, }, ], });
const json = response.content[0]; if (json?.type !== "text") throw new Error("Unexpected response type");
const compact = JSON.parse(json.text) as CompactDiagram; const definitions = expand(compact);
return Bpmn.export(definitions);}
const xml = await generateProcess( "An invoice approval process where invoices over $10,000 need manager approval");OpenAI Function Calling
Use function/tool calling for reliable structured output:
import OpenAI from "openai";import { expand, Bpmn } from "@bpmn-sdk/core";
const openai = new OpenAI();
const response = await openai.chat.completions.create({ model: "gpt-4o", messages: [ { role: "user", content: "Create a customer onboarding process with email verification and KYC check", }, ], tools: [ { type: "function", function: { name: "create_bpmn_process", description: "Create a BPMN process diagram", parameters: compactDiagramJsonSchema, // export from @bpmn-sdk/core }, }, ], tool_choice: { type: "function", function: { name: "create_bpmn_process" } },});
const toolCall = response.choices[0]?.message.tool_calls?.[0];if (!toolCall) throw new Error("No tool call");
const compact = JSON.parse(toolCall.function.arguments);const xml = Bpmn.export(expand(compact));MCP Server
BPMN SDK ships with a Model Context Protocol (MCP) server that exposes process editing tools to any MCP-compatible AI client (Claude Desktop, Cursor, etc.):
# Start the MCP servercasen mcpAvailable MCP tools:
get_diagram— returns the current diagram as CompactDiagram JSONupdate_diagram— applies a CompactDiagram diffadd_service_task— adds a single service task with Zeebe configadd_http_call— adds a pre-configured Camunda HTTP connector taskapply_layout— re-runs auto-layout on the current diagramvalidate— validates the diagram and returns any schema errors