UML-Driven Agent Development¶
Model-first approach to agent workflow design: specify behavior as diagrams-as-code before writing implementation, keeping diagrams version-controlled alongside code.
Key Facts¶
- Model-Driven Architecture (MDA, OMG 2001) is the formal basis; pragmatic adoption = draw only for hard parts, not the whole system
- Mermaid renders natively in GitHub/GitLab/Notion markdown — no plugin required; diffs cleanly as text
- PlantUML covers all 14 UML 2.x diagram types (timing, profile, composite structure); Mermaid covers ~10
- D2 (2023+) has cleaner layout engine than Mermaid but smaller LLM training corpus
- LLMs generate Mermaid/PlantUML syntax reliably — feed a prompt, get a diff-able diagram
- Store diagrams in
docs/diagrams/alongside code; validate existence via CI orinit.sh - agent design patterns (ReAct, Plan-and-Execute, Reflexion) benefit from sequence + state diagrams during design
- agent orchestration graphs (LangGraph nodes/edges) map directly to activity diagrams
Diagram-to-Agent-Concern Mapping¶
| Agent concern | Diagram type | What it captures | Tooling fit |
|---|---|---|---|
| Multi-agent message flow | Sequence | Lifelines, message order, async awaits, alt/opt/loop fragments | Mermaid sequenceDiagram or PlantUML |
| Feature / task lifecycle | State | States, guard conditions, entry/exit actions, transitions | Mermaid stateDiagram-v2 or PlantUML |
| Hook and tool lifecycle | Activity | Decision points, parallel forks/joins, swimlanes per agent | PlantUML (swimlane support) |
| Memory layer hierarchy | Package / Component | Layer nesting, dependency arrows, namespace boundaries | PlantUML or C4 Component |
| Service topology (MCPs, APIs) | Deployment / C4 | Nodes, artifacts, communication paths, trust boundaries | Structurizr DSL or PlantUML |
| Actor scope discovery | Use Case | Actors, include/extend, acceptance criteria derivation | PlantUML |
| Data schema before code | Class | Types, fields, multiplicities, associations | Mermaid classDiagram or PlantUML |
| Time-critical protocol | Timing | Lifeline state over clock axis, signal transitions | PlantUML only (Mermaid lacks timing) |
Not worth diagramming: trivial functions, single-file scripts, hot fixes, exploratory code.
Mermaid Examples¶
Multi-Agent Coordination — sequenceDiagram¶
sequenceDiagram
autonumber
participant O as Orchestrator
participant R as ResearchAgent
participant V as VerifierAgent
participant T as ToolRunner
O->>R: dispatch(task, budget)
activate R
R->>T: search(query)
T-->>R: results[]
R-->>O: draft_report
deactivate R
O->>V: verify(draft_report)
activate V
alt verdict == REJECT
V-->>O: REJECT + reason
O->>R: retry(reason, reduced_budget)
else verdict == PASS
V-->>O: PASS
end
deactivate V
O-->>O: emit_result()
Feature/Task State Machine — stateDiagram-v2¶
stateDiagram-v2
[*] --> not_started
not_started --> in_progress : assign(agent_id)
in_progress --> blocked : external_dep_missing
blocked --> in_progress : dep_resolved
in_progress --> failed : error(reason)
failed --> in_progress : retry [attempts < MAX]
failed --> not_started : reset [user_decision]
in_progress --> done : L1_L2_L3_pass
done --> [*]
note right of in_progress
WIP = 1 enforced:
only one feature
in_progress at a time
end note
Hook Lifecycle Example — stateDiagram-v2¶
stateDiagram-v2
direction LR
[*] --> SessionStart : claude invoked
SessionStart --> PreToolUse : tool call queued
PreToolUse --> BLOCKED : hook exits non-zero
PreToolUse --> ToolExecution : hook exits 0
ToolExecution --> PostToolUse : tool returns
PostToolUse --> PreToolUse : next tool call
PostToolUse --> Stop : session end
Stop --> [*]
BLOCKED --> [*] : abort
Tool Comparison — When to Use Which¶
| Criterion | Mermaid | PlantUML | D2 | Structurizr (C4) |
|---|---|---|---|---|
| GitHub native render | Yes | No (needs pre-render or plugin) | No | No |
| UML 2.x coverage | ~10 of 14 types | All 14 | ~6 | 4 (C4 levels) |
| Timing diagrams | No | Yes | No | No |
| Profile / stereotype | No | Yes | No | No |
| Swimlane activity | Limited | Full | No | No |
| LLM generation quality | High (large corpus) | High | Medium (smaller corpus) | Medium |
| Layout control | Low (auto) | Medium | High (auto+manual) | Low (auto) |
| Java dependency | No | Yes (local jar) | No | No |
| Diff-ability | Excellent | Excellent | Excellent | Good |
| CI integration | mmdc CLI | plantuml.jar or server | d2 CLI | Structurizr CLI |
Decision rules: - Default to Mermaid — markdown-native, zero setup, LLM-ready - Switch to PlantUML when: timing diagrams needed, swimlane activity, full UML 2.x profile, enterprise compliance - Use D2 when: layout precision matters more than UML compliance (architecture sketches, ERD) - Use C4/Structurizr when: system context and container boundaries are the focus (service architecture, MCP topology)
PlantUML Sequence Fragment Reference¶
@startuml
participant Orchestrator as O
participant Worker as W
O -> W: start()
activate W
group loop [while budget > 0]
W -> W: process_batch()
alt result == ERROR
W --> O: error(code)
else result == OK
W --> O: partial_result
end
end
deactivate W
@enduml
Fragments available in PlantUML not in Mermaid: loop, opt, par, break, critical, ref.
Render Pipeline (CI / init.sh)¶
# PlantUML batch render (requires plantuml.jar or server)
find docs/diagrams -name "*.puml" | xargs -I{} java -jar plantuml.jar {}
# Mermaid batch render via CLI
find docs/diagrams -name "*.mmd" | xargs -I{} mmdc -i {} -o {}.svg
# Validate all referenced diagrams exist (add to init.sh)
grep -r "docs/diagrams/" . --include="*.md" | \
grep -oP 'docs/diagrams/[^\s)>"]+' | sort -u | \
while read f; do [ -f "$f" ] || echo "MISSING: $f"; done
Gotchas¶
-
Issue: Mermaid sequence diagram silently drops messages when participant names contain spaces or special characters without quoting. -> Fix: Always quote participant aliases:
participant "Tool Runner" as Tor use short aliases with no spaces; test render locally withmmdcbefore committing. -
Issue: PlantUML timing diagrams require
@startuml/@endumlplus explicitrobustorclockdeclarations — LLMs often generate syntactically invalid timing blocks from hallucinated keywords. -> Fix: Use the canonical PlantUML timing template:robust "Signal" as S+@S has state1,state2+@0 S is state1; validate with the official PlantUML server athttps://www.plantuml.com/plantuml/uml/before saving. -
Issue: Mermaid
stateDiagram-v2note syntax (note right of StateX) is only valid for top-level states — nested notes insidestate X {}blocks produce render errors without visible error messages. -> Fix: Move notes to top level after the composite state definition, or use PlantUML which has full note placement support. -
Issue: D2 auto-layout can place nodes in non-intuitive order when edge direction is bidirectional, making agent flow diagrams hard to read. -> Fix: Use
direction: rightordirection: downat the diagram root and force grouping withgrid-rows/grid-columnson container nodes.
See Also¶
- agent design patterns - ReAct, Plan-and-Execute, Reflexion patterns — these behavioral patterns are the subject of sequence and state diagrams
- agent orchestration - LangGraph state graphs and node/edge definitions map directly to activity diagrams
- multi agent systems - Coordinator/Fork/Swarm topologies visualized with sequence + component diagrams
- production patterns - Hook lifecycle and tool validation flows modeled with activity diagrams
- OMG UML 2.5.1 specification: https://www.omg.org/spec/UML/2.5.1/
- PlantUML official: https://plantuml.com/
- Mermaid documentation: https://mermaid.js.org/
- C4 Model: https://c4model.com/
- D2 language: https://d2lang.com/
- Diagrams as Code survey: https://modeling-languages.com/text-uml-tools-complete-list/