Develop and test
The dev loop
orchestrator-zero dev # in the plugin's folder, or: orchestrator-zero dev ./my-plugin
dev lints the plugin, starts a dev server on free ports and a node, installs the plugin from its working tree (no commit needed) and waits until the node reports its functions. Then it watches the folder and reinstalls the plugin within seconds of every change.
Dev server ready. In another terminal:
export OZ0_CONTEXT=/tmp/.../operator/context.json
Temporal UI: http://127.0.0.1:...
Node started (log: /tmp/.../node.log)
my-plugin dev-... ready in 14.0s: my_plugin.hello
Watching for changes; Ctrl+C stops.
my-plugin dev-... reloaded in 8.5s: my_plugin.hello, my_plugin.goodbye
What it needs:
orchestrator-zero-nodenext to the server binary or onPATH, or--node-binary.- A runtime bundle:
--runtime-bundle, or$OZ0_RUNTIME_BUNDLE, or the newest in./dist/runtime.
The node's uv, Python and Node.js are cached between runs (--cache-dir), so only the first start is slow. The server starts empty every time.
Secrets in the plugin's requires.secrets come from your environment: dev and plugin test copy each one that is set into the dev server's tenant before installing, so export JEV_API_KEY=... before orchestrator-zero dev is all a tool with a key needs. A declared secret that is not set keeps the node from starting the plugin, and dev says which.
Lint
orchestrator-zero plugin lint # or: orchestrator-zero plugin lint ./my-plugin
orchestrator-zero plugin lint --json # the checked bundle and its problems, for CI
lint runs the same checks the edge runs before it installs a plugin: the manifest (unknown fields are errors), the agents it lists, its skills and the files they refer to. It exits non-zero on errors; warnings, such as an unpinned package, do not fail it. Run it in your plugin's CI.
Call a tool directly
Agents call tools for you. To call one yourself, for debugging, run ToolCallWorkflow on a node:
orchestrator-zero job run --workflow ToolCallWorkflow --task-queue oz0.default \
--input '{"tool": "my_plugin.hello", "arguments": {"name": "you"}}'
Use --task-queue node.<node-id> to call it on a particular node.
Run the MCP server by hand
Your tool is a normal MCP server, so you can also run it outside Orchestrator Zero:
uv run python -m my_plugin.server # speaks MCP over stdio
Any MCP client or inspector can talk to it.
Test it
orchestrator-zero plugin test runs the plugin's evals on a dev server and a node of its own, with model answers recorded once (--record) and replayed after, so tests are fast, free and repeatable, in CI too:
orchestrator-zero plugin test ./my-plugin --record # once, with your API key
orchestrator-zero plugin test ./my-plugin # after: no key, no tokens