# Difference Between iii Python, TypeScript, and Rust SDKs: A Complete Guide

> Explore the iii Python, TypeScript, and Rust SDKs. Discover their unique type systems, error handling, and async patterns to choose the best fit for your project.

- Repository: [iii/iii](https://github.com/iii-hq/iii)
- Tags: comparison
- Published: 2026-05-28

---

**The iii platform provides three officially supported SDKs—Python, TypeScript, and Rust—that expose identical core functionality but differ in type systems, error handling, and async runtime patterns.**

The **iii** engine from the `iii-hq/iii` repository offers native SDKs for Python, TypeScript/JavaScript (Node and browser), and Rust. While all three SDKs communicate using the same WebSocket protocol defined in [`engine/src/protocol.rs`](https://github.com/iii-hq/iii/blob/main/engine/src/protocol.rs), each implementation is idiomatic to its host language. This guide breaks down the architectural distinctions, source file locations, and practical usage patterns to help you choose the right SDK for your stack.

## SDK Architecture and Language Paradigms

Each SDK wraps the engine's WebSocket protocol with language-specific ergonomics. The entry points and concurrency models reflect the distinct runtime characteristics of Python, TypeScript, and Rust.

### Python SDK

The **Python SDK** (`iii-sdk` on PyPI) targets CPython 3.10+ and relies on `asyncio` for concurrency. All network operations are coroutines that must be awaited, and payloads are handled as dynamic Python dictionaries converted to JSON at runtime. Error handling follows the Python convention of raising exceptions.

**Key source files:**
- Core API: [`sdk/packages/python/iii/src/iii/iii.py`](https://github.com/iii-hq/iii/blob/main/sdk/packages/python/iii/src/iii/iii.py)
- Registration helpers: `register_function` and `register_trigger` functions in [`iii.py`](https://github.com/iii-hq/iii/blob/main/iii.py)
- Observability: [`sdk/packages/python/iii/src/iii/log.py`](https://github.com/iii-hq/iii/blob/main/sdk/packages/python/iii/src/iii/log.py)

**Error model:** Raises `iii.errors.IIIError` (subclass of `Exception`).

### TypeScript SDK

The **TypeScript SDK** (`iii-sdk` on npm) supports Node 18+ and browsers via the `iii-browser-sdk` package. It uses standard JavaScript `Promise` objects with async/await syntax and provides strong compile-time typing through interfaces like `IIIRegisterFunction` and `IIITriggerConfig`. The SDK includes WebSocket auto-reconnect utilities for browser environments.

**Key source files:**
- Core API: [`sdk/packages/node/iii/src/iii.ts`](https://github.com/iii-hq/iii/blob/main/sdk/packages/node/iii/src/iii.ts)
- Registration: Re-exported via [`index.ts`](https://github.com/iii-hq/iii/blob/main/index.ts) with `registerFunction` and `registerTrigger`
- Logging: [`sdk/packages/node/iii/src/logger.ts`](https://github.com/iii-hq/iii/blob/main/sdk/packages/node/iii/src/logger.ts)

**Error model:** Returns `Promise<T>` that rejects on failure.

### Rust SDK

The **Rust SDK** (`iii-sdk` on crates.io) requires Rust 1.70+ and offers zero-cost abstractions with no runtime reflection. It uses strongly-typed builder structs like `RegisterFunction` for configuration and returns `Result<T, IIIError>` for error propagation. Optional feature flags (such as `observability` and `async-std`) control extra functionality.

**Key source files:**
- Public API: [`sdk/packages/rust/iii/src/lib.rs`](https://github.com/iii-hq/iii/blob/main/sdk/packages/rust/iii/src/lib.rs)
- Registration builders: [`src/register.rs`](https://github.com/iii-hq/iii/blob/main/src/register.rs) (e.g., `RegisterFunction`, `RegisterTrigger`)
- Logger: [`src/logger.rs`](https://github.com/iii-hq/iii/blob/main/src/logger.rs)

**Error model:** Explicit `Result<T, IIIError>` returns with `?` operator propagation.

## Side-by-Side Implementation Comparison

The following examples demonstrate registering an HTTP trigger that accepts a POST request at `/hello` and returns a greeting. Each snippet assumes the iii engine is running locally at `ws://localhost:8080`.

### Python Implementation

Install with: `pip install iii-sdk`

```python

# file: hello.py

import asyncio
import iii

async def greet(payload: dict) -> dict:
    name = payload.get("name", "world")
    await iii.log_info(f"Greeting {name}")
    return {"message": f"Hello, {name}!"}

async def main() -> None:
    await iii.register_function(
        function_id="hello::greet",
        handler=greet,
        description="Return a greeting",
    )
    await iii.register_trigger(
        type="http",
        function_id="hello::greet",
        config={"api_path": "/hello", "http_method": "POST"},
    )
    await asyncio.Event().wait()

if __name__ == "__main__":
    asyncio.run(main())

```

Source reference: The `register_function` and `register_trigger` coroutines are implemented in [`sdk/packages/python/iii/src/iii/iii.py`](https://github.com/iii-hq/iii/blob/main/sdk/packages/python/iii/src/iii/iii.py).

### TypeScript Implementation

Install with: `pnpm install iii-sdk` (or `iii-browser-sdk` for browser contexts)

```typescript
// file: hello.ts
import { iii } from "iii-sdk";

async function greet(payload: { name?: string }) {
  const name = payload.name ?? "world";
  await iii.logInfo(`Greeting ${name}`);
  return { message: `Hello, ${name}!` };
}

await iii.registerFunction({
  function_id: "hello::greet",
  handler: greet,
  description: "Return a greeting",
});

await iii.registerTrigger({
  type: "http",
  function_id: "hello::greet",
  config: { api_path: "/hello", http_method: "POST" },
});

await new Promise(() => {});

```

Source reference: Core registration logic resides in [`sdk/packages/node/iii/src/iii.ts`](https://github.com/iii-hq/iii/blob/main/sdk/packages/node/iii/src/iii.ts).

### Rust Implementation

Add with: `cargo add iii-sdk`

```rust
// file: hello.rs
use iii_sdk::{
    register::{RegisterFunction, RegisterTrigger},
    III,
    error::Result,
    types::HttpMethod,
};

#[iii::function]
async fn greet(payload: serde_json::Value) -> Result<serde_json::Value> {
    let name = payload
        .get("name")
        .and_then(|v| v.as_str())
        .unwrap_or("world");
    III::log_info(&format!("Greeting {}", name)).await?;
    Ok(serde_json::json!({ "message": format!("Hello, {}!", name) }))
}

#[tokio::main]
async fn main() -> Result<()> {
    III::register_function(
        RegisterFunction::new("hello::greet", greet)
            .description("Return a greeting"),
    )
    .await?;

    III::register_trigger(
        iii_sdk::trigger::HttpTrigger::new("/hello", HttpMethod::Post)
            .for_function("hello::greet"),
    )
    .await?;

    futures::future::pending::<()>().await;
    Ok(())
}

```

Source reference: The `RegisterFunction` and `RegisterTrigger` builders are defined in [`sdk/packages/rust/iii/src/register.rs`](https://github.com/iii-hq/iii/blob/main/sdk/packages/rust/iii/src/register.rs) and exposed through [`sdk/packages/rust/iii/src/lib.rs`](https://github.com/iii-hq/iii/blob/main/sdk/packages/rust/iii/src/lib.rs).

## Core Differences: Type Systems, Error Handling, and Async Models

While the underlying protocol remains identical across SDKs, the developer experience differs significantly in three key areas.

### Type Safety and Serialization

- **Python:** Uses dynamic typing with runtime dictionary validation. Payloads are plain Python `dict` objects serialized to JSON by the SDK.
- **TypeScript:** Provides compile-time structural typing via TypeScript interfaces (`IIIRegisterFunction`, `IIITriggerConfig`) with JSON serialization handled transparently.
- **Rust:** Enforces compile-time type safety using `serde_derive` for zero-cost serialization. The `iii::function` procedural macro generates boilerplate at compile time.

### Error Handling Patterns

- **Python SDK:** Propagates errors through exceptions. Callers wrap SDK calls in `try/except` blocks catching `iii.errors.IIIError`.
- **TypeScript SDK:** Returns rejected `Promise` objects on failure, allowing standard `.catch()` or `try/catch` with async/await.
- **Rust SDK:** Returns explicit `Result<T, IIIError>` types, requiring callers to handle errors via `match`, `if let`, or the `?` operator.

### Concurrency and Runtime

- **Python:** Built on `asyncio` event loops with coroutine-based concurrency.
- **TypeScript:** Uses the JavaScript event loop with `Promise` and async/await syntax. The browser SDK adds WebSocket connection management.
- **Rust:** Compatible with both `tokio` and `async-std` runtimes, offering true parallelism through OS threads combined with async tasks.

## File Structure and Source References

Understanding the layout of the `iii-hq/iii` repository helps when debugging or extending SDK functionality.

| SDK | Core Module | Registration Logic | Observability | Example Usage |
|-----|-------------|---------------------|---------------|---------------|
| **Python** | [`sdk/packages/python/iii/src/iii/iii.py`](https://github.com/iii-hq/iii/blob/main/sdk/packages/python/iii/src/iii/iii.py) | `register_function`, `register_trigger` functions in [`iii.py`](https://github.com/iii-hq/iii/blob/main/iii.py) | [`sdk/packages/python/iii/src/iii/log.py`](https://github.com/iii-hq/iii/blob/main/sdk/packages/python/iii/src/iii/log.py) | [`sdk/packages/python/iii-example/src/iii_function_example.py`](https://github.com/iii-hq/iii/blob/main/sdk/packages/python/iii-example/src/iii_function_example.py) |
| **TypeScript** | [`sdk/packages/node/iii/src/iii.ts`](https://github.com/iii-hq/iii/blob/main/sdk/packages/node/iii/src/iii.ts) | `registerFunction`, `registerTrigger` exports in [`iii.ts`](https://github.com/iii-hq/iii/blob/main/iii.ts) | [`sdk/packages/node/iii/src/logger.ts`](https://github.com/iii-hq/iii/blob/main/sdk/packages/node/iii/src/logger.ts) | Browser/Node tests in `sdk/packages/node/iii-example/` |
| **Rust** | [`sdk/packages/rust/iii/src/lib.rs`](https://github.com/iii-hq/iii/blob/main/sdk/packages/rust/iii/src/lib.rs) | Builder structs in [`src/register.rs`](https://github.com/iii-hq/iii/blob/main/src/register.rs) | [`src/logger.rs`](https://github.com/iii-hq/iii/blob/main/src/logger.rs) with `observability` feature | [`sdk/packages/rust/iii-example/src/http_example.rs`](https://github.com/iii-hq/iii/blob/main/sdk/packages/rust/iii-example/src/http_example.rs) |

All three SDKs transmit messages using the protocol definitions in [`engine/src/protocol.rs`](https://github.com/iii-hq/iii/blob/main/engine/src/protocol.rs), ensuring wire-format compatibility regardless of language choice.

## Which SDK Should You Choose?

Select the SDK that aligns with your existing infrastructure and performance requirements.

- **Choose Python** when integrating with existing Python services or data science workflows. The `asyncio` pattern integrates cleanly with FastAPI or other async Python frameworks, and the PyPI distribution (`pip install iii-sdk`) requires no compilation step.

- **Choose TypeScript** for full-stack JavaScript applications or when you need browser-based worker execution. The `iii-browser-sdk` provides a lightweight bundle with WebSocket auto-reconnection, while the Node SDK (`pnpm install iii-sdk`) works seamlessly with Express or Next.js backends.

- **Choose Rust** for performance-critical workers requiring minimal memory footprint and compile-time safety guarantees. The crate (`cargo add iii-sdk`) produces native binaries with zero-cost abstractions and strong typing via `serde`.

## Summary

- **All three SDKs expose identical high-level APIs** (function registration, trigger binding, streaming, and logging) but differ in language-specific ergonomics.
- **Python** uses `asyncio` coroutines with exception-based error handling and dynamic typing.
- **TypeScript** provides Promise-based async/await with compile-time interfaces and browser compatibility.
- **Rust** offers zero-cost abstractions with `Result<T, Error>` returns and `serde`-based serialization.
- Installation differs by ecosystem: `pip install iii-sdk` (Python), `pnpm install iii-sdk` (TypeScript), and `cargo add iii-sdk` (Rust).
- Source code for each SDK resides in `sdk/packages/python/`, `sdk/packages/node/`, and `sdk/packages/rust/` respectively.

## Frequently Asked Questions

### Can I mix SDKs in the same iii deployment?

Yes. The iii engine treats all SDKs identically on the wire because they use the same WebSocket protocol defined in [`engine/src/protocol.rs`](https://github.com/iii-hq/iii/blob/main/engine/src/protocol.rs). You can register functions in Rust, trigger them from TypeScript clients, and process results in Python workers within the same application.

### Do all SDKs support the same trigger types?

Yes. All three SDKs support HTTP endpoints, cron schedules, pub/sub topics, and custom triggers. However, the **TypeScript SDK** specifically provides additional browser-oriented utilities like `iii-browser-sdk` for WebSocket connection management, while the **Rust SDK** offers strongly-typed trigger builders (e.g., `HttpTrigger::new`) for compile-time validation.

### How does error propagation differ between the SDKs?

**Python** raises `iii.errors.IIIError` exceptions that must be caught with `try/except`. **TypeScript** returns rejected Promises that can be handled with `.catch()` or `try/catch`. **Rust** returns `Result<T, IIIError>` enums, requiring explicit error handling with the `?` operator or pattern matching. All three propagate error details back to the engine logs regardless of language.

### Which SDK offers the best performance for high-throughput workers?

The **Rust SDK** provides the best raw performance due to zero-cost abstractions, lack of garbage collection, and compile-time optimizations. However, the **Python** and **TypeScript** SDKs are sufficient for I/O-bound workloads and offer faster development cycles. For CPU-intensive tasks, Rust's native binary execution in [`sdk/packages/rust/iii/src/lib.rs`](https://github.com/iii-hq/iii/blob/main/sdk/packages/rust/iii/src/lib.rs) minimizes latency and memory overhead.