SDK · Getting started¶
Prerequisites¶
To build plugins, you need:
- A UNI installation
- Python knowledge
- A code editor
Your first plugin¶
Create a folder named uni_dice inside plugins/, then add an __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:
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:
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:
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")
[plugin.uni_weather]
timeout = "30s"
cache = true
default_city = "New York"
The API automatically scopes reads and writes to your plugin's name.
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:
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.