Examples

Six diagrams archgram drew, each with what it shows, the keys in its spec that make it so, and the spec to copy.

Each drawing below is archgram's own output, untouched, drawn from the spec under it. Under each one you'll find what it shows, the keys in its spec that make it look that way, and the kind of system it suits. Open the spec, copy it, and change it into yours.

To draw one, save its spec in your project and run archgram build on it. The Quickstart shows how.

A web service with a cache and a worker#

The API creates short links and redirects. A redirect reads the URL from the Redis cache, falls back to Postgres on a miss, adds the click to a Redis stream and returns. A worker drains the stream in batches and adds the counts to Postgres, where the stats route reads them. a visit: Visitor → API → Click stream → Worker → links.The API creates short links and redirects. A redirect reads the URL from the Redis cache, falls back to Postgres on a miss, adds the click to a Redis stream and returns. A worker drains the stream in batches and adds the counts to Postgres, where the stats route reads them. a visit: Visitor → API → Click stream → Worker → links.

A link shortener. The API reads the cache and falls back to the database on a miss, and a worker counts the clicks in the background.

Fields in the specWhat it does
frames: [{ id: redis, label: Redis }]Draws a box round the cache and the click stream, two parts of one Redis.
style: dashedDraws the call that happens only sometimes, on a cache miss, as a dashed line.
note: "1-day TTL"Adds a short line under a card's name.
flows: [{ name: a visit, … }]Animates one visit, from the browser to the database.

Use it for the README of a typical web backend.

linkshort.archgram.yaml
yaml
archgram: 1
credit: false
title: linkshort
description: >-
  The API creates short links and redirects. A redirect reads the URL from
  the Redis cache, falls back to Postgres on a miss, adds the click to a
  Redis stream and returns. A worker drains the stream in batches and adds
  the counts to Postgres, where the stats route reads them.
nodes:
  - { id: browser, kind: browser, label: Visitor }
  - { id: api, kind: service, label: API, note: "FastAPI, port 8000", tech: fastapi }
  - { id: cache, kind: cache, label: URL cache, note: "1-day TTL", tech: redis, frame: redis }
  - { id: clicks, kind: queue, label: Click stream, tech: redis, frame: redis }
  - { id: worker, kind: service, label: Worker, note: up to 500 per read }
  - { id: postgres, kind: database, label: links, note: source of truth, tech: postgresql }
frames:
  - { id: redis, label: Redis }
edges:
  - { from: browser, to: api }
  - { from: api, to: cache }
  - { from: api, to: postgres, label: on a miss, style: dashed }
  - { from: api, to: clicks }
  - { from: clicks, to: worker }
  - { from: worker, to: postgres }
flows:
  - { name: a visit, steps: [browser, api, clicks, worker, postgres] }

A request turned away at a check#

The browser asks the API for the user's orders. Before anything is read, the API has Clerk check the request's session. A request without a session is refused at the session check and the refusal goes back to the browser; signed in, it passes to the orders service, which reads the orders from Postgres. a request without a session: Browser → API → Session, refused at Session. signed in, it goes through: Browser → API → Session → Orders → Postgres.The browser asks the API for the user's orders. Before anything is read, the API has Clerk check the request's session. A request without a session is refused at the session check and the refusal goes back to the browser; signed in, it passes to the orders service, which reads the orders from Postgres. a request without a session: Browser → API → Session, refused at Session. signed in, it goes through: Browser → API → Session → Orders → Postgres.

A request without a session is refused at the session check and the refusal goes back to the browser. Signed in, the same request passes and reaches the database.

Fields in the specWhat it does
stop: sessionEnds the first flow at Session. A ✕ marks the line into it, and the refusal travels back to the browser.
direction: downLays the drawing out from top to bottom.
variant: externalMarks Session as a service you do not run, here Clerk.

Use it for sign-in, permissions, validation or rate limits, anywhere a request can be told no.

sign-in.archgram.yaml
yaml
archgram: 1
credit: false
title: Orders behind a sign-in
description: >-
  The browser asks the API for the user's orders. Before anything is read,
  the API has Clerk check the request's session. A request without a
  session is refused at the session check and the refusal goes back to the
  browser; signed in, it passes to the orders service, which reads the
  orders from Postgres.
direction: down
nodes:
  - { id: browser, kind: browser, label: Browser, note: the shop, tech: react }
  - { id: api, kind: service, label: API, note: GET /orders, tech: nodedotjs }
  - { id: session, kind: service, label: Session, note: is the user signed in?, tech: clerk, variant: external }
  - { id: orders, kind: service, label: Orders, note: the user's orders }
  - { id: db, kind: database, label: Postgres, note: orders, tech: postgresql }
edges:
  - { from: browser, to: api }
  - { from: api, to: session, label: check }
  - { from: session, to: orders, label: signed in }
  - { from: orders, to: db }
flows:
  - { name: a request without a session, steps: [browser, api, session], stop: session }
  - { name: "signed in, it goes through", steps: [browser, api, session, orders, db] }

A checkout across hosted services#

The Next.js storefront on Vercel sends each checkout through edge middleware, which asks Clerk to verify the session before the checkout API reads the cart from Upstash Redis and charges with Stripe. Stripe's webhook starts a Temporal workflow that writes the order to Supabase and sends the receipt with Resend. A guest's checkout is refused at the session check; signed in, it goes through. a guest checks out: Storefront → Middleware → Session, refused at Session. signed in, the order goes through: Storefront → Middleware → Session → Checkout API → Payments → Fulfilment → orders, Receipts.The Next.js storefront on Vercel sends each checkout through edge middleware, which asks Clerk to verify the session before the checkout API reads the cart from Upstash Redis and charges with Stripe. Stripe's webhook starts a Temporal workflow that writes the order to Supabase and sends the receipt with Resend. A guest's checkout is refused at the session check; signed in, it goes through. a guest checks out: Storefront → Middleware → Session, refused at Session. signed in, the order goes through: Storefront → Middleware → Session → Checkout API → Payments → Fulfilment → orders, Receipts.

A storefront built on hosted services. A guest's checkout is refused at the session check. Signed in, the order is paid, and a webhook starts a workflow that saves the order and sends the receipt at once.

Fields in the specWhat it does
variant: externalMarks Clerk, Upstash, Stripe and Resend as services you do not run.
steps: [… flow, [db, mail]]A list inside the steps is a branch. Both are reached at once.
label: webhookNames a line.
signal: sparkPicks how the moving request is drawn.

Use it for a product built on SaaS APIs, where most boxes belong to someone else.

saas.archgram.yaml
yaml
archgram: 1
credit: false
title: Checkout on the edge
description: >-
  The Next.js storefront on Vercel sends each checkout through edge
  middleware, which asks Clerk to verify the session before the checkout
  API reads the cart from Upstash Redis and charges with Stripe. Stripe's
  webhook starts a Temporal workflow that writes the order to Supabase and
  sends the receipt with Resend. A guest's checkout is refused at the
  session check; signed in, it goes through.
direction: down
signal: spark
glow: true
nodes:
  - { id: web, kind: browser, label: Storefront, note: Next.js, tech: nextdotjs }
  - { id: edge, kind: service, label: Middleware, note: at the edge, tech: vercel, frame: vercel }
  - { id: auth, kind: service, label: Session, note: verify, tech: clerk, variant: external }
  - { id: api, kind: service, label: Checkout API, note: route handlers, tech: nodedotjs, frame: vercel }
  - { id: cart, kind: cache, label: Cart, tech: upstash, variant: external }
  - { id: pay, kind: service, label: Payments, tech: stripe, variant: external }
  - { id: flow, kind: service, label: Fulfilment, note: durable workflow, tech: temporal }
  - { id: db, kind: database, label: orders, tech: supabase }
  - { id: mail, kind: service, label: Receipts, tech: resend, variant: external }
frames:
  - { id: vercel, label: Vercel }
edges:
  - { from: web, to: edge }
  - { from: edge, to: auth }
  - { from: auth, to: api, label: signed in }
  - { from: api, to: cart }
  - { from: api, to: pay }
  - { from: pay, to: flow, label: webhook }
  - { from: flow, to: db }
  - { from: flow, to: mail }
flows:
  - { name: a guest checks out, steps: [web, edge, auth], stop: auth }
  - { name: "signed in, the order goes through", steps: [web, edge, auth, api, pay, flow, [db, mail]] }

An AI agent with tools#

A chat sends the question to the agent, which reasons with Claude and calls its tools: search_docs reads a Qdrant index of the docs, query_db reads the Postgres warehouse and run_code runs in a Docker sandbox. Every night a Python script embeds the docs with Mistral into the index. indexing the docs: docs/ → ingest.py → Embeddings → Docs index. a question: Chat → Agent → search_docs, query_db → Docs index, Warehouse. trying the fix: Chat → Agent → run_code.A chat sends the question to the agent, which reasons with Claude and calls its tools: search_docs reads a Qdrant index of the docs, query_db reads the Postgres warehouse and run_code runs in a Docker sandbox. Every night a Python script embeds the docs with Mistral into the index. indexing the docs: docs/ → ingest.py → Embeddings → Docs index. a question: Chat → Agent → search_docs, query_db → Docs index, Warehouse. trying the fix: Chat → Agent → run_code.

An agent that reasons with a model and calls three tools, one of which searches a docs index that a nightly script fills.

Fields in the specWhat it does
kind: agent / model / tool / vector-storeGives each AI part its own icon.
framesTwo boxes, loop and nightly, separate the agent's loop from the nightly indexing.
flowsThree paths, played one after another. One branches to two tools at once.
signal: cometDraws the moving request as a comet.

Use it for LLM apps, RAG and agents with tools.

agent.archgram.yaml
yaml
archgram: 1
credit: false
title: A coding agent with tools
description: >-
  A chat sends the question to the agent, which reasons with Claude and
  calls its tools: search_docs reads a Qdrant index of the docs, query_db
  reads the Postgres warehouse and run_code runs in a Docker sandbox.
  Every night a Python script embeds the docs with Mistral into the index.
signal: comet
glow: true
nodes:
  - { id: chat, kind: browser, label: Chat, note: React, tech: react }
  - { id: agent, kind: agent, label: Agent, note: plans and calls tools, tech: claude, frame: loop }
  - { id: llm, kind: model, label: Claude, note: reasoning, tech: anthropic, variant: external, frame: loop }
  - { id: search, kind: tool, label: search_docs, frame: loop }
  - { id: sql, kind: tool, label: query_db, frame: loop }
  - { id: run, kind: tool, label: run_code, note: sandbox, tech: docker, frame: loop }
  - { id: vec, kind: vector-store, label: Docs index, tech: qdrant }
  - { id: db, kind: database, label: Warehouse, tech: postgresql }
  - { id: docs, kind: file, label: docs/, note: Markdown, frame: nightly }
  - { id: ingest, kind: script, label: ingest.py, tech: python, frame: nightly }
  - { id: embed, kind: model, label: Embeddings, tech: mistralai, variant: external }
frames:
  - { id: loop, label: Agent loop }
  - { id: nightly, label: Nightly }
edges:
  - { from: chat, to: agent }
  - { from: agent, to: llm, label: think }
  - { from: agent, to: search }
  - { from: agent, to: sql }
  - { from: agent, to: run }
  - { from: search, to: vec }
  - { from: sql, to: db }
  - { from: docs, to: ingest }
  - { from: ingest, to: embed }
  - { from: embed, to: vec }
flows:
  - { name: indexing the docs, steps: [docs, ingest, embed, vec] }
  - { name: a question, steps: [chat, agent, [search, sql], [vec, db]] }
  - { name: trying the fix, steps: [chat, agent, run] }

Three apps on one platform#

The iOS, Android and web apps call one Cloudflare gateway. On Kubernetes, the Go orders service writes to Postgres and publishes each order to RabbitMQ, which streams it into ClickHouse; the Python recommendations service reads ClickHouse, and Grafana charts it. an order: iOS → Gateway → Orders → Events → Analytics. a recommendation: Web → Gateway → Recommendations → Analytics.The iOS, Android and web apps call one Cloudflare gateway. On Kubernetes, the Go orders service writes to Postgres and publishes each order to RabbitMQ, which streams it into ClickHouse; the Python recommendations service reads ClickHouse, and Grafana charts it. an order: iOS → Gateway → Orders → Events → Analytics. a recommendation: Web → Gateway → Recommendations → Analytics.

iOS, Android and web apps behind one gateway. Services on Kubernetes write to Postgres and stream events into an analytics database.

Fields in the specWhat it does
kind: mobile / browserDraws each client as what it is.
variant: multiShows a service that runs as several instances.
frames: [{ id: k8s, label: Kubernetes }]Draws the cluster round the services in it.
signal: pulseDraws the moving request as a pulse.

Use it for microservices behind a gateway, with more than one client.

platform.archgram.yaml
yaml
archgram: 1
credit: false
title: One platform, three apps
description: >-
  The iOS, Android and web apps call one Cloudflare gateway. On Kubernetes,
  the Go orders service writes to Postgres and publishes each order to
  RabbitMQ, which streams it into ClickHouse; the Python recommendations
  service reads ClickHouse, and Grafana charts it.
direction: down
signal: pulse
glow: true
nodes:
  - { id: ios, kind: mobile, label: iOS, tech: swift }
  - { id: android, kind: mobile, label: Android, tech: kotlin }
  - { id: web, kind: browser, label: Web, tech: react }
  - { id: gw, kind: service, label: Gateway, tech: cloudflare, variant: external }
  - { id: orders, kind: service, label: Orders, note: 6 pods, tech: go, variant: multi, frame: k8s }
  - { id: recs, kind: service, label: Recommendations, tech: python, variant: multi, frame: k8s }
  - { id: events, kind: queue, label: Events, tech: rabbitmq, frame: k8s }
  - { id: pg, kind: database, label: Orders DB, tech: postgresql }
  - { id: olap, kind: database, label: Analytics, tech: clickhouse }
  - { id: dash, kind: service, label: Dashboards, tech: grafana }
frames:
  - { id: k8s, label: Kubernetes }
edges:
  - { from: ios, to: gw }
  - { from: android, to: gw }
  - { from: web, to: gw }
  - { from: gw, to: orders }
  - { from: gw, to: recs }
  - { from: orders, to: pg }
  - { from: orders, to: events }
  - { from: events, to: olap, label: stream }
  - { from: recs, to: olap }
  - { from: dash, to: olap }
flows:
  - { name: an order, steps: [ios, gw, orders, events, olap] }
  - { name: a recommendation, steps: [web, gw, recs, olap] }

Tooling, written in JSON#

An agent's edit or commit goes through its hooks in .claude/hooks/design-system, a person's commit through the git pre-commit hook, and CI calls the core directly. All three run a stage of design-system/harness/gates.mjs, which reads design-system/gates.json and runs the token and rules checks against the DTCG tokens and DESIGN.md. A commit with a raw colour is refused at the checks and goes back to the person; fixed, it passes. a commit with a raw colour: A person → pre-commit → harness/gates.mjs → checks/, refused at checks/. the commit again, fixed: A person → pre-commit → harness/gates.mjs → checks/ → tokens/, DESIGN.md.An agent's edit or commit goes through its hooks in .claude/hooks/design-system, a person's commit through the git pre-commit hook, and CI calls the core directly. All three run a stage of design-system/harness/gates.mjs, which reads design-system/gates.json and runs the token and rules checks against the DTCG tokens and DESIGN.md. A commit with a raw colour is refused at the checks and goes back to the person; fixed, it passes. a commit with a raw colour: A person → pre-commit → harness/gates.mjs → checks/, refused at checks/. the commit again, fixed: A person → pre-commit → harness/gates.mjs → checks/ → tokens/, DESIGN.md.

Not a running system but a repository's tooling. An agent, a person and CI reach the same checks, and a commit with a raw colour is refused, then passes once fixed.

Fields in the specWhat it does
"kind": "script" / "file" / "check" / "users"Draws hooks, files, checks and people.
"stop": "checks"Refuses the first commit at the checks.
{ "archgram": 1, … }The whole spec is JSON. The fields are the same as in YAML, which suits a spec another program writes.

Use it for build pipelines, git hooks, CI and other tooling.

commit-gates.json
json
{
  "archgram": 1,
  "credit": false,
  "title": "One set of gates for agent, person and CI",
  "description": "An agent's edit or commit goes through its hooks in .claude/hooks/design-system, a person's commit through the git pre-commit hook, and CI calls the core directly. All three run a stage of design-system/harness/gates.mjs, which reads design-system/gates.json and runs the token and rules checks against the DTCG tokens and DESIGN.md. A commit with a raw colour is refused at the checks and goes back to the person; fixed, it passes.",
  "direction": "down",
  "nodes": [
    {
      "id": "agent",
      "kind": "agent",
      "label": "Claude Code",
      "note": "an edit, a commit",
      "tech": "claude",
      "variant": "external"
    },
    {
      "id": "person",
      "kind": "users",
      "label": "A person",
      "note": "git commit"
    },
    {
      "id": "ci",
      "kind": "service",
      "label": "CI job",
      "note": "optional",
      "tech": "githubactions"
    },
    {
      "id": "adapters",
      "kind": "script",
      "label": ".claude/hooks/design-system",
      "note": "only translate",
      "frame": "claude"
    },
    {
      "id": "precommit",
      "kind": "script",
      "label": "pre-commit",
      "note": "git hook"
    },
    {
      "id": "core",
      "kind": "script",
      "label": "harness/gates.mjs",
      "note": "every decision",
      "frame": "ds"
    },
    {
      "id": "gates",
      "kind": "file",
      "label": "gates.json",
      "note": "what runs, and when",
      "frame": "ds"
    },
    {
      "id": "checks",
      "kind": "check",
      "label": "checks/",
      "note": "tokens and rules contract",
      "frame": "ds"
    },
    {
      "id": "tokens",
      "kind": "file",
      "label": "tokens/",
      "note": "DTCG, the one source of values",
      "frame": "ds"
    },
    {
      "id": "designmd",
      "kind": "file",
      "label": "DESIGN.md",
      "note": "rules, no values"
    }
  ],
  "frames": [
    {
      "id": "claude",
      "label": "The agent's own folder"
    },
    {
      "id": "ds",
      "label": "design-system/ names no agent"
    }
  ],
  "edges": [
    {
      "from": "agent",
      "to": "adapters"
    },
    {
      "from": "person",
      "to": "precommit"
    },
    {
      "from": "ci",
      "to": "core",
      "label": "before-commit"
    },
    {
      "from": "adapters",
      "to": "core"
    },
    {
      "from": "precommit",
      "to": "core",
      "label": "before-commit"
    },
    {
      "from": "core",
      "to": "gates"
    },
    {
      "from": "core",
      "to": "checks"
    },
    {
      "from": "checks",
      "to": "tokens"
    },
    {
      "from": "checks",
      "to": "designmd"
    }
  ],
  "flows": [
    {
      "name": "a commit with a raw colour",
      "steps": [
        "person",
        "precommit",
        "core",
        "checks"
      ],
      "stop": "checks"
    },
    {
      "name": "the commit again, fixed",
      "steps": [
        "person",
        "precommit",
        "core",
        "checks",
        [
          "tokens",
          "designmd"
        ]
      ]
    }
  ]
}