The source of truth is arch.yaml. The .drawio is generated from it, and if you tweak it in draw.io
arch import put it back into the source of truth with. The reason for keeping a source of truth is so that diffs can be read, it can be edited and verified with scripts,
and the same diagram comes out no matter how many times you regenerate it.
The code is in tools/ 's uv project.Always use this form for invocation
(<SKILL> is the directory containing this SKILL.md. It may contain spaces, so wrap it in quotes).
uv run --project "<SKILL>/tools" arch <サブコマンド> ...
Do not use plain python3 . In a Nix environment, python3 may keep launching itself and hang.
Dependencies are pinned with tools/uv.lock , and on the first run they go into tools/.venv .
Entry points
| What was said | Where to go |
|---|---|
| "Make a diagram of ~" "Design this kind of architecture" | From step 0 |
Given an existing .drawio and told "fix it" "check whether it follows the conventions" |
Step 0 → arch import → from step 4 |
| "The icons don't show up" "Add a new icon ZIP" | Step 0 only |
| "Change just this part" (the diagram made just before) | arch edit → from step 4 |
0. Check that icons can be read (once at the start, every time)
uv run --project "<SKILL>/tools" arch doctor
The icon is Use the SVG from the official AWS Asset Package as the source of truth. Do not use draw.io's standard mxgraph.aws4 (because updates lag, old designs get mixed in, and convention checks cannot determine whether something is official).
Place the library in <SKILL>/icons/current/ (not under git management. It can be replaced with$ARCH_ICON_LIB か --lib ).
doctor が NG If you getdo not proceed to drawing。
- If ZIP candidates are shown, ask the user in one line whether it is okay to import it, then
arch icons build '<zip>'run it (vendor's aws-drawio-import converts it) - If there are no candidates, ask the user as follows and stop: "The official AWS icons (Asset Package ZIP) are required. Download fromhttps://aws.amazon.com/architecture/icons/ and tell me the path to the ZIP"
You can draw even without draw.io Desktop (check with an approximate SVG instead of PNG). In that case, write that fact in the report.
doctor also outputs the date of the imported Asset Package. Write it in the report. The Asset Package is updated quarterly, so if a warning that it is old appears, tell the user in one line whether a new version has been released (do not stop drawing).
1. Nail down the requirements (confirm only once)
Fill in the following table yourself from the request text.Only the ones that cannot be filled in AskUserQuestion で、all at onceAsk (up to 4 questions).
Make the options concrete proposals derived from the request, and put the recommended one first.
| Item | Example | Default that may be decided without asking |
|---|---|---|
| What the diagram is for / who will view it | For design review / for proposal materials / for operational procedures | Design review |
| Environment and availability | Production (2 AZs) / test (1 AZ) | Production = 2 AZs |
| How far to draw | Down to subnets / down to the VPC / only the relationships between services | up to subnet |
| Required services and constraints | "ECS on Fargate" "on-premises and VPN" | Only what is in the request |
| Region | ap-northeast-1 | ap-northeast-1 |
| How users enter | Public internet / internal only (VPN, Direct Connect) | Do not decide (see below) |
| Strictness of the final pass | Standard / strict | Standard |
Do not silently settle on assumptions that are not in the request. In particular, how users enter (public internet or internal only) completely changes the security shape. When you cannot ask (you have used up your questions, or the user is not available), draw it with the most plausible option, andwrite it in the diagram as an assumption (notes:.spec.md) and also write it in the "Assumptions" section of the report.
Notes must be readable at a size close to body labels even in the full-diagram view.notes: is output to fit the page width, so split it into short pieces per assumption.
"Strict" is chosen when the user says "strictly", "for review submission", or "so there is no misreading".
Also resolve the critique's should , or list what cannot be resolved as unresolved in the report (step 5).
Design decisions (why ALB, why Aurora) go in the report, not the diagram. Put only the configuration, flows, and assumptions in the diagram.
1.5 Verify the latest AWS information (only where uncertain)
Your local knowledge and the lint rules are from a certain point in time. Only when one of the following applies,verify with official sourcesbefore starting the design.
- New services or features, recently changed specifications (name changes, limits, whether integration is possible)
- Whether it is available in the specified region (new services may not have arrived in Tokyo)
- Specifications that determine whether the configuration works (e.g., whether that combination can connect to a VPC, whether it supports Multi-AZ)
- The impact of configuration choices specified in the request (such as "do not use a VPC" or "1 AZ is fine") and the conditions under which they should be reconsidered. Draw the diagram as specified, and write the impact in the design decisions section of the report
How to verify and how to record it is references/aws-knowledge.md. If AWS Knowledge MCP is available, use it; if not, use a web search limited to official documentation
(docs.aws.amazon.com / aws.amazon.com).Leave the date verified and the source URLs in the report.
Do not verify well-known, stable facts (such as placing NAT in a public subnet). Spend time only on uncertain points.
2. Write arch.yaml
The format is references/spec.md, and the example is assets/example.arch.yaml。Read both before writing.
If the user does not specify an output destination, place it as docs/architecture/<slug>/ に <slug>.arch.yaml .
- Write icons by name. If you do not know it, search:
arch icons search <語>(e.g., even common names or abbreviations likearch icons search firewall)NAT GatewayALBS3are resolved to the official name
- The group is
group:Specify the type withaws-cloud/region/vpc/az/public-subnet/private-subnet/security-group/auto-scaling/account/corporate-dc/genericetc. For the list, see spec.md) - A
genericwith children becomes a grouping frame, and an emptygenericwith a label connected to a line becomes a compact solid-line box as an external endpoint. An unconnected empty group becomes a lint warning - Boxes for arranging the layout should be
group: layout. No frame is drawn, and they are treated as nonexistent in nested convention checks - If you need a paper aspect ratio matching a photo or form, use
page_aspect(for the specified range and default values, seereferences/spec.md) - Compose the diagram with Web page header / body / footer. Place IGW above the header (the top edge of the VPC), ALB in the header, AZs side by side in the body (inside each AZ, public → app → data from top to bottom), and the exit to the outside in the footer (the bottom edge of the VPC). Each icon has its inlet and outlet facing each other (inside the VPC, top→bottom; outside, left→right), and lines from the ALB descend between AZs and split into a T shape. Connection ports are determined automatically by build. For details, see "Flow and connection ports" in spec.md (the example is this shape)
- Gateways have fixed placement locations. IGW / VGW go on the VPC border (if placed directly under the VPC, they are automatically placed on it), NAT goes inside a public subnet,
Gateway-type endpoints go on the VPC border (specify the edge with
border:). For the list, see "Gateway placement locations" in spec.md
3. Generate
uv run --project "<SKILL>/tools" arch build <slug>.arch.yaml -o <slug>.drawio
build reads arch.yaml in UTF-8 (with or without BOM), reloads the generated temporary .drawio , and lints it.flow and explicitly specified exit / entry は .drawio . If the lint results at build time and after saving do not match, or if there is an error after saving, it fails and does not replace the existing output.
4. Deterministic checks (lint) — reduce errors to 0
uv run --project "<SKILL>/tools" arch lint <slug>.drawio # 実物の .drawio を検査する
uv run --project "<SKILL>/tools" arch lint <slug>.drawio --strict-geometry # 交差・接触・重複・検査不能な線があれば失敗
error(N-*: drawing conventions) should all be fixed. If even one remains, do not proceed to critique or delivery- Before delivery, also run
--strict-geometry. If there is even one crossing, endpoint contact, duplicate route, or line whose route cannot be restored, the exit code is 1 warn(A-*: configuration best practices) should in principle be fixed. If you leave one intentionally, write the reason in the report (e.g., 1 AZ because it is a verification environment)- The meaning and rationale of each rule are in
references/aws-conventions.md. How to fix it is on the line of→in the output - Lint the delivered
.drawioitself after the last edit. Do not reuse the lint results from build time.N-PORT-FACE/N-PORT-SLOT、N-EDGE-*、N-NODE-UNCONNECTEDconfirm that it does not remain in the final diagram. For warnings that are kept, write the reason in the report
When fixing,rather than manually rewriting the yaml, arch edit is preferred. This is because the script guarantees id consistency (e.g., connection lines are also removed when deleted).
If you touch up the final diagram in draw.io Desktop, after saving, restore it to the source of truth with arch import <slug>.drawio -o <slug>.arch.yaml and from there regenerate .drawio . Lint the .drawio after regeneration, and export the PNG from that same file. Do not use the lint or PNG from before the touch-up as the final version's inspection results. For isolated service nodes, either add the relevant lines or remove them from the diagram.
The build automatically searches for connection line routes. The connection ports below are at the bottom edge of the label, and a route that avoids icons, labels, and headings is chosen.
Lines that cannot be avoided become N-EDGE-THROUGH-NODE (error), so fix them by changing the order or layout , or by fixing the connection ports.
In zsh, a command stored in a variable is not split on whitespace, so make it a function and then call it.
A() { uv run --project "<SKILL>/tools" arch edit <slug>.arch.yaml "$@"; }
A add-node waf --icon "AWS WAF" --label WAF --parent cloud --after cf
A add-group az-d --type az --label "AZ ap-northeast-1d" --parent azs
A move rds-a --parent db-a # 所属を変える (手動座標は外れて自動配置に戻る)
A set alb label="ALB\n(internet-facing)"
A connect cf waf --label HTTPS ; A disconnect cf alb
A set-edge alb ecs-a label=HTTP exit=right entry=left # 線のラベル・線種・接続口 (exit= で探索に戻す)
A remove az-c # 子と、それにつながる接続線も消える
A relayout # draw.io から取り込んだ手動座標を消して自動配置に戻す
After editing,build → lint run through it once more.
5. Look at the PNG and submit it for critique (rework loop)
uv run --project "<SKILL>/tools" arch render <slug>.drawio -o .arch-loop/<slug>/round-N/<slug>.png
First, Read the PNG yourself and look at it. There are visual breakdowns that lint cannot catch. Particularly common ones are connection lines crossing over icons or labels, line intersections, reversed flow direction, and elements being too crowded or too sparse. Fix the ones you can identify yourself first. Also check overlaps between line labels or with other lines, the height and bending of lines for the same role between AZs, and branches that share a trunk.
Then,a model from a different series than the implementationhave it critique. The default is Sonnet. If the same model grades it, it will overlook its own habits. If that series is unavailable in the environment, run it with another available series and convey in one line, "The critique was run with <model>."
Start a new critique owner for each round and wait for the reply (run_in_background: false). If you ask the previous round's critique owner to continue via
SendMessage, your work here may finish before the reply arrives. Pass the previous context with accepted .
Agent: subagent_type "general-purpose", model "sonnet", run_in_background false
prompt:
よく考えてから採点してほしい。まず <SKILL>/agents/diagram-critic.md を読み、その指示に完全に従うこと。
- png: <.arch-loop/<slug>/round-N/<slug>.png> ← 必ず Read で画像を見る
- spec: <slug>.arch.yaml のパス
- requirements: <手順1で固めた要件を箇条書きで>
- strictness: <標準 / 厳しめ>
- lint: <arch lint の出力をそのまま>
- accepted: <これまでに確定した判断 (.arch-loop/<slug>/accepted.md の中身。無ければ「なし」)>
返答は指定の JSON のみ。
- The reply is
.arch-loop/<slug>/round-N/critique.jsonにwithout modificationsave - Fix only the findings. Do not tidy up other places while you are at it. After fixing, run build → lint → render
- Add confirmed decisions (such as "Place S3 directly under the region") to
.arch-loop/<slug>/accepted.mdone line at a time. If you do not add them, the critique owner in the next round will point out the opposite and you will go back and forth user_conflictIf it is not empty, do not fix it on the implementation side; ask the user to decide
Exit conditions: 0 lint errors, andThe delivered PNG itselfcriticism of it is pass If so, it is complete.
- If you fix it after the criticism, that diagram still has not been seen by anyone.The revised final version must always go through criticism again. If you fix it after the second round, use the assumption of not fixing it for theconfirmation criticismrun it only once, and write the result in the report
- The critic makes misleading points (mistaking line endpoints, arrows pointing opposite to the flow, lines appearing to touch unrelated elements)
mustinto.mustWhile remains, it does not pass - When "strict",
shouldalso pass with 0 items. List what remains in the report's "Unresolved" with the reason for not fixing it - Cut off at 2 rounds (confirmation criticism is not counted). Even if it has not passed, return it to the user with the actual item and the remaining points. The third round is run only when the user says "continue"
6. Delivery and report
The deliverables are <slug>.arch.yaml (master),<slug>.drawio (for editing),<slug>.png (for confirmation), three in total.
.arch-loop/ is for work, so write only the path in the report. Write the following briefly in the report:
- Paths of the three deliverables
- Key points of the structure and design decisions (why that structure) in 3–6 lines
- Assumptions (the diagram's
notes:same as . Assumptions not in the request that you placed yourself) - Confirmed AWS information (what was verified in step 1.5. Confirmation date and source URL. If not verified, "none")
- Icons used: Asset Package date (doctor output)
- lint results (error 0 / remaining warns and their reasons)
- Number of criticism rounds,Result of criticism on the final version、Unresolvedpoints (not fixed
shouldand the reason) - How to return after manual edits in draw.io: "After saving,
arch import <slug>.drawio -o <slug>.arch.yamlreturn to the master with "
When receiving a diagram manually edited in draw.io
uv run --project "<SKILL>/tools" arch import <slug>.drawio -o <slug>.arch.yaml
- import writes the coordinates on draw.io back to yaml as
pos/size.Before overwriting the master, check whether it is under git management, or make a copy - For official icons placed from draw.io's Custom Library, look up the official name from the image contents.
Images or shapes that cannot be looked up become
N-UNMANAGEDerrors - If the visual position and belonging are misaligned (e.g., it is only on top of the frame and not inside it),
N-VISUAL-PARENTit becomes. Drag it back inside the frame in draw.io, orarch edit movefix the belonging with
For users who want to add icons in draw.io,<SKILL>/icons/current/*.xml and have them open it via "File → Open Library" (Custom Libraries if using the VS Code extension).
Bundled items
| Path | Contents | When to read |
|---|---|---|
references/spec.md |
arch.yaml format, list of groups, and placement tips | Before writing arch.yaml |
references/aws-conventions.md |
Meaning and rationale of each lint rule | When interpreting lint results |
.mcp.json |
AWS Knowledge MCP Server connection endpoint (also registered at the repository root. If absent, proceed with web search) | Step 1.5 |
references/aws-knowledge.md |
How to verify the latest AWS information (AWS Knowledge MCP / official documentation) and how to record it | Step 1.5 |
agents/diagram-critic.md |
Instructions for the critique subagent | Read by the subagent |
assets/example.arch.yaml |
Sample of a 3-tier web (2 AZ) | When writing it for the first time |
tools/src/arch_builder/cli.py |
arch Command body (layout, generation, import, editing) |
When fixing behavior |
tools/src/arch_builder/route.py |
Connection line pathfinding (port selection, detours, penalties). lint uses the same judgment | When fixing how lines are drawn |
tools/src/arch_builder/rules.py |
Convention checks. Add rules here | When adding rules |
tools/src/arch_builder/render.mjs |
PNG export (uses the Desktop integration in vendor/drawio) | — |
tools/tests/test_arch.py |
Self-check: uv run --project <SKILL>/tools pytest <SKILL>/tools/tests -q |
Always when you touch the code |
vendor/drawio/ |
drawio skill (MIT). XML and style specifications (references/official/) and export implementation |
When directly editing raw XML |
vendor/aws-drawio-import/ |
Official icon ZIP → draw.io library conversion | arch icons build called by |
icons/current/ |
Imported official icons (not under git management) | — |