Skip to content

SDK Code Generation

Ironflow uses a manifest-based code generation pipeline to produce SDK clients in multiple languages from a single source of truth: the server’s registered HTTP routes.

server.go (route registration)
|
v
GET /api/v1/routes → sdk-manifest.json
|
v
cmd/sdk-gen (Go template engine)
|
+---> Go client (107 methods, all non-internal REST endpoints)
+---> Node client (107 methods)
+---> Browser client (67 methods, no server-only or enterprise-only endpoints)
+---> Python client (107 methods)

The server exposes all registered routes via GET /api/v1/routes with metadata:

  • method: HTTP verb (GET, POST, PUT, PATCH, DELETE)
  • path: URL pattern with path parameters (e.g., /api/v1/runs/{id})
  • category: supported, server-only, enterprise-only, or internal
  • group: logical grouping (events, runs, projections, kv, etc.)

Full pipeline (extract manifest + generate all SDKs)

Section titled “Full pipeline (extract manifest + generate all SDKs)”
Terminal window
make sdk-manifest # Start server, extract routes, write sdk-manifest.json
make sdk-gen # Generate Go + TypeScript + Python clients from manifest
Terminal window
make sdk-gen-go # Go → sdk/go/ironflow/gen/
make sdk-gen-ts # TypeScript (Node) → sdk/js/node/src/gen/
make sdk-gen-browser # TypeScript (Browser, supported-only) → sdk/js/browser/src/gen/
make sdk-gen-python # Python → sdk/python/ironflow/
Terminal window
make sdk-gen-test-stubs # Generate per-method test stubs for Go + TS
make sdk-health # Coverage report → sdk-health.json

Run make sdk-manifest && make sdk-gen whenever:

  • A new HTTP route is added to internal/server/server.go
  • A route’s method, path, or middleware changes
  • A new ConnectRPC service is registered

The CI sdk-freshness job will catch drift if you forget.

Terminal window
make sdk-gen-check # Starts server, compares routes against manifest

This compares the live server’s route table against sdk-manifest.json. If they differ, it prints the diff and exits non-zero.

To see what changed between two manifest snapshots (e.g., between releases):

Terminal window
# Save current manifest before changes
cp sdk-manifest.json sdk-manifest-before.json
# Make changes, regenerate
make sdk-manifest
# See what changed
make sdk-changelog OLD=sdk-manifest-before.json NEW=sdk-manifest.json

Output:

SDK Changelog
═══════════════════════════════════════════
Old: sdk-manifest-before.json (180 routes)
New: sdk-manifest.json (183 routes)
Summary: +3 added, -0 removed
Added endpoints:
+ POST /api/v1/workflows (workflows, supported)
+ GET /api/v1/workflows (workflows, supported)
+ GET /api/v1/workflows/{id} (workflows, supported)

To add SDK generation for a new language (e.g., C#, Rust):

  1. Add a new template in cmd/sdk-gen/main.go
  2. Add a generate{Lang}() function following the Go/TS/Python patterns
  3. Add the language case to the switch in main()
  4. Add a make sdk-gen-{lang} target to the Makefile
  5. Test that the generated code compiles in the target language

The buildGroups() function handles filtering, grouping, and deduplication — it’s shared across all languages. You only need to write the template.

CategoryIncluded inDescription
supportedGo, Node, Browser, PythonPublic API, all SDKs should support
server-onlyGo, Node, PythonRequires server-side execution (secrets, users, workers)
enterprise-onlyGo, Node, PythonEnterprise features (orgs, roles, tenants, policies)
internalNoneInfrastructure endpoints (health, debug, auth login)

The Browser SDK excludes both server-only and enterprise-only endpoints for security (untrusted runtime).

The generation pipeline has no external dependencies:

  • Manifest extraction: curl against the running server
  • Code generation: Go text/template engine (cmd/sdk-gen)
  • No vendor tools: no Fern, Speakeasy, or Stainless dependency

See _internal/designs/multi-sdk-management.md for the full strategy and design decisions.