{"id":14719,"date":"2025-12-04T17:17:02","date_gmt":"2025-12-04T14:17:02","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=14719"},"modified":"2025-12-04T17:49:10","modified_gmt":"2025-12-04T14:49:10","slug":"how-to-create-org-chart-builder-dhtmlx-diagram-and-openai-api","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/how-to-create-org-chart-builder-dhtmlx-diagram-and-openai-api\/","title":{"rendered":"How to Create Org Chart Builder with DHTMLX Diagram and OpenAI API"},"content":{"rendered":"<p>Today, many organisations have complex structures with multiple levels of management, varied reporting lines, and roles that often overlap or change over time. Organisational charts (or simply org charts) visualise such structures, providing a clear chain of command, responsibilities, and the overall structure of departments and teams. DHTMLX Diagram offers a dedicated org chart mode specifically designed to display such hierarchical structures on web pages. But you can go further and complement DHTMLX Diagram with AI to generate interactive org charts using commands in plain English. <\/p>\n<p>In this tutorial, we provide step-by-step instructions for creating your own AI Org Chart Builder using  DHTMLX Diagram and AI services.<\/p>\n<h2>What to Expect from AI Org Chart Builder<\/h2>\n<p>The AI Org Chart Builder is the latest addition to the list of <a href=\"https:\/\/dhtmlx.com\/docs\/products\/ai-demos\/\" rel=\"noopener\" target=\"_blank\">DHTMLX AI demos<\/a>. It turns a text description of your team into a clear, interactive diagram. Instead of manually creating charts, you can just write or paste your organisational info, and the system does the rest. <\/p>\n<p>For instance, you can ask the Org Chart Builder to create an org chart for a dental clinic with a Clinic Manager overseeing Therapeutic, Orthodontics, Oral Surgery, Dental Hygiene, and Administrative departments, along with their corresponding staff.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/12\/image1.gif\" alt=\"generating org charts with AI\" width=\"1920\" height=\"856\" class=\"aligncenter size-full wp-image-14720\" \/><br \/>\n<a href=\"https:\/\/dhtmlx.com\/docs\/demo\/ai-org-chart-builder\/\" rel=\"noopener\" target=\"_blank\">Open live demo ><\/a><\/p>\n<p>The Org Chart Builder workflow is divided into simple, sequential steps:<\/p>\n<ol>\n<li><strong>Describe:<\/strong> A user inputs the required organization structure in plain English (or picks one of the ready-made templates for a try-out) and presses the &#8220;Analyze&#8221; button.<\/li>\n<li><strong>Analyze:<\/strong> The backend attaches a set of instructions to the prompt and sends everything to the AI for transforming the message into a well-structured hierarchy.<\/li>\n<li><strong>Review:<\/strong> The updated structure appears in the second section of the Org Chart Builder, so the user can review it, make edits, and click the &#8220;Build diagram&#8221; button.<\/li>\n<li><strong>Build:<\/strong> The backend asks the AI to generate the final JSON configuration for the org chart.<\/li>\n<li><strong>Visualize and Edit:<\/strong> The system uses the AI-generated JSON to render the org chart using the functional DHTMLX Diagram editor. The same JSON data appears in the code editor, where any tweaks sync instantly with the Diagram editor.<\/li>\n<li><strong>Export:<\/strong> The final diagram can be exported to JSON, PNG, and PDF formats.<\/li>\n<\/ol>\n<p>Looks like something worth trying in a web project, right? And we are ready to help you out with relevant implementation instructions. The full project codebase is available in the <a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/\" rel=\"noopener\" target=\"_blank\">GitHub repository<\/a>.<\/p>\n<p><em><strong>Note:<\/strong> make sure that you have installed Node.js for running the backend server and an OpenAI API key (or a compatible AI service).<\/em><\/p>\n<h2>Step 1: Setting Up the Frontend UI<\/h2>\n<p>The Org Chart Builder interface is based on our <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxDiagram\/\" rel=\"noopener\" target=\"_blank\">JavaScript diagramming component<\/a> and provides a convenient workspace for data visualization, which consists of four collapsible sections. Each section represents one logical step of the workflow, keeping the UI tidy and guiding the user naturally through the process. <\/p>\n<p>There is nothing complicated about creating such an interface. First, you create an HTML layout that will give placeholders for all UI elements of your future AI Org Chart Builder.<br \/>\nThe markup for this UI is already available in our demo project (<a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/blob\/main\/frontend\/index.html\" rel=\"noopener\" target=\"_blank\">index.html<\/a>), so here we\u2019ll look at the key elements that make up the layout:<\/p>\n<div class=\"codecolorer-container html4strict default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"html4strict codecolorer\"><span class=\"sc2\">&lt;<span class=\"kw2\">div<\/span> <span class=\"kw3\">class<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;main-content&quot;<\/span>&gt;<\/span> <br \/>\n&nbsp; &nbsp; <span class=\"sc-1\">&lt;!-- Step 1: User Input --&gt;<\/span> <br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">textarea<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;user-input&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">textarea<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">button<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;analyze-btn&quot;<\/span>&gt;<\/span>Analyze<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">button<\/span>&gt;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"sc-1\">&lt;!-- Step 2: AI Review --&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">textarea<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;rephrased-text&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">textarea<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">button<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;confirm-btn&quot;<\/span>&gt;<\/span>Build diagram<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">button<\/span>&gt;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"sc-1\">&lt;!-- Step 3: Visualization --&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">div<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;diagram-container&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">div<\/span>&gt;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"sc-1\">&lt;!-- Step 4: Data &amp; Export --&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">div<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;json-editor&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">div<\/span>&gt;<\/span><br \/>\n&nbsp;<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">div<\/span>&gt;<\/span><\/div><\/div>\n<p>Now, you can initialize the interactive parts of your AI Org Chart Builder (<a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/blob\/main\/frontend\/app.js\" rel=\"noopener\" target=\"_blank\">app.js<\/a>). Here is the relevant portion of the initialization code:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"co1\">\/\/ initializes the DHTMLX Diagram editor (org chart mode)<\/span><br \/>\n<span class=\"kw1\">const<\/span> diagramEditor <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">DiagramEditor<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;diagram-container&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;org&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; shapeType<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;img-card&quot;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ initalizes the Monaco JSON editor<\/span><br \/>\n<span class=\"kw1\">const<\/span> jsonEditor <span class=\"sy0\">=<\/span> monacoInstance.<span class=\"me1\">editor<\/span>.<span class=\"me1\">create<\/span><span class=\"br0\">&#40;<\/span>document.<span class=\"me1\">getElementById<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'json-editor'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; value<span class=\"sy0\">:<\/span> <span class=\"st0\">''<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; language<span class=\"sy0\">:<\/span> <span class=\"st0\">'json'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; theme<span class=\"sy0\">:<\/span> <span class=\"st0\">'vs-dark'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; readOnly<span class=\"sy0\">:<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; automaticLayout<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>As a result, you get the Diagram editor for displaying org charts and the code editor for working with JSON structures of your visualizations. <\/p>\n<h2>Step 2: Interfacing with AI &#8211; Rephrase, Build, and Sync<\/h2>\n<p>Now that the UI\u2019s foundation is set, it is time to connect it to the backend. After that, you will learn how to add an interaction layer (<a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/blob\/main\/frontend\/app.js\" rel=\"noopener\" target=\"_blank\">app.js<\/a>), including the ability to send prompts to the AI, receive AI-processed hierarchy, generate the org chart preview, and keep everything updated across the diagram and code editors.<\/p>\n<h3>2.1 Establishing the WebSocket Connection<\/h3>\n<p>You should use the Socket.IO library to enable real-time communication between the frontend and the backend. This ensures that when a user submits text, the AI processes it and sends back results instantly:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"co1\">\/\/ Opens a websocket connection for AI operations<\/span><br \/>\n<span class=\"kw1\">const<\/span> socket <span class=\"sy0\">=<\/span> io<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>This single line enables real-time updates between the frontend and backend, making our diagram responsive to AI-generated changes. <\/p>\n<h3>2.2 Handling User Prompts<\/h3>\n<p>After the user enters a description and clicks the Analyze button, the prompt is sent to the backend, where it is complemented with guiding instructions. After that, this data is sent to the LLM, which produces a clean, structured hierarchy. <\/p>\n<p>To make it work, you need to add the <strong>addEventListener<\/strong> handler. So, when the button is clicked, the following logic is executed:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">analyzeButton.<span class=\"me1\">addEventListener<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'click'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> text <span class=\"sy0\">=<\/span> userInputTextArea.<span class=\"me1\">value<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>text<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Please enter a description.&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; setButtonLoadingState<span class=\"br0\">&#40;<\/span><span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span> analyzeButton<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; resetUI<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ Sends the initial prompt to the backend for AI rephrasing &nbsp; &nbsp; &nbsp; <\/span><br \/>\n&nbsp; &nbsp; socket.<span class=\"me1\">emit<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'rephrase_text'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> text <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span>response<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; setButtonLoadingState<span class=\"br0\">&#40;<\/span><span class=\"kw2\">false<\/span><span class=\"sy0\">,<\/span> analyzeButton<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ If AI provides the rephrased version, it will be displayed for review<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>response.<span class=\"me1\">status<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">'success'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reviewTextArea.<span class=\"me1\">value<\/span> <span class=\"sy0\">=<\/span> response.<span class=\"me1\">payload<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reviewSection.<span class=\"me1\">open<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">''<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Analysis error: &quot;<\/span> <span class=\"sy0\">+<\/span> response.<span class=\"me1\">message<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>The user can estimate the rephrased prompt and manually make necessary adjustments.<\/p>\n<h3>2.3 Building the Org Chart<\/h3>\n<p>Once the user confirms the rephrased prompt by clicking the &#8220;Build Diagram&#8221; button, it is sent to the LLM to generate structured JSON for the org chart.<\/p>\n<p>Just like in the case above, you add the <strong>addEventListener<\/strong> to the button to react to the user\u2019s click and run all the logic that generates the final org chart:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">confirmButton.<span class=\"me1\">addEventListener<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'click'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> verifiedText <span class=\"sy0\">=<\/span> reviewTextArea.<span class=\"me1\">value<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>verifiedText<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Text for analysis cannot be empty.&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; setButtonLoadingState<span class=\"br0\">&#40;<\/span><span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span> confirmButton<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ Verified prompt is sent, and the backend instructs AI to generate the org chart<\/span><br \/>\n&nbsp; &nbsp; socket.<span class=\"me1\">emit<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'generate_diagram'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> verifiedText <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span>response<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; setButtonLoadingState<span class=\"br0\">&#40;<\/span><span class=\"kw2\">false<\/span><span class=\"sy0\">,<\/span> confirmButton<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>response.<span class=\"me1\">status<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">'success'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> data <span class=\"sy0\">=<\/span> response.<span class=\"me1\">payload<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Populates the JSON editor<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jsonEditor.<span class=\"me1\">setValue<\/span><span class=\"br0\">&#40;<\/span>JSON.<span class=\"me1\">stringify<\/span><span class=\"br0\">&#40;<\/span>data<span class=\"sy0\">,<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Renders the org chart in the Diagram Editor <\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; diagramEditor.<span class=\"me1\">diagram<\/span>.<span class=\"me1\">data<\/span>.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>data<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; diagramSection.<span class=\"me1\">open<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exportSection.<span class=\"me1\">open<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">''<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Generation error: &quot;<\/span> <span class=\"sy0\">+<\/span> response.<span class=\"me1\">message<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, the Diagram editor displays the org chart, while the code editor shows the corresponding JSON structure.<\/p>\n<h3>2.4 Syncing Editors<\/h3>\n<p>The code editor is fully interactive. Any manual changes in the JSON structure will be reflected in the Diagram editor in real time. <\/p>\n<p>Here is the logic behind this behavior:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">jsonEditor.<span class=\"me1\">onDidChangeModelContent<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; clearTimeout<span class=\"br0\">&#40;<\/span>debounceTimer<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; debounceTimer <span class=\"sy0\">=<\/span> setTimeout<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">try<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class=\"kw1\">const<\/span> jsonData <span class=\"sy0\">=<\/span> JSON.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>jsonEditor.<span class=\"me1\">getValue<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;diagramEditor.<span class=\"me1\">diagram<\/span>.<span class=\"me1\">data<\/span>.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>jsonData<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;displayError<span class=\"br0\">&#40;<\/span><span class=\"st0\">''<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">catch<\/span> <span class=\"br0\">&#40;<\/span>e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ It's okay if the JSON is temporarily invalid while typing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">500<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>This ensures full synchronization between the visual org chart and its JSON representation.<\/p>\n<h3>2.5 Export Options<\/h3>\n<p>Finally, you can enable users to export the org chart using <strong>diagram.export.png()<\/strong> and <strong>diagram.export.pdf()<\/strong> methods included in the DHTMLX Diagram API.<\/p>\n<p>Now, we can proceed to the most exciting part of our tutorial, namely, how the backend prepares the data for AI, calls the model, and sends its responses back to the browser.<\/p>\n<h2>Step 3: Backend Intelligence Layer \u2013 Rules, Prompts, Validation, Response Delivery<\/h2>\n<p>In previous sections, we touched on the backend\u2019s behavior at a high level. Now, we are transitioning from general concepts to explaining the backend role from a technical standpoint, providing concrete code examples. <\/p>\n<h3>Main Backend Responsibilities<\/h3>\n<p>Right now, we\u2019ll consider the core backend responsibilities (<a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/blob\/main\/backend\/server.js\" rel=\"noopener\" target=\"_blank\">server.js<\/a>) and explain how each of them contributes to producing correct org charts:<\/p>\n<ul>\n<li>Receiving events from frontend (<strong>rephrase_text<\/strong>, <strong>generate_diagram<\/strong>) via Socket.IO<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">io.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'connection'<\/span><span class=\"sy0\">,<\/span> socket <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n<span class=\"co1\">\/\/event for rephrasing the initial prompt<\/span><br \/>\n&nbsp; &nbsp; socket.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'rephrase_text'<\/span><span class=\"sy0\">,<\/span> async <span class=\"br0\">&#40;<\/span>data<span class=\"sy0\">,<\/span> callback<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp;<span class=\"co1\">\/\/... <\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp;<br \/>\n<span class=\"co1\">\/\/event for generating the final org chart structure<\/span><br \/>\n&nbsp; &nbsp; socket.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'generate_diagram'<\/span><span class=\"sy0\">,<\/span> async <span class=\"br0\">&#40;<\/span>data<span class=\"sy0\">,<\/span> callback<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/... <\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Once the backend receives these events, it can apply the necessary rules, prompts, and schema validations, ensuring the AI correctly addresses the user&#8217;s request. <\/p>\n<ul>\n<li>Calling the LLM using structured prompts and a function-calling schema<\/li>\n<\/ul>\n<p>The <strong>callOpenAIForDiagram(userText)<\/strong> function sends the cleaned user text to the AI, using a function-calling schema, and asks the AI to return a properly structured JSON configuration for the org chart.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">async <span class=\"kw1\">function<\/span> callOpenAIForDiagram<span class=\"br0\">&#40;<\/span>userText<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> messages <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> role<span class=\"sy0\">:<\/span> <span class=\"st0\">'system'<\/span><span class=\"sy0\">,<\/span> content<span class=\"sy0\">:<\/span> diagramPrompt <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> role<span class=\"sy0\">:<\/span> <span class=\"st0\">'user'<\/span><span class=\"sy0\">,<\/span> content<span class=\"sy0\">:<\/span> userText <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">try<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> res <span class=\"sy0\">=<\/span> await openai.<span class=\"me1\">chat<\/span>.<span class=\"me1\">completions<\/span>.<span class=\"me1\">create<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; model<span class=\"sy0\">:<\/span> <span class=\"st0\">'gpt-4.1-nano'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messages<span class=\"sy0\">:<\/span> messages<span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tools<span class=\"sy0\">:<\/span> schemaList<span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tool_choice<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;function&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span><span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;create_org_chart_diagram&quot;<\/span> <span class=\"br0\">&#125;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> res.<span class=\"me1\">choices<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#93;<\/span>.<span class=\"me1\">message<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">catch<\/span> <span class=\"br0\">&#40;<\/span>e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">throw<\/span> <span class=\"kw1\">new<\/span> Error<span class=\"br0\">&#40;<\/span>`Error from AI service<span class=\"sy0\">:<\/span> $<span class=\"br0\">&#123;<\/span>e.<span class=\"me1\">message<\/span><span class=\"br0\">&#125;<\/span>`<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>The <strong>callOpenAIForRephrase(userText)<\/strong> function works similarly, but without Function Calling. It wraps the user text with a system prompt, instructing the AI how to structure the output.<\/p>\n<ul>\n<li>Validating AI output<\/li>\n<\/ul>\n<p>Raw AI output can sometimes be unpredictable. The backend performs two validation steps before sending data to the frontend:<\/p>\n<p>1) Ensures each node has a text label, and if not, assigns the default one:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">parsedResult.<span class=\"me1\">nodes<\/span>.<span class=\"me1\">forEach<\/span><span class=\"br0\">&#40;<\/span>node <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>node.<span class=\"me1\">text<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; node.<span class=\"me1\">text<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;Unknown Position&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>2) Fixes the hierarchy by removing connections to non-existent parent nodes using the <strong>fixHierarchy(nodes)<\/strong> helper function:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> fixHierarchy<span class=\"br0\">&#40;<\/span>nodes<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>nodes <span class=\"sy0\">||<\/span> nodes.<span class=\"me1\">length<\/span> <span class=\"sy0\">===<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">return<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> existingIds <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> Set<span class=\"br0\">&#40;<\/span>nodes.<span class=\"me1\">map<\/span><span class=\"br0\">&#40;<\/span>node <span class=\"sy0\">=&gt;<\/span> node.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; nodes.<span class=\"me1\">forEach<\/span><span class=\"br0\">&#40;<\/span>node <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>node.<span class=\"me1\">parent<\/span> <span class=\"sy0\">&amp;&amp;<\/span> <span class=\"sy0\">!<\/span>existingIds.<span class=\"me1\">has<\/span><span class=\"br0\">&#40;<\/span>node.<span class=\"me1\">parent<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.<span class=\"me1\">warn<\/span><span class=\"br0\">&#40;<\/span>`<span class=\"st0\">&quot;Orphan&quot;<\/span> detected<span class=\"sy0\">!<\/span> Node <span class=\"st0\">&quot;${node.text}&quot;<\/span> refers to a non<span class=\"sy0\">-<\/span>existent parent <span class=\"st0\">&quot;${node.parent}&quot;<\/span>. <span class=\"me1\">Connection<\/span> removed.`<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">delete<\/span> node.<span class=\"me1\">parent<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> nodes<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>These measures help keep the UI safe from inaccurate hierarchies.<\/p>\n<ul>\n<li>Returning the final JSON configuration to the frontend<\/li>\n<\/ul>\n<p>After validating the AI response, all that remains for the backend to do is forward the finalized JSON data to the frontend for rendering  via the Socket.IO callback:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">callback<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> status<span class=\"sy0\">:<\/span> <span class=\"st0\">'success'<\/span><span class=\"sy0\">,<\/span> payload<span class=\"sy0\">:<\/span> fixedNodes <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<h3>How the AI is Instructed: System Prompts and Schema<\/h3>\n<p>Only one question remains: how exactly does the backend instruct the LLM to rearrange the initial user prompt into a clear hierarchy and generate JSON data for creating the org chart? To do that, the backend uses two system prompts (<a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/blob\/main\/backend\/ai-prompts.js\" rel=\"noopener\" target=\"_blank\">ai-prompts.js<\/a>):<\/p>\n<ul>\n<li><strong>rephrasePrompt<\/strong> &#8211; converts free-text descriptions into a well-defined hierarchical list aligning with specific structural rules.<\/li>\n<li><strong>diagramPrompt<\/strong> &#8211; explains to the AI how to turn the user\u2019s request into a corresponding diagram configuration. Importantly, it tells the model to call the <strong>create_org_chart_diagram<\/strong> function.<\/li>\n<\/ul>\n<p>Apart from system prompts, it is necessary to specify the JSON format that DHTMLX Diagram will accept. Here, you will need the function-calling schema (OpenAI\u2019s Function Calling). The schema (<a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\/blob\/main\/backend\/schema.js\" rel=\"noopener\" target=\"_blank\">schema.js<\/a>) defines the expected JSON structure:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">export<\/span> <span class=\"kw1\">const<\/span> schemaList <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;function&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">function<\/span><span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;create_org_chart_diagram&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Creates an organizational chart diagram from an array of nodes.&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;object&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; properties<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nodes<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;array&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;An array of objects, where each object represents an employee.&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;object&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; properties<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;string&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Unique numerical employee identifier using dot notation for hierarchy (e.g., '1', '1.1', '1.2').&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;string&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Employee's position (e.g., 'CEO', 'Manager', 'Developer').&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parent<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;string&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;ID of the direct manager.&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"co1\">\/\/\u2026more properties<\/span><\/div><\/div>\n<p>This approach ensures that the AI cannot return free text or arbitrary formats, even when users provide vague or unstructured requests. The AI must generate a valid function call that matches the schema, providing the JSON configuration for rendering in the Diagram editor.<\/p>\n<p>That\u2019s all you have to know to integrate DHTMLX Diagram with AI services without any serious problems. But if anything is still unclear about how the DHTMLX AI Org Chart Builder works, check out the project\u2019s <a href=\"https:\/\/github.com\/DHTMLX\/diagram-org-chart-builder-ai-demo\" rel=\"noopener\" target=\"_blank\">GitHub repository<\/a> to fill the gaps. <\/p>\n<h2>Conclusion<\/h2>\n<p>This tutorial is another vivid demonstration of what becomes possible when DHTMLX Diagram meets AI. The AI Org Chart Builder turns unstructured ideas into clear visuals in seconds, unlocking opportunities for faster visualizations of complex hierarchical structures and more intuitive user experiences. Stay tuned for new examples of using DHTMLX components with AI.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, many organisations have complex structures with multiple levels of management, varied reporting lines, and roles that often overlap or change over time. Organisational charts (or simply org charts) &#8230;<\/p>\n","protected":false},"author":101014,"featured_media":14721,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71],"tags":[77,33,58],"class_list":["post-14719","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-ai","tag-all-posts","tag-diagram"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14719","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/101014"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=14719"}],"version-history":[{"count":9,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14719\/revisions"}],"predecessor-version":[{"id":14730,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14719\/revisions\/14730"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/14721"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=14719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=14719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=14719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}