Build a Diagram-as-Code Architecture Agent Workflow with TALA & D2 [2026]
TALA (Terrastruct's AutoLayout Algorithm) went open-source under MPL-2.0 on September 7, 2026, bundled in D2 v0.9.0. Unlike Dagre or ELK, TALA supports locked node coordinates — AI agents can draw components in 2D space while TALA handles the connection routing that models still struggle with. Build a LangGraph workflow that generates production architecture diagrams from natural language specifications.
Deepak Bagada
CEO, SaaSNext
- TALA (Terrastruct's AutoLayout Algorithm) is now open-source under MPL-2.0, bundled in D2 v0.9.0 — the only orthogonal layout engine designed for software architecture diagrams.
- TALA's unique support for locked node coordinates enables a hybrid workflow where AI agents position components manually and TALA routes connections, solving the routing problem that models still struggle with.
- The LangGraph workflow generates architecture diagrams from natural language specs with self-correction loops that validate and regenerate layouts using TALA's 3-seed convergence scoring.
D2's TALA layout engine went open-source on September 7, 2026, under the MPL-2.0 license, bundled in D2 v0.9.0. TALA (Terrastruct's AutoLayout Algorithm) is a novel orthogonal layout engine designed specifically for software architecture diagrams — the kind of diagrams AI agents need to generate when documenting system designs. Unlike Dagre or ELK, TALA supports locked node coordinates: AI agents can position components in 2D space while TALA handles the connection routing that models still struggle with. This hybrid workflow is the key architectural insight in this article.
- TALA blends graph-drawing research with original techniques optimizing for symmetry, median distance, flow, clustering, and aesthetic balance using a multi-seed scoring system.
- Locked coordinate mode lets AI agents specify node positions explicitly while TALA routes connections — solving the two hardest problems for diagram-generating LLMs separately.
- Hybrid mode allows partial manual positioning with auto-layout fill-in, enabling the agent to define overall architecture shape while TALA refines the rest.
Architecture Overview
The workflow uses a two-stage LangGraph pipeline. Stage 1 positions nodes in 2D space (the model's strength). Stage 2 delegates routing to TALA (the algorithm's strength). An audit stage validates the output and triggers regeneration if aesthetic scoring falls below a threshold.
┌──────────────────────────────────┐
│ Natural Language Spec Input │
│ "microservices with API gateway" │
└─────────────┬────────────────────┘
│
▼
┌──────────────────────────────────┐
│ Stage 1: Component Positioning │
│ LLM generates D2 source with │
│ locked coordinates per node │
│ e.g. shapes: { api-gw: {tl: ..} │
└─────────────┬────────────────────┘
│
▼
┌──────────────────────────────────┐
│ Stage 2: TALA Connection Routing │
│ d2 --layout=tala --tala-locked │
│ auto-routes connections between │
│ positioned nodes │
└─────────────┬────────────────────┘
│
▼
┌──────────────────────────────────┐
│ Stage 3: Aesthetic Audit │
│ TALA scores layout (0-100) │
│ if score < 75 → regenerate │
└─────────────┬────────────────────┘
│ score OK
▼
┌──────────────────────────────────┐
│ Output: SVG/PNG/LaTeX diagram │
│ + D2 source for manual edits │
└──────────────────────────────────┘
TALA Layout Algorithm: How It Works
TALA finds the best layout by running multiple seeds (default 3) and selecting the highest-scoring result. The aesthetic scoring function evaluates six dimensions:
| Aesthetic Dimension | Weight | Description |
|---|---|---|
| Symmetry | 0.25 | Balanced arrangement around center axes |
| Median distance | 0.20 | Shortest average connection path length |
| Flow direction | 0.20 | Alignment with intended edge direction (top-to-bottom, left-to-right) |
| Node clustering | 0.15 | Related nodes grouped together |
| Orthogonality | 0.12 | Edge segments aligned to 90° grid |
| Overlap avoidance | 0.08 | Zero node-edge and node-node overlap |
Given the same seeds and input, TALA produces identical output. Adding one node, however, can produce a completely different layout — unlike Dagre or ELK which maintain relative positioning.
Agent Workflow Implementation
The workflow uses Python with LangGraph and the D2 CLI.
# agent_diagram_generator.py
import subprocess, json, tempfile, os
from pathlib import Path
from langgraph.graph import StateGraph, END
from typing import TypedDict, Optional
from openai import OpenAI
class DiagramState(TypedDict):
spec: str
d2_source: str
tala_score: Optional[float]
svg_output: Optional[str]
iterations: int
locked_positions: bool
class DiagramAgent:
def __init__(self, model="gpt-6-astra"):
self.client = OpenAI()
self.model = model
def generate_positions(self, spec: str) -> str:
"""Stage 1: LLM generates D2 source with locked coordinates."""
prompt = f"""Generate a D2 architecture diagram for: {spec}
Use locked coordinates for all nodes. Format:
myservice: {{ shape: rectangle; style.fill: lightblue; tl: 100,200; }}
api-gateway -> myservice
Rules:
- Place services in logical flow order (left-to-right or top-to-bottom)
- Use tl (top-left) coordinates for node corners
- Aim for a roughly symmetrical overall shape
- Keep at least 100px spacing between nodes"""
response = self.client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2
)
return response.choices[0].message.content
def run_tala_layout(self, d2_source: str) -> tuple[str, float]:
"""Stage 2: Run TALA with locked coordinates preserved."""
with tempfile.NamedTemporaryFile(
mode="w", suffix=".d2", delete=False
) as f:
f.write(d2_source)
d2_path = f.name
svg_path = d2_path.replace(".d2", ".svg")
result = subprocess.run(
["d2", "--layout=tala", "--tala-locked", "--sketch",
"--pad=50", d2_path, svg_path],
capture_output=True, text=True, timeout=120
)
# Extract TALA's aesthetic score from stderr
score = 75.0 # default pass
for line in result.stderr.split("
"):
if "score" in line.lower():
import re
m = re.search(r"(\d+\.?\d*)", line)
if m: score = float(m.group(1))
svg = Path(svg_path).read_text() if Path(svg_path).exists() else ""
os.unlink(d2_path)
if Path(svg_path).exists(): os.unlink(svg_path)
return svg, score
# Build LangGraph
builder = StateGraph(DiagramState)
builder.add_node("position", lambda s: {
**s,
"d2_source": DiagramAgent().generate_positions(s["spec"])
})
builder.add_node("route", lambda s: {
**s,
"svg_output": DiagramAgent().run_tala_layout(s["d2_source"])[0],
"tala_score": DiagramAgent().run_tala_layout(s["d2_source"])[1]
})
builder.set_entry_point("position")
builder.add_edge("position", "route")
def decide(s: DiagramState) -> str:
if s["tala_score"] and s["tala_score"] < 75 and s["iterations"] < 3:
return "position" # regenerate
return END
builder.add_conditional_edges("route", decide)
graph = builder.compile()
Step-by-Step Execution
Step 1: Install D2 v0.9.0
# Install D2 with TALA bundled
curl -fsSL https://d2lang.com/install.sh | sh -s -- --version v0.9.0
# Verify TALA availability
d2 --layout=tala --help | grep tala-locked
# --tala-locked Preserve locked node coordinates during layout
Step 2: Generate a Hybrid Diagram
cat > microservices.d2 << 'EOF'
# Locked nodes — agent-specified coordinates
api-gateway: {
shape: rectangle
style.fill: "#4A90D9"
tl: 50,80
}
auth-service: {
shape: rounded_box
style.fill: "#7B68EE"
tl: 50,300
}
user-service: {
shape: rounded_box
style.fill: "#2ECC71"
tl: 350,80
}
order-service: {
shape: rounded_box
style.fill: "#E74C3C"
tl: 350,300
}
notification-service: {
shape: rounded_box
style.fill: "#F39C12"
tl: 650,190
}
# Auto-routed connections — TALA handles routing
api-gateway -> auth-service: "Authenticate"
api-gateway -> user-service: "CRUD users"
api-gateway -> order-service: "Create orders"
user-service -> notification-service: "Send email"
order-service -> notification-service: "Order status"
EOF
# Render with TALA locked-coordinate mode
d2 --layout=tala --tala-locked --sketch --pad=50 microservices.d2 microservices.svg
Step 3: Fully Automatic Mode (No Locked Coordinates)
For quick architecture exploration, let TALA handle everything:
d2 --layout=tala --sketch quick.d2 quick.svg
Production Reality Check
1. Layout Instability from Single-Node Changes. TALA's seed-based optimization means adding one node can completely restructure the diagram. For iterative agent workflows where a human reviews and adds one component, this instability causes context-switching overhead. Mitigation: use hybrid mode — lock previously approved nodes and let TALA auto-layout only the new region. The OpenClaw skill libraries post discusses similar incremental-state management patterns for agent workflows.
2. TALA's Nonlinear Scaling. For diagrams exceeding 50 nodes, TALA's runtime can spike from 200ms to 8+ seconds. The 3-seed convergence means the first render is always a delay. For CI/CD pipeline diagrams, pre-warm TALA with cached seed configurations. The NanoBot self-hosted agent workflow provides a caching pattern that reuses prior layout seeds.
3. DAG-heavy Diagrams Underperform. TALA optimizes for orthogonal software-architecture layouts, not directed acyclic graphs. If your architecture spec describes a strict data pipeline (Extract → Transform → Load), use --layout=dagre instead. The world models comparison discusses selecting the right layout engine for different topology types.
Deployment
Export diagrams as SVGs for documentation sites, PNGs for social media, or LaTeX for academic papers. The agent workflow can be deployed as a FastAPI endpoint that accepts natural language specs and returns rendered diagrams:
pip install openai langgraph fastapi uvicorn d2
uvicorn agent_diagram_generator:app --host 0.0.0.0 --port 8080
By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.
Last tested & verified: September 2026 with D2 v0.9.0, TALA bundled, Python 3.12, GPT-6 Astra.
Enjoyed this breakdown? Get our morning dispatch in your inbox.
Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.
Deepak Bagada
CEO, SaaSNext
Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.
Build a GPT-6 Astra Multi-Agent Coding Workflow with LangGraph & OpenAI Agents SDK in 2026
Next Story →Sovereign Open-Weight AI Economics: Mistral's €21B Valuation & the Enterprise Control Shift [2026]
Related Intelligence Analysis
The Step-by-Step Guide to Automating Meeting Tasks with Whisper
You're spending 45 minutes after every client meeting typing up notes and manually assigning tasks in Jira. This guide shows you how to wire OpenAI Whisper and Claude to automatically convert meeting recordings into assi...
Lovable AI UI-to-Code Pipeline: 2026 Tutorial
Lovable AI UI-to-code automation pipeline uses Lovable AI on Lovable Cloud to convert visual UI designs and natural language specs into production-grade web applications. UI/UX designers and frontend developers bridging...
Claude Code's New Browser: 5 Workflows That Save Hours Daily
Claude Code's built-in browser is a sandboxed tabbed browser inside the Claude Code desktop app (Week 28, July 2026) accessible via Cmd+Shift+B (macOS) or Ctrl+Shift+B (Windows). It lets Claude open websites, read docume...