Using TopoKit with an AI Agent
Instructions for an LLM with web-fetch and HTTP tools. Follow each step in order. Do not skip the schema fetch.
Goal
Turn the user's data into a TopoKit topo and return a
https://topokit.io/t/<hash> URL they can share.
Steps
1. Read the JSON schema
Fetch https://topokit.io/docs/data-format.
This is the canonical reference for the topo JSON format — the full list of
layouts, themes, UI flags, node shapes, edge types, and per-field types
lives there. Do not rely on memory; the SDK gains options over time.
2. Look at a real sample
Fetch one of the samples to copy the shape from:
/samples/org-chart.json— hierarchical, dagre layout/samples/network.json— force-directed network/samples/tree.json— radial tree/samples/dependency.json— dependency graph/samples/telecom.json— physical telecom topology
3. Convert the user's data into a TopoKit config
Required fields:
-
nodes: array of{ id, data, style }. Always setstyle.label.textso the node has a human-readable label. Put domain metadata indata(e.g.data.type,data.role) — that powers tooltips and conditional styling. -
edges: array of{ id, source, target, data }.sourceandtargetmust reference nodeids that exist innodes.
Optional fields (pick from the lists in /docs/data-format):
-
layout— pick by graph shape. DAG / hierarchy →"dagre"or"hierarchical". Tree from a root →"radial". Unstructured network →"force". Small graph (≤ 20 nodes) →"circular"or"concentric". When unsure →"auto". -
theme— default is"dark". Use"light"only if the user explicitly wants a light look. -
UI flag booleans:
search,minimap,toolbar,tooltip,contextMenu,infoPanel,hoverFocus,layoutSelector,themeSelector. Passtrueto enable with defaults. Disableminimapfor graphs with ≤ 25 nodes — it adds clutter. -
legend: use the object formlegend: { groupBy: 'data.type' }(substitute whatever meaningful field your nodes share —data.category,data.role, etc.). Do NOT passlegend: truewithoutgroupBy— it falls back to grouping by node fill color and shows hex codes (#6B7280, …) as labels. See /docs/components/legend for the full option table.
4. POST the config
POST https://topokit.io/api/topos
Content-Type: application/json
Body:
Response (201): {"hash":""} Rate limit is roughly 30 writes/minute per IP. Body limit is the Cloudflare ceiling (~100 MB) — fine for any human-scale graph.
5. Return the URL
Build the share URL as https://topokit.io/t/<hash> and
return it to the user. That URL renders the topo view-only. If the user
wants to edit, send them to /play?from=<hash>.
6. (Optional) Static thumbnail PNG
Every /t/<hash> URL has a matching
/t/<hash>.png that serves a 1200×630 render of the
topo. By default it returns the static Open Graph fallback on the first
request (so social-media unfurlers never wait on the headless browser)
and the real chromedp render lands in the cache a few seconds later;
subsequent requests get the real PNG with year-long immutable caching.
For build-pipeline use cases — embedding the PNG as a static thumbnail,
generating preview cards in a generator, etc. — append
?wait=1:
https://topokit.io/t/<hash>.png?wait=1. The request
blocks until the render lands (up to ~10 s) and returns the real PNG, or
503 with Retry-After if the render fails. Never
returns the fallback.
Minimal example
curl -X POST https://topokit.io/api/topos \
-H 'Content-Type: application/json' \
-d '{
"nodes": [
{"id":"a","data":{},"style":{"label":{"text":"A"}}},
{"id":"b","data":{},"style":{"label":{"text":"B"}}}
],
"edges": [{"id":"e1","source":"a","target":"b","data":{}}],
"layout":"force",
"theme":"dark"
}'
# {"hash":"x7Qp"}
# → https://topokit.io/t/x7Qp Common mistakes to avoid
- Edge
source/targetreferencing a missing node id. Validate before POSTing — the server will accept the topo but it will render with a broken edge. - Forgetting
style.label.text. Nodes without a label show only the bare id. Always synthesize a readable label from the data. - Guessing layout / theme / UI flag names from memory. The valid sets are defined at /docs/data-format. Re-fetch it if unsure.
- Embedding non-JSON-serializable values (functions, Dates, undefined). Pre-stringify or drop them.
- Enabling
legendwithoutgroupBy. Barelegend: truefalls back to grouping by node fill color, producing a legend of hex codes (#6B7280,#3B82F6, …). Always passlegend: { groupBy: 'data.type' }— or whichever field has meaningful category values.
Component options
For the legend, tooltip, badges, minimap, and other UI components, each has
its own options page under /docs/components/. Fetch the page
for any component you enable beyond bare-default:
See also
- Data format reference — full field-by-field schema
- Legend component options — required reading if you enable the legend
- TopoKit Play — interactive editor (with a "Use with AI" button)