- SDK Reference
- SDK Comparison
SDK Comparison
This page records what each Ironflow SDK can do — use it to pick an SDK, or to check whether a capability you need is reachable from the one you already have. For the exhaustive per-capability view — every transport, test and documentation status, and gap classification — see the SDK Parity Matrix.
The tables record capabilities, not transport. An SDK may reach a capability over ConnectRPC or a WebSocket instead of the equivalent REST path: the Go SDK resumes a run over ConnectRPC, the Browser SDK watches config over a WebSocket topic. ✅ means you can do it, ❌ means you cannot, and N/A means it is deliberately excluded — as secrets are from the browser. The Agents table reads by a narrower rule, stated above it.
The four SDKs
Section titled “The four SDKs”| SDK | Package | Tier | What it is |
|---|---|---|---|
| Go | github.com/sahina/ironflow-go/ironflow | 1 | Worker runtime + client, for servers and workers |
| Node | @ironflow/node | 1 | Worker runtime + client, for servers, workers and handlers |
| Browser | @ironflow/browser | — | Outside the tiers: hand-written like Tier 1 (it shares @ironflow/core with Node), client-only like Tier 2, plus real-time subscriptions |
| Python | ironflow (distribution ironflow-py on PyPI) | 2 | Generated REST + ConnectRPC clients, no worker runtime |
SDK Tiers
Section titled “SDK Tiers”The dividing line between the tiers is which direction the call goes.
Tier 1 — worker runtime + client (Go, Node)
Section titled “Tier 1 — worker runtime + client (Go, Node)”Tier-1 SDKs carry the worker runtime: the engine that runs your function code
under Ironflow’s control — durable-step memoization, crash-resume replay,
step.sleep / waitForEvent suspension, saga compensation, and pull mode
(long-running workers, no timeout). The client methods are fused to that runtime,
so a Tier-1 SDK is hand-written end to end and never generated.
Go and TypeScript are the only Tier-1 languages, and that limit is deliberate. No additional Tier-1 languages are planned.
The two Tier-1 SDKs are peers. A capability added to one is incomplete until the other has it. The two implementations do not need to land in the same commit or release. If one ships first, its peer gap must be filed before the release notes are published and those notes must link it. This also applies when a Tier-2 SDK reaches a capability before either Tier-1 SDK. The release may proceed, but the missing Tier-1 work cannot remain implicit.
scripts/check-tier1-sdk-parity.py enforces this mechanically for the public
fields of SubscribeOptions, the option type that exposed the first concrete
drift. An unmatched field fails unless tier1-sdk-parity.json names the missing
SDK and links its implementation issue. The check also rejects an exception
after the field reaches both SDKs. This is intentionally narrow.
sdk-coverage.json records which routes SDK source calls, not which capabilities
or options the SDK exposes, so it is not evidence of Tier-1 capability parity.
Broader parity remains a review rule until another concrete case supports a
reliable source-level check.
Published blog posts, tutorials, and how-to guides follow the same peer model. When material demonstrates a Tier-1 capability with code, it includes both Go and TypeScript examples. Browser-only and Tier-2 capabilities are exempt. This is an editorial review rule rather than a code-fence-counting gate, because a document may also contain SQL, shell, frontend, or transport-specific examples. The existing blog posts that teach Tier-1 worker capabilities have been backfilled; new material follows this rule from its first publication.
Tier 2 — generated client only (Python today; Rust, C#, Java later)
Section titled “Tier 2 — generated client only (Python today; Rust, C#, Java later)”Tier-2 SDKs call the Ironflow REST API and its ConnectRPC surface, and contain no worker runtime. Each is built in two parts: a generated surface, machine-generated from the server’s REST API so the client tracks it as the API changes, and a small hand-written transport core supplying retry, backoff, auth, and the error taxonomy.
A Tier-2 SDK is a smaller SDK, not a lesser one. Applications in Tier-2 languages still get their functions executed by Ironflow via push mode: the server POSTs to an HTTP endpoint you own, which needs no SDK runtime at all. What Tier 2 does not get is pull mode and durable steps — workflows that need crash-resume, long sleeps, or sagas are written in Go or TypeScript.
The same REST surface is published as an OpenAPI 3.1 spec at
GET /api/v1/openapi.json, so a language with no SDK starts from a
machine-readable contract rather than from scratch.
Two protocols, and why Tier 2 only reaches one
Section titled “Two protocols, and why Tier 2 only reaches one”The server speaks two protocols to clients:
- REST — plain HTTP paths under
/api/v1, published with a machine-readable description and schemas for most of them. - ConnectRPC — a protobuf protocol. Paths look like
POST /ironflow.v1.WebhookService/CreateSource. These sit outside the REST contract and carry no schema in it.
The client generator reads the REST description only, so a Tier-2 client holds REST methods only. Tier-1 SDKs are unaffected: they are hand-written and call whichever protocol fits. Run resume and step patch now use ConnectRPC in all SDKs. Their duplicate REST routes have been removed (#1972).
The generated REST client covers the remaining REST routes, including environment CRUD, event reads, secrets, and projection deletion and partition listing.
The migrated capabilities are delivered by IronflowRPC — 90 capability methods generated
from the protobuf definitions (86 unary, 4 server streams), covering webhook
management, agent tools, time travel, pub/sub consumer groups, function
versioning, executable deployments, raw SQL, and the environment compatibility
RPCs. The two clients are not
supersets of each other; each carries what its protocol serves.
One gap remains:
| Still out of reach | Why |
|---|---|
PubSubService/SubscribeBidirectional | Served, but the handler returns Unimplemented. Deliberately not exposed in any SDK |
IronflowRPC retries a unary call only when the protobuf method is annotated
idempotency_level = NO_SIDE_EFFECTS. It reconnects Subscribe when the caller
positions it with start_after_sequence, and no other stream — the rest are
positioned by the server on a durable consumer, so re-issuing the call resumes
them (#1848). Which of the 95 served RPCs the Python SDK exposes, and why, is
recorded row by row in sdk/python/rpc-capabilities.yaml.
No SDK at all
Section titled “No SDK at all”A language with no SDK is not locked out. It reaches almost everything in this
document over plain HTTP — the REST API under /api/v1, plus the ironflow CLI
and the MCP server (ironflow mcp) as no-codegen alternatives. But “generate a
client from the OpenAPI spec and you are done” is not true, for the same reason
Tier 2 needs two pipelines: the spec describes REST only.
Some ✅ rows above have no REST route at all. They are ConnectRPC, so a
client generated from api/openapi.json will not contain them:
| Capability | ConnectRPC method | What REST gives you |
|---|---|---|
| Register functions | IronflowService/RegisterFunction | No REST sibling |
| Create projection | ProjectionService/RegisterProjection, CreateSQLProjection | Deletion and partition listing, but no create |
| TriggerSync (blocking) | IronflowService/TriggerSync | No REST sibling |
| Invoke one function and block | IronflowService/InvokeFunctionSync | No REST sibling. IronflowService/InvokeFunction returns IDs immediately; InvokeFunctionSync waits for the result (ADR 0067) |
| Webhook mutation (11 RPCs) | WebhookService/* | The redacted GET /api/v1/flow/webhooks view |
| Join a consumer group | PubSubService/JoinConsumerGroup | Nothing |
The unary ones cost you a second path shape, not a second toolchain: a Connect
unary call is an ordinary POST /ironflow.v1.Service/Method carrying proto3
JSON, which any HTTP client can send. What you give up is the schema — these sit
outside the REST contract, and the field names are camelCase where REST is
snake_case. Use Ironflow from any
language walks the
registration call end to end.
Registration being RPC-only has a knock-on effect: an OpenAPI-only client has
nothing to invoke until something else registers a function, and no scheduled
work either — a cron is a field on the function, so api/openapi.json contains
no cron at all.
Three carve-outs, not two. Durable Step Primitives and agent authoring run
inside a worker and have no equivalent outside one. The third is receiving
pushed events, and it is not a worker feature: PubSubService/Subscribe and
JoinConsumerGroup are server streams, SubscribeBidirectional returns
Unimplemented by design, and the OpenAPI artifact carries no streaming media
type — no text/event-stream, no WebSocket upgrade. The GET /ws and KV/config
/watch upgrades exist on the server and are documented in the REST API
reference, but they are absent from the generated spec, so
codegen never sees them. Inbound from generated code means push mode: an HTTP
endpoint you own, which the engine calls.
Events
Section titled “Events”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Emit events | ✅ | ✅ | ✅ | ✅ |
| Trigger workflows | ✅ | ✅ | ✅ | ✅ |
| TriggerSync (blocking) | ✅ | ✅ | ✅ | ✅ |
| Trigger a batch of events | ✅ | ✅ | ✅ | ✅ |
| List stored events | ✅ | ✅ | ✅ | ✅ |
| Get a stored event | ✅ | ✅ | ✅ | ✅ |
| List event names | ✅ | ✅ | ✅ | ✅ |
| Offline write queue (durable outbox) | N/A | N/A | ✅ | N/A |
Functions
Section titled “Functions”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Define functions | ✅ | ✅ | N/A | ❌ |
| Register functions | ✅ | ✅ | N/A | ✅ |
| List functions | ✅ | ✅ | ✅ | ✅ |
| Get function detail | ✅ | ✅ | ✅ | ✅ |
| Enable or disable function | ✅ | ✅ | ✅ | ✅ |
| Delete function | ✅ | ✅ | ✅ | ✅ |
| List function version history | ✅ | ✅ | ✅ | ✅ |
| Get function at version | ✅ | ✅ | ✅ | ✅ |
| Roll back function version | ✅ | ✅ | ✅ | ✅ |
| Invoke function directly | ✅ | ✅ | ✅ | ✅ |
“Invoke function directly” is the client-level call, keyed by function id:
InvokeSync in Go, invoke() in Node and the browser,
rpc.functions.invoke or rpc.runs.invoke_function_sync in Python. All
four block for a result except the Python REST call, which answers with a
run_id you poll — see ADR 0067. It is a different thing from step.invoke / step.invokeAsync, which
invoke a function from inside a workflow and memoize — see Durable Step
Primitives below.
Durable Step Primitives (Tier 1)
Section titled “Durable Step Primitives (Tier 1)”These run inside a function handler, under Ironflow’s control. They are the worker runtime, so only Tier-1 SDKs have them.
| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
Memoized step (step.run) | ✅ | ✅ | N/A | ❌ |
| Sleep / sleep-until | ✅ | ✅ | N/A | ❌ |
| Durable wait for event | ✅ | ✅ | N/A | ❌ |
| Parallel branches | ✅ | ✅ | N/A | ❌ |
| Map over items | ✅ | ✅ | N/A | ❌ |
| Saga compensation | ✅ | ✅ | N/A | ❌ |
| Branch-scoped steps (nested fan-out, invoke, publish inside a branch) | ✅ | ✅ | N/A | ❌ |
| Invoke another function (sync / async) | ✅ | ✅ | N/A | ❌ |
| Publish to a topic from a step | ✅ | ✅ | N/A | ❌ |
| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Get run details | ✅ | ✅ | ✅ | ✅ |
| List runs | ✅ | ✅ | ✅ | ✅ |
| Get run steps | ✅ | ✅ | ✅ | ✅ |
| Get entity streams touched by a run | ✅ | ✅ | ✅ | ✅ |
| Cancel run | ✅ | ✅ | ✅ | ✅ |
| Resume run | ✅ | ✅ | ✅ | ✅ |
| Get audit trail (run events) | ✅ | ✅ | ✅ | ✅ |
Scoped Injection (Hot Patching & History Editing)
Section titled “Scoped Injection (Hot Patching & History Editing)”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Pause run | ✅ | ✅ | ✅ | ✅ |
| Get paused state | ✅ | ✅ | ✅ | ✅ |
| Inject step output | ✅ | ✅ | ✅ | ✅ |
| Patch step (modify outputs) | ✅ | ✅ | ✅ | ✅ |
The Python entry is rpc.runs.patch_step(PatchStepRequest(...)).
Time Travel Debugging
Section titled “Time Travel Debugging”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Get run state at timestamp | ✅ | ✅ | ✅ | ✅ |
| Get run timeline | ✅ | ✅ | ✅ | ✅ |
| Get step output at timestamp | ✅ | ✅ | ✅ | ✅ |
Entity Streams (Event Sourcing)
Section titled “Entity Streams (Event Sourcing)”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Append event to stream | ✅ | ✅ | ✅ | ✅ |
| Read stream events | ✅ | ✅ | ✅ | ✅ |
| Get stream info | ✅ | ✅ | ✅ | ✅ |
| Create snapshot | ✅ | ✅ | ✅ | ✅ |
| Get snapshot | ✅ | ✅ | ✅ | ✅ |
| List all streams | ✅ | ✅ | ✅ | ✅ |
| Get entity event history | ✅ | ✅ | ✅ | ✅ |
Projections
Section titled “Projections”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| List projections | ✅ | ✅ | ✅ | ✅ |
| Get projection | ✅ | ✅ | ✅ | ✅ |
| Get projection status | ✅ | ✅ | ✅ | ✅ |
| List projection partitions | ✅ | ✅ | N/A | ✅ |
| Create projection | ✅ | ✅ | N/A | ✅ |
| Rebuild projection | ✅ | ✅ | N/A | ✅ |
| Get rebuild job status | ✅ | ✅ | N/A | ✅ |
| Create SQL projection | N/A | ✅ | N/A | ✅ |
| Query SQL projection | N/A | ✅ | ✅ | ✅ |
| Execute raw SQL | ✅ | N/A | ❌ | ✅ |
| Pause projection | ✅ | ✅ | N/A | ✅ |
| Resume projection | ✅ | ✅ | N/A | ✅ |
| Cancel rebuild | ✅ | ✅ | N/A | ✅ |
| Delete projection | ✅ | ✅ | N/A | ✅ |
| Wait for catch-up (read-your-writes) | ✅ | ✅ | ✅ | ✅ |
Pub/Sub (Developer Topics)
Section titled “Pub/Sub (Developer Topics)”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Publish to topic | ✅ | ✅ | ✅ | ✅ |
| List topics | ✅ | ✅ | N/A | ✅ |
| Get topic statistics | ✅ | ✅ | N/A | ✅ |
| Join a consumer group (subscribe with acks) | ✅ | ✅ | ✅ | ✅ |
| Manage consumer groups (create/get/list/update/delete) | ✅ | ✅ | ✅ | ✅ |
KV Store (Key-Value Storage)
Section titled “KV Store (Key-Value Storage)”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Create bucket | ✅ | ✅ | ✅ | ✅ |
| List buckets | ✅ | ✅ | ✅ | ✅ |
| Get bucket | ✅ | ✅ | ✅ | ✅ |
| Delete bucket | ✅ | ✅ | ✅ | ✅ |
| Get key | ✅ | ✅ | ✅ | ✅ |
| Put key | ✅ | ✅ | ✅ | ✅ |
| Create key (fails if present) | ✅ | ✅ | ✅ | ✅ |
| Update key (compare-and-set) | ✅ | ✅ | ✅ | ✅ |
| Delete key | ✅ | ✅ | ✅ | ✅ |
| Purge key (drop history) | ✅ | ✅ | ✅ | ✅ |
| List keys | ✅ | ✅ | ✅ | ✅ |
| Watch keys | ✅ | ✅ | ✅ | ❌ |
Exclusive create and compare-and-set both ride on conditional request headers.
The generated Python kv_update_buckets_keys() method exposes them as
if_none_match and if_match keyword arguments.
Config Management
Section titled “Config Management”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Get config (read) | ✅ | ✅ | ✅ | ✅ |
| List configs | ✅ | ✅ | ✅ | ✅ |
| Set config (full replacement) | ✅ | ✅ | N/A | ✅ |
| Patch config (shallow merge) | ✅ | ✅ | N/A | ✅ |
| Delete config | ✅ | ✅ | N/A | ✅ |
| Watch config (real-time) | ✅ | ✅ | ✅ | ❌ |
Secrets Management
Section titled “Secrets Management”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Get secret | ✅ | ✅ | N/A | ✅ |
| Set secret | ✅ | ✅ | N/A | ✅ |
| Replace secret value | ✅ | ✅ | N/A | ✅ |
| Patch secret name or description | ✅ | ✅ | N/A | ✅ |
| Delete secret | ✅ | ✅ | N/A | ✅ |
| List secrets | ✅ | ✅ | N/A | ✅ |
Event Schema Registry
Section titled “Event Schema Registry”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Register schema | ✅ | ✅ | ✅ | ✅ |
| List schemas | ✅ | ✅ | ✅ | ✅ |
| Get schema (latest) | ✅ | ✅ | ✅ | ✅ |
| Get schema version | ✅ | ✅ | ✅ | ✅ |
| Delete schema version | ✅ | ✅ | ✅ | ✅ |
| Test upcast | ✅ | ✅ | ✅ | ✅ |
Agents
Section titled “Agents”Authoring an agent is worker-runtime work, so it is Tier-1 only. The Browser SDK carries the client half — start a run, follow it, read its memory.
This table is the one place that records named SDK helpers rather than raw reachability. An agent’s memory is an ordinary entity stream behind an ordinary projection, and an agent run starts from an ordinary event, so any client that can append an event, read a projection, or emit can do those three things by hand. For the Python column, ❌ on the memory and agent-invoke rows means the SDK ships no method named for the agent use of them — not that the data is out of reach. The note under the table says the same thing about Go and Node for the last two rows.
| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Define an agent handler | ✅ | ✅ | N/A | ❌ |
| Define a tool | ✅ | ✅ | N/A | ❌ |
| Human approval gate | ✅ | ✅ | N/A | ❌ |
| LLM call wrapper | ✅ | ✅ | N/A | ❌ |
| Spawn a sub-agent | ✅ | ✅ | N/A | ❌ |
| Expose tools over MCP | ✅ | ✅ | N/A | ❌ |
| Write agent memory | ✅ | ✅ | ❌ | ❌ |
| Read agent memory | ✅ | ✅ | ✅ | ❌ |
| Invoke an agent from a client | ❌ | ❌ | ✅ | ❌ |
| Subscribe to agent run events | ❌ | ❌ | ✅ | ❌ |
| List visible agent tools | ✅ | ✅ | N/A | ✅ |
The last two rows are a client convenience the Browser SDK has and the others do not. From Go or Node you start an agent by emitting its trigger event, and follow it with an ordinary run subscription.
Webhooks
Section titled “Webhooks”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Create webhook source | ✅ | ✅ | ✅ | ✅ |
| Get webhook source | ✅ | ✅ | ✅ | ✅ |
| List webhook sources | ✅ | ✅ | ✅ | ✅ |
| Update webhook source | ✅ | ✅ | ✅ | ✅ |
| Delete webhook source | ✅ | ✅ | ✅ | ✅ |
| Rotate verify secret | ✅ | ✅ | ✅ | ✅ |
| Expire previous secret | ✅ | ✅ | ✅ | ✅ |
| Disable signature verification | ✅ | ✅ | ✅ | ✅ |
| Rotate ingest token | ✅ | ✅ | ✅ | ✅ |
| Test verify config | ❌ | ❌ | ❌ | ✅ |
| List webhook deliveries | ✅ | ✅ | ✅ | ✅ |
Webhook mutation is ConnectRPC-only. Python reaches all of it through
rpc.webhooks — create_source, get_source, rotate_secret and the rest —
which is the capability IronflowRPC was added for. IronflowClient still sees
only the redacted flow-map view (names, prefixes, delivery counts).
Test verify config is a Dashboard-facing diagnostic. Python wraps it because the generated facade covers every WebhookService method; Go, Node and Browser have no wrapper for it.
API Keys
Section titled “API Keys”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Create API key | ✅ | ✅ | ✅ | ✅ |
| List API keys | ✅ | ✅ | ✅ | ✅ |
| Get API key | ✅ | ✅ | ✅ | ✅ |
| Delete API key | ✅ | ✅ | ✅ | ✅ |
| Rotate API key | ✅ | ✅ | ✅ | ✅ |
Organizations
Section titled “Organizations”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Create org | ✅ | ✅ | ✅ | ✅ |
| List orgs | ✅ | ✅ | ✅ | ✅ |
| Get org | ✅ | ✅ | ✅ | ✅ |
| Update org | ✅ | ✅ | ✅ | ✅ |
| Delete org | ✅ | ✅ | ✅ | ✅ |
Roles & Policies
Section titled “Roles & Policies”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Create role | ✅ | ✅ | ✅ | ✅ |
| List roles | ✅ | ✅ | ✅ | ✅ |
| Get role | ✅ | ✅ | ✅ | ✅ |
| Update role | ✅ | ✅ | ✅ | ✅ |
| Delete role | ✅ | ✅ | ✅ | ✅ |
| Assign policy to role | ✅ | ✅ | ✅ | ✅ |
| Remove policy from role | ✅ | ✅ | ✅ | ✅ |
| List policies assigned to role | ✅ | ✅ | ✅ | ✅ |
| Create policy | ✅ | ✅ | ✅ | ✅ |
| List policies | ✅ | ✅ | ✅ | ✅ |
| Get policy | ✅ | ✅ | ✅ | ✅ |
| Update policy | ✅ | ✅ | ✅ | ✅ |
| Delete policy | ✅ | ✅ | ✅ | ✅ |
Admin Management
Section titled “Admin Management”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Manage projects | ✅ | ✅ | N/A | ✅ |
| Manage environments | ✅ | ✅ | N/A | ✅ |
| Manage users | ✅ | ✅ | N/A | ✅ |
| Change own password | ✅ | ✅ | N/A | ✅ |
| List workers | ✅ | ✅ | ✅ | ✅ |
| List tenants | ✅ | ✅ | ✅ | ✅ |
| Provision tenant | ✅ | ✅ | ✅ | ✅ |
Operations
Section titled “Operations”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| List / requeue / discard outbox dead letters | N/A | N/A | N/A | ✅ |
| List circuit breakers, reset a breaker | N/A | N/A | N/A | ✅ |
| List / clear debounce entries | N/A | ❌ | N/A | ✅ |
| Inspect capacity (lanes, queue, leases, credits, sessions) | N/A | ❌ | N/A | ✅ |
| List / install policy templates | N/A | N/A | N/A | ✅ |
| Rotate the cluster join token | N/A | N/A | N/A | ✅ |
| Read the org-wide audit log | ✅ | ✅ | ✅ | ✅ |
The Tier-2 client remains widest here because its methods are generated from the
whole REST surface. Go, Node, and Browser expose the environment-wide audit log;
for the other operational routes, use the ironflow CLI or call REST directly.
Platform-tier administration — platform keys, tenant provisioning, impersonation — is a separate surface; see the Platform API reference.
Server Introspection
Section titled “Server Introspection”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Check liveness | ✅ | ✅ | ✅ | ✅ |
| Check readiness | ✅ | ✅ | ✅ | ✅ |
| Discover server capabilities | ✅ | ✅ | ✅ | ✅ |
Extended Administration
Section titled “Extended Administration”| Capability | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Dry-run a policy | N/A | N/A | N/A | ✅ |
| List policy versions and roll back | N/A | N/A | N/A | ✅ |
| Replace an API key’s roles | N/A | N/A | N/A | ✅ |
| Read authentication and authorization audit | N/A | N/A | N/A | ✅ |
These are intentionally outside the curated Go, Node, and Browser clients. They are not license-gated: the generated Python client reaches them because it covers the full REST and mounted ConnectRPC admin surface. Operators can also use the dashboard, CLI where available, or the underlying endpoint.
Execution Modes
Section titled “Execution Modes”| Feature | Go SDK | Node SDK | Browser SDK | Python SDK |
|---|---|---|---|---|
| Push mode (serverless functions) | ✅ | ✅ | N/A | ❌ |
| Pull mode (long-running workers) | ✅ | ✅ | N/A | ❌ |
| Subscriptions (real-time events) | ✅ | ✅ | ✅ | ✅ |
| WebSocket support | ✅ | ✅ | ✅ | ❌ |
| ConnectRPC support | ✅ | ✅ | ✅ | ✅ |
| HTTP/REST support | ✅ | ✅ | ✅ | ✅ |
Push mode ❌ for Python means the SDK has no handler runtime. A Python application still receives push invocations: the server POSTs to an HTTP endpoint you write yourself, which needs no SDK at all — see SDK Tiers.
Python real-time subscriptions use the tested
IronflowRPC.pubsub.subscribe() ConnectRPC server stream. Python still has no
WebSocket client and no agents.subscribe() convenience for following an agent
run, which are the narrower gaps recorded in those rows.
Recommendations
Section titled “Recommendations”Use Go SDK when:
Section titled “Use Go SDK when:”- Building high-performance backend services
- Implementing complex state machines or sagas
- Integrating with existing Go applications
- Need the broadest coverage of the workflow, event-sourcing and pub/sub surface
Use Node SDK when:
Section titled “Use Node SDK when:”- Building serverless functions (AWS Lambda, Vercel)
- Using JavaScript/TypeScript throughout your stack
- Need full control over step execution and error handling
- Prefer working in TypeScript for type safety
Use Browser SDK when:
Section titled “Use Browser SDK when:”- Building real-time frontends with live event subscriptions
- Implementing interactive dashboards or monitoring tools
- Need lightweight client-side integrations
- Want to display projection data and KV store values in UI
Use Python SDK when:
Section titled “Use Python SDK when:”- Building data pipelines or scripts that interact with Ironflow
- Integrating Ironflow with Python-based AI/ML workflows
- Running operational tasks — it is the only SDK that reaches the outbox DLQ, circuit breakers, and capacity views
- Want to manage Ironflow resources from Jupyter notebooks or CLI tools
Note: The Python SDK is Tier 2 — client API methods only, no worker runtime, by design (see SDK Tiers). For durable step execution, use the Go or Node SDK.
Feature Parity Status
Section titled “Feature Parity Status”Features are implemented incrementally, and these tables reflect the current state of each SDK.
The Python SDK is Tier 2 — generated client methods only, no worker runtime. It installs from PyPI as ironflow-py (import name ironflow) from v0.33.0. See the Python SDK reference for its full surface.