Writing diagrams with an agent
The loop an AI agent follows to produce a correct diagram: read the language once, write source, validate until clean, check the meaning, render. It is for people who connect an agent to the diagram tools, and for the prompt an agent reads.
TL;DR
| Rule | Yes | No |
|---|---|---|
| Learn the language | Call get_diagram_syntax once, before the first diagram, and again with kind for the kind you draw | Guess node types from memory |
| Choose a kind | Unsure which kind fits? Call suggest_diagram; for a whole document, plan_document_diagrams. See choosing a kind | Force every picture into a flow |
| Check | Call validate_diagram after every edit, until valid is true | Render first and hope |
| Fix | Use each error's line, column, and hint | Rewrite the whole diagram for one typo |
| Icons | Call search_icons with the product name from the request, and use the first result | Invent an icon name, or guess amazon:s3 |
| Suggestions | Add the exact icon= or type= that W204 or W205 gives, or write icon=none | Ignore a suggestion without deciding |
| Colors | Choose a type or a tone | Ask for hex colors; they do not exist in the language |
| Meaning | Call outline_diagram and read it as the reader would | Assume the layout says what you meant |
| Starting point | For a common architecture, call find_pattern and adapt the checked diagram it returns. See architecture patterns | Draw a three-tier network or a serverless API from nothing |
| Size | One idea per diagram, at most about 15 nodes, and one more for each group, up to 25 | One diagram for a whole system |
| Fewer calls | Prefer a workflow: draw_diagram checks, describes, and draws in one call. See workflows | Call validate_diagram, outline_diagram, and render_diagram one after another |
| Editing | To change a picture that already exists, call read_diagram with its link or its text, edit the source, and draw again with embedSource true. See Editing an existing diagram | Redraw it from the picture, or edit the SVG by hand |
| Mermaid already | Have Mermaid already? See Migrating from Mermaid | Retype a Mermaid diagram by hand |
1. The loop
sequence "Agent authoring loop" desc="An agent reads the language, writes a diagram, validates it until it is clean, then renders it."
actor agent person "Agent"actor tools service "Diagram tools"
agent -> tools : "get_diagram_syntax"tools --> agent : "Node types, arrows, limits, examples"
loop "until valid is true" { agent -> tools : "validate_diagram" tools --> agent : "Errors with line, column, hint"}
agent -> tools : "outline_diagram"tools --> agent : "Plain-text description"note over agent, tools : "The agent checks the outline against what it meant to draw"
agent -> tools : "render_diagram"tools --> agent : "SVG and size"Participants:
- Agent, person
- Diagram tools, service
Steps:
-
- Agent to Diagram tools: get_diagram_syntax
-
- Diagram tools to Agent (dashed): Node types, arrows, limits, examples
- loop: until valid is true
- 3. Agent to Diagram tools: validate_diagram
-
- Diagram tools to Agent (dashed): Errors with line, column, hint
-
- Agent to Diagram tools: outline_diagram
-
- Diagram tools to Agent (dashed): Plain-text description
- Note over Agent and Diagram tools: The agent checks the outline against what it meant to draw
-
- Agent to Diagram tools: render_diagram
-
- Diagram tools to Agent (dashed): SVG and size
2. Read the language
get_diagram_syntax returns the language as data, in two sizes so that an agent does not pay for kinds it does not draw. With no arguments it returns the overview: every node type with its default icon and tone, arrows, line options, tones, status icons, icon sets and providers, limits, how to edit an existing picture, one line about each kind, and the tested examples of the kinds those shared tables describe. Pass kind (for example git or flow) to get that kind in full: its statements, limits, and a tested example. flow also carries the group types with their frame, tone, and icon, the overlays, and a complete cloud architecture example. The error codes are in the diagnostic codes reference, because every diagnostic a tool returns already carries its code, line, column, and hint. It lists the icon sets but not every icon: it points to search_icons, which finds a product icon from its name. It never changes, so an agent reads the overview once per session, and a kind once.
3. Validate until clean
validate_diagram takes the source and returns every problem in one pass. A mistake is a normal result, not an exception, so the agent can loop.
Source with a misspelled type:
flow "T"node a servce "A"Each mistake has a code, a position, and a hint. Drawn with the offending line and a caret under the characters to change, it reads like this.
error E120: Unknown node type "servce" 2 | node a servce "A" | ^^^^^^hint: Did you mean "service"?The agent changes servce to service, validates again, and gets valid: true. The tool returns the same facts as data:
| Field | Use |
|---|---|
valid | true when the diagram can be rendered. Loop until it is. |
errors | Every mistake: code, message, line, column, length, and hint. |
line, column, length | The exact characters to change, counted inside the diagram source. The caret above is drawn from them. |
hint | The suggested fix. For an unknown word it names the closest valid one. |
warnings | Quality problems in a valid diagram: too dense, too wide, text cut, unconnected node. Fix them when the diagram is meant for a document. Two are suggestions, described below. |
summary and size | Present once the diagram is valid. |
The result as JSON
{ "valid": false, "errors": [ { "code": "E120", "message": "Unknown node type \"servce\"", "line": 2, "column": 8, "length": 6, "hint": "Did you mean \"service\"?" } ], "warnings": []}The full result also carries kind and severity, and summary and size as null until the diagram is valid.
Icon and group-type suggestions
For an architecture diagram, validate_diagram also suggests the icon and the group type an author left out. Each suggestion is a warning with the exact text to add, so the fix is one edit and never a guess. Nothing is applied for you.
| Code | The warning says | The fix |
|---|---|---|
W204 | Node "db" has no icon=, and its label names azure:cosmos-db | Add icon=azure:cosmos-db to the node, or write icon=none to keep it plain. |
W205 | Group "net" has no type=, and its name says subnet | Add type=subnet to the group, or type=subnet provider=aws when the name also names a provider. |
The rules are fixed, so the same source gets the same suggestions every time. A label counts only as whole words, the longest phrase wins, and a label that fits two products or two types gets no suggestion. A generic phrase such as SQL database counts only inside a group, or a diagram, whose provider= owns that product, and a brand such as Redis counts only when it is the whole label. The cloud architecture guide shows the full recipe.
4. Check the meaning
A valid diagram can still say the wrong thing: an arrow reversed, a node in the wrong group. outline_diagram returns the diagram as plain text, in reading order. Compare it to the intent. The one-line summary becomes the alt text of the picture, and the rest appears in the collapsed Text description, so it is also what a screen reader hears.
5. Render and place
render_diagram returns the SVG, its pixel size, and any warnings, in the light or dark theme. To put a diagram in a document, write it as a diagram fence in the Markdown file and call sync_markdown with the file; see Diagrams in Markdown and on GitHub.
6. Habits that produce good diagrams
| Habit | Yes | No |
|---|---|---|
| Labels | Auth API, Token exchange | The service that handles authentication requests |
| Detail | Put it in sub="OAuth 2.1" or a note | Put it in the label |
| Types | database for a database, gateway for a gateway | step for everything |
| Boundaries | A group with type=trust-boundary or type=network, a dashed frame | A text label that says "inside the VPC" |
| Cloud products | icon=aws:lambda found with search_icons, one node per service | A generic box labeled Lambda, or one node per instance |
| Outcomes | A terminal with icon=status:success or status:denied | A green node chosen by hand |
| Splitting | Two diagrams joined by a sentence | Fifteen nodes plus a legend |
7. Ways to call the tools
| Surface | How |
|---|---|
| MCP over stdio | npx -y @buun_group/plotwork-mcp@0.1.0-beta.10, started by your client, with no key. See Connecting an agent. |
| MCP over HTTP | https://mcp.plotwork.dev/mcp with an API key, or https://mcp.plotwork.dev/mcp-oauth with a browser sign-in. |
| HTTP API | POST /v1/diagrams/validate, /render, /outline, GET /v1/icons, GET /v1/vocabulary, on the Pro plan. See the API reference. |
8. Workflows: one call instead of several
A workflow is a tool that performs several operations and returns one combined answer, so the agent spends one turn where it would spend three or four. The single tools stay for fine-grained steps. Every workflow is read-only, never guesses, and keeps its work bounded; the tool reference lists the operations and the limit of each.
| Workflow | Ask your agent | It replaces |
|---|---|---|
draw_diagram | "Draw this flow and check it" | validate_diagram, then outline_diagram, then render_diagram. Invalid source returns every error and draws nothing, so the loop is one call per fix. |
convert_mermaid | "Convert this Mermaid diagram to Plotwork" | The converter, then validation, outline, and render. The result lists everything that was dropped, with a hint for each. |
map_icons | "Choose icons for these services" | One search_icons call per name. A name that could mean more than one icon comes back with candidates and no guess. |
find_pattern | "Is there a ready-made diagram for a two-zone network?" | A guess at what exists. It ranks the checked patterns for the request in plain words and returns summaries, never source. |
get_pattern | "Show me the three-tier network pattern for Azure" | Reading a pattern by hand. It fills the pattern with your slot values and returns the source, every slot, the advice, and the diagram as a tree. |
draw_from_pattern | "Draw the serverless API pattern, with my service names" | get_pattern, then validate_diagram, then render_diagram. Slot values that break a rule come back as problems, and nothing is drawn. |
sync_markdown | "Replace the Mermaid diagrams in README.md" | Reading the fences, converting, rendering, and building the picture blocks for a whole document. |
suggest_diagram | "Which diagram shows who can call which endpoint?" | Reading every kind to choose one. It ranks the kinds for the request and gives a starter for each. |
plan_document_diagrams | "Which parts of this design doc need a picture?" | Reading a document section by section and choosing a kind for each. |
To move the Mermaid diagrams in a document, the sequence is:
- Call
sync_markdownwith the document text, its path,convertMermaid: true, andmode: "check". Read the report. - Call it again with
mode: "sync". The result holds the rewritten document and the picture files. - Write the returned
markdownto the document and each returned file to itspath. The tool writes nothing itself. - Review the change in git before committing.
Migrating from Mermaid explains the diagnostics and shows the result of each call.
9. Choosing a kind and planning a document
Two workflows help before any source is written. Both are cheap: they read text, parse each starter once, and lay nothing out.
| Workflow | Send | You get |
|---|---|---|
suggest_diagram | request in plain words, and optional data: a pasted table, a list, Label: value lines, or numbers by period | Up to 3 kinds, best first, each with a one-sentence reason, a confidence, the statements to use, and a starter that parses. Names and numbers from the request and the data are in the starter, and tailored says so. |
plan_document_diagrams | document: Markdown, HTML, or text pasted from Confluence, Notion, or Google Docs | The sections a picture would help, in document order, each with its heading, its line, a kind, a reason, and a starter drafted from the section's lists, tables, numbers, and dates. Sections that read well as text, or already hold a diagram, are left out. |
The shape of the text counts as much as its words:
| The text holds | The kind suggested |
|---|---|
| A table of roles with R, A, C, and I | matrix with style=raci |
| A table of roles with yes and no | matrix, a permission matrix |
| Numbers by month, week, or quarter | xychart |
| A number for each part | pie, treemap, or sankey |
A -> B: 1200 lines | sankey |
Dated lines, such as 2024: Public API | timeline |
Role: action lines where the roles come back | swimlane |
Paths such as src/index.ts | tree with style=files |
| A numbered list | flow |
A starter is a start: replace its placeholders, call get_diagram_syntax with its kind, and check it with draw_diagram before you draw. To put the pictures into the document, add each as a diagram fence under its heading and call sync_markdown.
The MCP server also offers prompts, which a client lists in its prompt menu. Each tells the agent which tools to call, in order.
| Prompt | Arguments | What it does |
|---|---|---|
diagram-from-description | description | suggest_diagram, then get_diagram_syntax, then draw_diagram; a common architecture goes to find_pattern first. |
diagrams-for-document | document, optional path | plan_document_diagrams, then a checked diagram for each section, then sync_markdown. |
permission-matrix | endpoints, roles | A matrix with roles as columns and endpoints as rows. |
architecture-overview | system | find_pattern and draw_from_pattern, or a layered or C4 diagram written for the system. |
convert-mermaid-file | markdown, optional path | sync_markdown with convertMermaid, then convert_mermaid for each fence that did not convert. |
10. Save diagrams to your library
Saving a finished diagram to Plotwork keeps it where your team can find it, beside the files and view links on your machine. Where it goes depends on how you connect.
| You use | What happens |
|---|---|
| The hosted MCP server, and an organisation you belong to keeps members' diagrams in its library | The server tells the agent to save each finished diagram to that private library with publish_diagram, without asking you, because only members can open it. Each valid drawing's next step says so too, and the answer names the library and gives the page for members. See Where members publish. |
| The hosted MCP server with an organisation key | The same: the key's own library is private, so the agent saves there. |
| The hosted MCP server with only your own library | The agent publishes only when you ask, because that link is public. |
| The local MCP server | Nothing is saved: it has no account. Use the command line below. |
| The command line | plotwork publish file.diagram saves every diagram of a file with the key in PLOTWORK_API_KEY, where your organisations decide, and prints the link. --org names the library. |
| The Claude Code plugin | PLOTWORK_PUBLISH=library saves each file to the organisation in PLOTWORK_ORG after it is drawn. See Claude Code plugin. |
See also
| Doc | Why |
|---|---|
| Connecting an agent | Settings for Claude Code and other clients |
| Tool reference | Arguments and results of every tool |
| API reference | The same operations over HTTP |
| Writing diagrams | The language by example |
| Cloud architecture | The five-step recipe for AWS, Azure, and Google Cloud diagrams, with every icon and group type drawn |
| Architecture patterns | Ready-made, checked diagrams to start from, found and filled by tools |
| Editing an existing diagram | Read the source back from a link or an SVG file, change it, and save or publish it again |
| Migrating from Mermaid | Convert existing Mermaid diagrams, and what to do with each diagnostic |
| Language reference | Every word the language accepts |