Build a Plugin
Create a Studio Plugin with a witwin.toml manifest, register Agent Tools and a solver, contribute a Project template, and load it locally.
A Plugin is a folder with a witwin.toml manifest and Python code that
registers into Studio. This guide builds the skeleton of a solver Plugin and
loads it from a local folder.
Layout#
wt_example/
witwin.toml # the manifest
pyproject.toml # makes the Plugin a pip distribution named wt-example
__init__.py # importing it registers components, panels, ...
agent_tools.py # Agent Tools
solver_host.py # the solver process
templates/ # optional Project templatesThe manifest#
id = "example.solver"
name = "Example"
version = "0.1.0"
description = "A minimal solver Plugin."
license = "MIT"
repository = "https://github.com/you/wt_example"
dependencies = ["numpy"]
icon = "box"
[[contributes.tools]]
module = "agent_tools"
register = "register"
[permissions]
tools = ["read", "scene_write", "execute"]
[[contributes.solvers]]
id = "example.solve"
title = "Example solver"
entry = "solver_host.py"
lifecycle = "warm"
idleTimeoutSec = 300
[contributes.solvers.runtime]
python = "${project:python}"[permissions] is a disclosure shown before the user trusts the Plugin; it
does not sandbox the code. See the witwin.toml reference
for every field.
Write the solver#
Solvers run in their own process on the Project's interpreter
(${project:python}), so heavy dependencies such as CUDA builds of PyTorch
stay out of Studio. The solver SDK is witwin.studio.solver:
from witwin.studio.solver import serve
def solve(ctx, scene, config):
ctx.progress(0.5, "halfway")
# read the scene, run the computation, return the outputs
return {"value": 42}
if __name__ == "__main__":
serve(solve, scene="document")scene="document" hands solve the Scene document as a dict, so the solver
process never imports the editor's server code and runs on any Project
interpreter. ctx.progress reports progress to Studio and to witwin solve.
Load it while you develop#
On the Plugins page, open the + Add menu, choose Add Local Plugin Path and pick the folder. A local Plugin never triggers a dependency install: install its requirements into your environment yourself. If a requirement is missing, the Plugin is listed with the reason and its code is not loaded.
From the command line, pass --plugin-path to witwin solve or
witwin host.
Contribute a Project template#
A template is a folder copied into a new Project, plus a content manifest
whose sha256 is pinned in witwin.toml:
[[contributes.templates]]
id = "example-sim"
title = "Example Sim"
icon = "box"
version = "1.0.0"
dir = "templates/example-sim"
manifest = "template.manifest.json"
sha256 = "<sha256 of template.manifest.json>"
preview = "templates/example-sim.webp"The payload must contain witwin.toml, and should be a complete Python
Project: a pyproject.toml that depends on your Plugin, plus scripts/ and
tests/ that run with witwin.studio alone. .witwin/, results/,
plugins/, .venv/ and __pycache__/ are refused.
Commit template payloads with line-ending conversion off
(templates/** -text in .gitattributes); otherwise a Windows checkout
rewrites line endings and the hashes stop matching.
Publish#
Plugins are distributed from git repositories or the witwin index, never
from PyPI. Tag a release in your repository; users add it with
git+https://github.com/you/wt_example and the tag.