UNI is still under development — Please check back at the end of March
Skip to content

SDK · Getting started

Prerequisites

To build plugins, you need:

Your first plugin

Create a folder named uni_dice inside plugins/, then add an __init__.py:

plugins/uni_dice/__init__.py
"""
Roll dice with configurable sides.

Name: Dice
Icon: casino
"""

import random

import uni_plugin_sdk as uni

@uni.tool
def roll_dice(sides: int = 6) -> dict:
    """
    Roll a dice with the specified number of sides.

    Args:
        sides: Number of sides on the dice (default: 6)

    Returns:
        The result of the dice roll
    """
    result = random.randint(1, sides)

    uni.push_text_card(
        title="🎲 Dice roll",
        message=f"Rolled {result}",
        timeout="10s"
    )

    return {
        "sides": sides,
        "result": result
    }

Once loaded, ask UNI to roll a dice and it will call roll_dice. The Tools & cards article covers tools and cards in depth.

Running

Plugins load automatically when you run uni. For development, use dev mode:

Starting dev mode
uni --dev

Dev mode mounts your plugin source into the container, enabling auto-restart on code changes without rebuilding. It also uses an isolated user_dev data directory.

Plugin structure

File/Directory Required Description
__init__.py Yes Plugin entrypoint
requirements.txt No Python dependencies
*.py, **/*.py No Additional Python modules
static/ No Client assets (URL: /plugins/{name}/static/*)
templates/ No Jinja2 templates for web pages

Every __init__.py must contain import uni_plugin_sdk as uni.

The module docstring supports optional metadata as trailing Key: Value lines:

Key Description
Name Display name
Icon Material icon name
Author Plugin author(s)
Requires Runtime requirement. Supported: cuda

Dependencies

Plugins with additional Python dependencies should include a requirements.txt:

plugins/{name}/requirements.txt
beautifulsoup4~=4.14.2
google-auth~=2.41.0

These are installed at Docker build time. The following packages are pre-installed:

cryptography dateparser fastapi html2text huggingface-hub nltk numpy openai openwakeword packaging pillow pydantic pydub python-multipart python-socketio PyYAML requests tomlkit

After modifying requirements.txt, restart with uni --dev to rebuild.

Configuration

Plugin settings live in user/settings.toml. Read them with config.plugin:

Reading settings
config = uni.get_config()

timeout = config.plugin.get("timeout", str, "30s")
use_cache = config.plugin.get("cache", bool, True)
default_city = config.plugin.get("default_city", str, "London")
user/settings.toml
[plugin.uni_weather]
timeout = "30s"
cache = true
default_city = "New York"

The API automatically scopes reads and writes to your plugin's name.

Writing settings
config = uni.get_config()

config.plugin.set({
    "default_city": "London",
    "timeout": "45s",
    "cache": False
})

No secrets in settings

Never store API keys or secrets in settings.toml. Use uni.secure_json_file instead.

Debugging

Logs appear in the terminal and in user[_dev]/logs. Add logging to your plugin:

Plugin logging
logger = uni.get_logger(__name__)

logger.info("Plugin loaded")
logger.exception("Failed to connect")

For step-through debugging, run uni --dev --debug to expose debugpy on port 5678. Use the [UNI] Attach to container VS Code configuration to connect.

Publishing

To add your plugin to the community plugin list, publish it to GitHub and submit it here.

Real-world examples

The bundled plugins in plugins/ demonstrate SDK patterns at scale:

Plugin Demonstrates
uni_calculator Basic safe tool with sandboxed Python interpreter
uni_web_access Tools with conditional safety, LLM tasks, lifecycle hooks
uni_timer Tools, scheduling, rich cards (HTML/JS/CSS), device connection hooks
uni_memory System prompt modifier, context injection, secure JSONL storage, embeddings
uni_avatar_vrm Avatar provider, web interface, file uploads, sockets

Copy one and modify it, or read through the rest of the SDK articles starting with Tools & cards.