Skip to main content

Overview

MoFA provides native language bindings for Python, Java, Kotlin, Swift, and Go through Mozilla UniFFI. These bindings expose the full power of MoFA’s Rust core with zero-cost abstractions and idiomatic APIs for each language.

Python

Native Python bindings with type hints and async support

Java

Java bindings with Maven/Gradle integration

Kotlin

Kotlin bindings with coroutine support

Swift

Swift bindings for iOS and macOS

Go

Go bindings with goroutine support

Architecture

MoFA’s binding architecture leverages UniFFI to generate language-specific interfaces from a single UDL (UniFFI Definition Language) file:

Layered Architecture

1

Kernel Layer

Core Rust implementation in mofa-kernel - agent lifecycle, metadata, communication primitives
2

Foundation Layer

Business logic in mofa-foundation - LLM integration, persistence, agent abstractions
3

SDK Layer

Standard API surface in mofa-sdk - high-level interfaces, secretary agent mode
4

FFI Layer

Foreign Function Interface in mofa-ffi - UniFFI bindings, type conversions
5

Language Bindings

Generated language-specific wrappers with idiomatic APIs

UniFFI Definition Language

The mofa.udl file defines the interface exposed to all languages:
namespace mofa {};

// Error types
[Error]
enum MoFaError {
    "ConfigError",
    "RuntimeError",
    "LLMError",
    "IoError",
    "InvalidArgument",
    "ToolError",
    "SessionError",
};

// Agent lifecycle types
enum AgentStatus {
    "Created",
    "Initializing",
    "Ready",
    "Running",
    "Executing",
    "Paused",
    "Interrupted",
    "ShuttingDown",
    "Shutdown",
    "Failed",
    "Destroyed",
    "Error",
};

// LLM Agent interface
interface LLMAgent {
    [Throws=MoFaError]
    string agent_id();
    
    [Throws=MoFaError]
    string name();
    
    [Throws=MoFaError]
    string ask(string question);
    
    [Throws=MoFaError]
    string chat(string message);
    
    void clear_history();
    sequence<ChatMessage> get_history();
};

Core Features

LLM Agent Interface

All bindings provide a consistent LLM agent API:
  • Builder Pattern: Fluent API for agent configuration
  • Simple Q&A: Stateless question answering via ask()
  • Multi-turn Chat: Contextual conversations via chat()
  • History Management: Access and clear conversation history
  • Multiple Providers: OpenAI, Azure, Anthropic, Gemini, Ollama, custom

Session Management

Persistent conversation sessions with storage backends:
  • In-Memory Sessions: Fast, ephemeral storage
  • File-Based Sessions: JSONL persistence
  • Metadata Support: Store custom key-value pairs
  • Session Lifecycle: Create, retrieve, save, delete, list

Tool Registry

Define custom tools in your language that agents can invoke:
  • FfiToolCallback Interface: Define tools in Python, Java, Kotlin, Swift, or Go
  • Dynamic Registration: Register tools at runtime
  • JSON Schema: Automatic parameter validation
  • Error Handling: Structured success/failure results

Type Conversions

Rust to Language Mappings

Rust TypePythonJavaKotlinSwiftGo
StringstrStringStringStringstring
boolboolbooleanBooleanBoolbool
u32intintIntUInt32uint32
f32floatfloatFloatFloatfloat32
Vec<T>List[T]List<T>List<T>[T][]T
Option<T>Optional[T]T / nullT?T?*T
Result<T, E>raises Ethrows Ethrows Ethrows E(T, error)

FFI-Safe Types

UniFFI enforces FFI-safe type boundaries:
pub struct TokenUsageInfo {
    pub prompt_tokens: u32,
    pub completion_tokens: u32,
    pub total_tokens: u32,
}

pub struct AgentOutputInfo {
    pub content: String,
    pub content_type: String,
    pub tools_used: Vec<ToolUsageRecord>,
    pub duration_ms: u64,
    pub token_usage: Option<TokenUsageInfo>,
    pub metadata_json: String,
}

Performance Characteristics

Zero-Copy Where Possible

UniFFI minimizes data copying:
  • String Views: Shared string data where safe
  • Reference Counting: Arc<T> for shared ownership
  • Direct FFI Calls: No intermediate serialization for primitives

Async Bridging

Rust’s async runtime is bridged to language-native async:
pub async fn ask(&self, question: &str) -> Result<String, AgentError> {
    // Tokio async runtime
    self.provider.complete(question).await
}

Building from Source

Prerequisites

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Build MoFA FFI
cd mofa
cargo build --release --features uniffi -p mofa-ffi

Common Patterns

Error Handling

All bindings expose unified error types:
from mofa import MoFaError

try:
    agent = builder.build()
    response = agent.ask("Hello")
except MoFaError as e:
    print(f"Error: {e}")

Resource Management

UniFFI handles reference counting automatically:
  • Automatic Cleanup: Objects are freed when no longer referenced
  • No Manual Memory Management: GC/ARC handles cleanup
  • Thread-Safe: Internal Arc<RwLock<T>> for concurrent access

Limitations

Current Constraints

UniFFI has some limitations to be aware of:
  • No Callbacks from Rust to FFI: Callbacks flow from FFI languages to Rust only
  • No Generic Types: All types must be concrete in UDL
  • No Lifetimes: All data must be owned or Arc-wrapped
  • Blocking Bridge: Async Rust calls are bridged to blocking FFI calls

Workarounds

  • Callbacks: Use FfiToolCallback trait for foreign tool implementations
  • Generics: Use JSON strings for flexible data exchange
  • Streaming: Return batch results, not true streams (for now)

Next Steps

Python Guide

Complete Python binding documentation with examples

Java Guide

Java integration with Maven and Gradle

Kotlin Guide

Kotlin bindings with coroutines

Swift Guide

Swift bindings for Apple platforms

Go Guide

Go bindings with idiomatic Go patterns

Resources

Build docs developers (and LLMs) love