# Graphs and nodes

> A graph is nodes plus connections. A node is one typed unit of work with input and output pins. Everything Kaitoi runs is a graph, including the things that do not look like one.

Source: https://kaitoi.io/docs/concepts/graphs-and-nodes/
Section: Concepts
Written for: Anyone who needs to read, build or modify a Kaitoi graph.
Last reviewed: 2026-09-16

---

A graph is a set of nodes and the connections between them. A node is one unit
of work with typed inputs and typed outputs. A connection carries a value from
one node's output pin to another node's input pin.

That is the entire structure. The interesting part is what a node can be.

## A node is not only a model call

It is tempting to read a node as "one call to one AI model", because that is the
most visible case. It is narrower than the truth. A node can be a model call, a
piece of code, a call out to an external service, a file operation, a piece of
domain tooling, or a small application with its own interface.

This is what makes a graph worth having rather than a script. The same structure
holds the generative step and the deterministic step around it, so the part that
has to be exact stays exact while the part that should vary is free to vary.

## Pins

Each node type declares what it accepts and what it produces. Those declarations
are its pins.

- An **input pin** can take a connection from another node, or a value set
  directly on the node, or be left at its default.
- An **output pin** produces a value other nodes can consume.

Pins are typed. A connection between incompatible pins is rejected at validation
time rather than at run time, which is the difference between a clear error and
a run that fails halfway through having already spent money.

## Discovering what exists

The node catalogue is large and it changes, so nothing good comes of
hard-coding a list of node types. Discover them instead.

```bash
curl -s "https://api.studio.kaitoi.io/api/v1/node-types?search=upscale&limit=10" \
  -H "Authorization: Bearer $KAITOI_API_KEY"
```

`search` runs over type, title, category, description and tags. `limit` defaults
to 50 and is capped at 200. Results are paginated with an opaque cursor.

Once you have a candidate, read its schema to see the exact pins:

```bash
curl -s "https://api.studio.kaitoi.io/api/v1/node-types/$NODE_TYPE" \
  -H "Authorization: Bearer $KAITOI_API_KEY"
```

The response gives you the node's public schema, including its exposed input and
output pins. That is what you need before you can connect it to anything or
override its inputs on a run.

Both endpoints return only the node types available to the account the key
belongs to, so a key belonging to an account with custom nodes will see more
than a key that does not.

## Two ways to get a graph

You do not have to save a project to run a graph.

- **A saved project graph** lives in a project, persists, and can be opened in
  Kaitoi Studio.
- **An inline graph** is sent in the body of a run request, executed, and not
  persisted as a project.

Inline graphs suit request-shaped work: a fixed pipeline your backend invokes
with different inputs each time, where there is no user-facing canvas and
nothing to keep. Saved projects suit work someone will come back to.

The inline shape is deliberately small. A node needs an `id` and a `type`.
Everything else, including `inputs`, `title` and `position`, is optional.

Each input value is a typed pin object rather than a bare value. The input names
come from the node type's schema, and the types are `string`, `number`,
`boolean`, `json`, `file` and `null`.

```json
{
  "nodes": [
    {
      "id": "a",
      "type": "<node type from the catalogue>",
      "inputs": { "inputText": { "type": "string", "value": "a cat" } }
    }
  ],
  "connections": []
}
```

## Current limitations

- Node type paths are validated before lookup, so a user-node path cannot
  traverse storage boundaries. A malformed type is rejected rather than
  resolved.
- Thumbnails returned by the node type endpoints are short-lived signed URLs.
  The token in the URL authorizes that thumbnail only. Do not send your API key
  to it.
