Swift Bindings Release

Today, we are excited to announce the release of our Swift bindings! These have been in the works for some time now and are a part of our ongoing effort of making NobodyWho available wherever you need it. In this post, we will briefly cover some of the interesting things we dealt with during development. For the full docs please check out docs.nobodywho.ooo.

UniFFI Bindings

To handle the FFI between Rust and Swift, we use UniFFI. This is a tool developed and maintained by the Mozilla Foundation, designed to simplify the process of generating FFI bindings from Rust to multiple target languages.

The main languages supported by UniFFI are Python, Swift and Kotlin, but there are many open source repos which support additional languages and frameworks (like the one we use for our React Native bindings). The great thing about UniFFI is that for each target language it gets us 80% of the way in an instant. It gives us access to our Rust code in each language without having to manage the FFI layer ourselves.

However, since it is pretty language agnostic the generated bindings do not result in the most ergonomic API for each language. As a result we wrap the code generated by UniFFI in the target lanuage. A lot of this wrapping work is mostly to enchance the API, but there are some cases where additional work is needed like async iterators (for streaming tokens) and tool calling. Of these, tool calling is the most interesting case.

Tool Calling Macros

Tool calling is by far the trickiest part of bringing NobodyWho to new languages. This has been the case for every binding before, and Swift is no exception.

For NobodyWho to use a tool, we need to know the name of the function, as well as the names and types of all the parameters.

Some languages make this easy: e.g. in Python, we can just inspect the entire function signature at runtime. Done.

This makes Python tool declaration very pretty:

from nobodywho import tool

@tool(description="Triples a number")
def triple(x: float) -> str:
    return f"{x} * 3 = {x * 3}"

React Native bindings made this difficult. Typescript types are stripped at compiletime, and NobodyWho doesn't get to touch it until the native library is loaded at runtime, so we effectively need devs to annotate the function twice. Ugh:

import { Tool } from 'react-native-nobodywho';

const triple = (x: number): string => {
  return `${x} * 3 = ${x * 3}`;
};

const tripleTool = new Tool({
  name: 'triple',
  description: 'Triples a number',
  parameters: [
    { name: 'x', type: 'number' },
  ],
  call: triple,
});

...and even if we could somehow extract the TypeScript types, we also need to support plain JS, which just doesn't have types.

While NobodyWho in Swift does expose the same verbose API that we use in React Native, we can also do something much neater: Macros!

These were introduced to Swift in 5.9 and allow us to inspect the literal function definition and directly read the parameter names and types at compile time. From this we then generate the corresponding code using the verbose tool creation API with the properly derived types. This also lets us error early if the function has parameter types which we don't support (like custom structs).

With this macro, Swift tool declarations are super clean!

@DeclareTool("Triples a number")
func triple(x: Double) -> String {
    return "\(x) * 3 = \(x * 3)"
}

Much better. Thank you, Swift!

WatchOS and VisionOS

Creating bindings for Swift also brings NobodyWho to new platforms. With Godot, Python, Flutter and React Native, we cover game development, iOS, Android, Desktop and more.

With the addition of Swift we can now also run NobodyWho on more niche devices like Apple Watch and Apple Vision Pro. We are very interested in how far on-device AI can be pushed, and which devices can run it. With this in mind, we will soon be releasing an example app for WatchOS running a local model on Apple Watch hardware see demo video here.

Final Remarks

With this post we hope to have given you some insight into our new Swift bindings and some of the interesting work that went into creating them. We hope that you will find them useful and that you will stay tuned for when we release Kotlin bindings very soon!

In the meantime, go try out NobodyWho in Swift: https://docs.nobodywho.ooo/swift and, if you'd like, give us a star on GitHub: https://github.com/nobodywho-ooo/nobodywho

This post was written entirely by a human. No words were made up by the machine

Published May 15, 2026

Release Swift