Skip to main content

graphspec

A spec for a graph. Agent systems built on Claude Code have an implicit topology: it is scattered across .claude/agents/*.md, the orchestrator's runtime decisions, and a few hooks. Nobody can see it whole, review it in a pull request, or diff two versions of it.

graphspec makes that topology an explicit, versioned artifact — a graphspec.yaml file — and gives it five things a hand-drawn diagram cannot:

  • a renderer (graphspec render) — Graphviz DOT/SVG/PNG with a stable visual grammar,
  • a validator (graphspec validate) — twelve mechanical rules, including the one that catches a node acting on half the story (E-READ-UNSET),
  • a semantic differ (graphspec diff) — topology changes reviewable like code changes,
  • a trace overlay (graphspec trace) — real OpenTelemetry executions drawn onto the declared graph, drift included,
  • a generator (graphspec scaffold) — agents, workflow skeletons and structured-output schemas that keep the declaration and the implementation in sync.

graphspec is the companion tool for the book Graph Engineering (Spanish and English editions).

What graphspec is not

graphspec does not execute graphs. It declares, draws, checks, diffs and generates. If you need durable execution — retries, persistence, resumable state machines — you want LangGraph or Temporal; graphspec will happily describe the graph you run there. No orchestration runtime, no scheduler, no cloud service, no telemetry, no account.

Install

pip install graphspec

Python 3.11+. The core depends only on pyyaml. render, validate and diff work without Graphviz installed (DOT output is text); --format svg|png needs the dot binary (graphviz.org/download).

Quick start

graphspec validate examples/software-delivery.yaml
graphspec render examples/software-delivery.yaml > graph.dot

The format is one YAML file with graphspec: 1 at the top. The full reference lives in docs/FORMAT.md; the shipped examples/software-delivery.yaml is the conformance target and the example printed in the book.

Validate

graphspec validate [FILE] [--strict] [--target claude]

Each violation prints file:line: [RULE-ID] message plus a one-line hint. Exit 1 on any error, 0 with warnings only; --strict promotes warnings to errors. --target claude additionally warns about advisory fields — declared behavior the generated code documents but does not enforce — so the gap between declaration and implementation is visible, never silent. The rule table is in docs/FORMAT.md.

Render

graphspec render [FILE] [--format dot|svg|png]

Emits Graphviz DOT on stdout by default — deterministic, byte-identical across runs, so it diffs cleanly in CI. --format svg|png shells out to dot and fails with an install hint when Graphviz is absent. The visual grammar is stable (the book prints these figures): node shape and colour by kind (function rectangle, llm rounded box, subagent double border, human diamond, terminal doubled circle); conditional edges dashed and labelled with their when; cycle-capping and on_timeout/on_exhausted edges in a distinct colour with max=N; shape-encoded badges (⚡ external effects, ⧉∥N fan-out with concurrency, ∀ ∃ ½ 1 join glyphs, ✓ checkpoints); substrate clusters when a graph spans more than one substrate; entry at the top, terminals at the bottom.

Trace

graphspec trace [FILE] --otlp FILE_OR_ENDPOINT [--session SESSION_ID]

Overlays real executions on the declared graph using the OpenTelemetry spans Claude Code already emits (CLAUDE_CODE_ENABLE_TELEMETRY=1 plus CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1) — no invented log format. Accepts an OTLP JSON export or a collector endpoint. The output is DOT where executed nodes are filled in proportion to token cost (with a numeric badge — never tint alone), un-executed nodes are greyed out, repeat visits are labelled ×N and the node where the run stopped is highlighted; a per-node cost table follows as // DOT comments, so the whole stream still pipes into dot.

Spans map onto nodes by the correlation contract scaffold emits: a graphspec:<node> label first, the agent name second. Every executed unit that matches neither is reported as drift between the declared topology and the real one — surfacing that is a feature, not an error. Span shapes are beta; every assumption about them lives in one fixture-covered module (graphspec/trace/mapping.py).

Diff

graphspec diff OLD NEW [--format text|markdown]

Semantic diff of two graph files: nodes, edges and state fields added, removed and changed (kind, agent, model, guards, caps, joins, effects). Exit 0 when topologically identical, 1 otherwise; --format markdown emits a PR-comment-ready summary. This — not a rendered image — is what makes topology reviewable: a change in the graph gets reviewed the way a change in code does.

Scaffold

graphspec scaffold [FILE] [--out .] [--force] [--target claude]

Generates, never overwriting by default: .claude/agents/<agent>.md per subagent node (frontmatter plus the node's contract — reads with optional markers, writes, advisory fields, expected evidence); a dynamic workflow skeleton under .claude/workflows/ whose control flow is derived from the edges, guards, caps, fan-out and join policies; a structured-output schema per writing node, derived from the declared state fields and injected into the generated agent() call — the mechanism that keeps declaration and implementation in sync; graphspec:<node> correlation labels on every generated unit (what trace maps spans by); a hooks fragment for deterministic edges; and stubs for missing impl: paths. Re-running is idempotent. validate --target claude names every advisory field so the declaration/generated-code gap is never silent.

CI: review topology like code

.github/workflows/graphspec-validate.yml is a reusable workflow: call it from any repository to validate graphspec.yaml on every pull request, post the graphspec diff against the base branch as a PR comment, and upload the rendered diagram as an artifact.

jobs:
  graphspec:
    uses: librosdeia/graphspec/.github/workflows/graphspec-validate.yml@main
    with:
      file: ./graphspec.yaml

Serve — the editor

graphspec serve [FILE] [--port PORT]

A local editor at http://localhost:PORT: YAML on the left, live graph on the right, validation inline as you type — with the exact CLI error strings, so the terminal, CI and the editor all speak identically. One renderer: the browser shows SVG produced server-side by the same pipeline as graphspec render; the editor is a view, never a second layout implementation. Without Graphviz it degrades honestly: DOT preview plus fully live validation.

Three interactions you won't find in a generic YAML editor:

  1. Bidirectional linking — click a node to jump to its YAML; move the cursor to halo the element in the canvas; hover an edge for its when/max/counter.
  2. The data-flow lens — select any state field: writers, readers and optional readers get distinct outlines, and every path along which a required reader would receive the field unwritten is tinted red — E-READ-UNSET, made visible before any model runs.
  3. Trace overlay — drop an OTLP JSON export on the canvas: cost-proportional fills, ×N repeat badges, the stopped node highlighted, a per-node cost table, drift surfaced.

Local-first by design: binds to 127.0.0.1 only, every asset vendored, zero external requests, no telemetry. Works on a plane.

Status

v1.0.0. The v1.0-book tag freezes the state the first edition of Graph Engineering describes; the format version is graphspec: 1. Built milestone by milestone: v0.1.0 model + validator, v0.2.0 render, v0.3.0 trace, v0.4.0 scaffold + diff + CI, v1.0.0 the serve editor.

License

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphspec-1.0.0.tar.gz (82.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

graphspec-1.0.0-py3-none-any.whl (70.9 kB view details)

Uploaded Python 3

File details

Details for the file graphspec-1.0.0.tar.gz.

File metadata

  • Download URL: graphspec-1.0.0.tar.gz
  • Upload date:
  • Size: 82.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.1 {"installer":{"name":"uv","version":"0.10.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for graphspec-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f83a6b8a0321b044421aedaaf277b930d43819b2457acdcacb66db8985557908
MD5 80d3388639b26570eecd96471868f535
BLAKE2b-256 c5dd62ffda07d65f24fb899ecb48e0d33bc45a63c42f0f8fc22330290bdc5422

See more details on using hashes here.

File details

Details for the file graphspec-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: graphspec-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 70.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.1 {"installer":{"name":"uv","version":"0.10.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for graphspec-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1fd505c910a6ca602dc7b417f728fba9129083c93f086725fa6ef6a80df207d5
MD5 49db71f5a473dcca6b6e922b96d92e96
BLAKE2b-256 493c7e9fa72632780b57ff187f0f153ada8e353908a3e8dcd2c574c93e656351

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page