Skip to main content

Custom Node Development

FluidGrids nodes are self-contained microservices. Each node lives under nodes/<node>/<version>/ in the fluidgrids-nodes repository and exposes a small GraphQL API that the workflow engine invokes during a run. This guide covers creating, testing, and deploying one.

There is no @fluidgrids/node-sdk package and no defineNode() helper — a node is a directory of files, not a compiled bundle. The canonical reference is nodes/gmail_node/1.0.0; copy its structure for every new node. The full contract is documented in docs/node-standard.md.

Node Architecture

A FluidGrids node consists of:

  • manifest.json — the contract: node identity (nodeType, nodeVersion, publishType, endpointUrl, healthCheckUrl, category, icon) plus the full operations[] list
  • GraphQL SDL (<domain>_sdl.gql) — one field per operation
  • Ariadne resolvers (<domain>_gql.py) — binds every SDL field
  • Handlers (<domain>_actions_ops.py) — the code that runs when an operation executes, wrapped in a FastAPI app (server.py + router.py)
  • A per-operation configuration panel — an AdaptiveCard 1.5 adaptive_card declared on each operation, which the builder renders as that operation's property panel
  • Error handling — resolvers never raise; every result type carries an error: String field

Integration nodes are Python (FastAPI + Ariadne); a handful of platform nodes use Bun/TypeScript but keep the same contract (manifest shape, GraphQL signature, health endpoint, port, network, per-execution credential injection).

Development Process

Setup

# Clone the nodes repo
git clone https://github.com/algoshred/fluidgrids-nodes.git
cd fluidgrids-nodes

Scaffold the node

Create nodes/<node>/<version>/ and copy the file set from the reference node nodes/gmail_node/1.0.0/:

nodes/my_node/1.0.0/
├── manifest.json # the contract: identity + operations[]
├── my_node_sdl.gql # GraphQL SDL — one field per operation
├── my_node_gql.py # Ariadne resolvers
├── my_node_actions_ops.py # handlers — the real work
├── server.py # FastAPI app: /graphql + /api/v1/health
├── router.py # REST /health route
├── config.py # Pydantic Settings from .env (PROJECT_NAME, APP_PORT, ...)
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── .env

Each operation in manifest.json must be backed by an SDL field, a resolver, and a handler — no manifest-only operations. Every operation also carries an adaptive_card (AdaptiveCard 1.5) that becomes its configuration panel in the builder, and a credentialAdapters list so the engine can inject credentials per execution. Credentials are never stored in the node.

Run and test locally

Each node ships its own docker-compose.yml. Bring the container up from the node directory — it hot-reloads your source and joins the shared external nodenetwork:

cd nodes/my_node/1.0.0
docker compose up -d

# Health check
curl localhost:<APP_PORT>/api/v1/health

# GraphQL playground
open http://localhost:<APP_PORT>/graphql

APP_PORT is unique per node (Gmail uses 6501) and set in the node's .env. The nodenetwork is created by another compose stack; if it does not exist yet, create it with docker network create nodenetwork.

Register the node locally

Re-seed the local node registry so the builder can see your node. seed-nodes.ts reads every manifest.json in the repo and upserts it into the local registry database:

cd fluidgrids-nodes
bun scripts/seed-nodes.ts

Reload the builder and your node appears in the palette.

Deploying a node

Deployment is a container image plus a registry entry — there is no web-app upload and no fluidgrids nodes publish command.

  1. Build the image. scripts/build-node-image.sh reads the node's manifest.json and tags the image by the convention the workers' sandbox mode expects (${NODE_IMAGE_REGISTRY_PREFIX}/${nodeType}:${version}):

    # Build locally
    scripts/build-node-image.sh my_node 1.0.0

    # Build and push to the registry
    # <registry-host> = your environment's container registry (see the fluidgrids-nodes repo)
    NODE_IMAGE_REGISTRY_PREFIX=<registry-host>/fluidgrids-nodes \
    scripts/build-node-image.sh my_node 1.0.0 --push
  2. Seed the registry. Run scripts/seed-nodes.ts against the target environment's registry so the manifest is registered. In alpha and production this flows through the standard node deploy pipeline (per-node images built and published via .github/workflows/build-node-images.yml, then registry seeding).

Browsing the catalog

The CLI can browse the node catalog but does not deploy nodes:

fluidgrids nodes list          # list available nodes
fluidgrids nodes get <type> # inspect a node's manifest

Next steps