Plugins

The workspace

Plugins made in the studio, saved as revisions, installed like a Git commit and exported to Git.

For: plugin authors.

Use the tenant workspace for plugin folders edited in Studio or with oz0 workspace. Each save creates a revision. Installing that revision runs the same checks, quality gate and rollout as installing a commit from Git.

Export the folder to Git when you want to continue development in a repository.

Folders and revisions

A folder holds one plugin, and is named like it: the manifest's name must be the folder's. Create one from a template (agent, the default: an agent in one file, <folder>.md, with no manifest; flow, a manifest with an agent, a flow and an eval; or empty, a manifest alone), or from a plugin folder on your machine:

Terminal
oz0 workspace create helper                   # one file: helper.md, the agent
oz0 workspace create support --from ./support # hidden files, .venv and the like are left out
oz0 workspace list
FOLDER   SOURCE     HEAD          FILES  DRAFT      INSTALLED     UPDATED
helper   workspace  3f2a91c0d4be  1      -          -             2026-10-06 10:12
support  workspace  889c011eb8b6  5      2 changes  889c011eb8b6  2026-10-06 11:07
tools    git        4be1a9e07c2d  0      -          git https://github.com/acme/tools  2026-10-01 09:30

What you write goes into your own draft of the folder, not into a revision: typing never creates one, and other people do not see your draft. workspace save makes a revision of it, the folder's new head:

Terminal
oz0 workspace write helper prompts/helper.md ./helper.md
oz0 workspace files helper --draft      # the files with your changes, marked
oz0 workspace save helper -m "Answer in two sentences"
oz0 workspace log helper

A revision is immutable: its ID is a hash of its files, its parent, its author, its message and its time, 40 characters like a Git commit, and its first 7 or more characters name it. Every revision is in the audit log.

When someone else saved a revision after you began your draft, saving lays your changes over theirs as long as you changed different files. When you both changed a file, the save is refused and names the files; --overwrite keeps your version of them, and workspace discard throws your draft away.

Limits: a file is at most 1 MB of text, and a folder at most 16 MB and 1000 files. Binary files belong in a Git repository.

Lint while you type

The studio checks the draft on every pause in typing, with the same checks as plugin lint, and marks each finding at its line and column. From the command line:

Terminal
oz0 workspace lint support --draft
flows/pipeline.yaml:8:30: error: Syntax error: mismatched input '<EOF>' expecting ... [cel]
agents/writer.yaml:5:12: info: anthropic/claude-haiku-4-5 ties the agent to anthropic; ... [suggestion]
1 errors, 0 warnings (1 ms)

A revision with errors can be saved, as a checkpoint; installing it is refused, as for a commit with errors.

Edit with forms

The studio's forms change one value at a time in the YAML, and keep the rest of the file as you wrote it: comments, blank lines, quotes and indentation. A changed value is written where the old one was, and nothing else on the line moves; a new key takes the indentation of the lines around it. In the rare layout where the kept lines would not hold the values you set, the file comes back as the YAML library writes it: comments kept, blank lines dropped, two-space indentation. The same from the command line, with values as YAML:

Terminal
oz0 workspace edit support agents/writer.yaml --set limits.max_cost_usd=0.05 --write
oz0 workspace edit support flows/pipeline.yaml --set 'steps[1].when="size(string(steps.draft)) > 1000"'
oz0 workspace edit support agents/writer.yaml --unset limits.timeout --write

Paths look like model.primary, steps[1].when and tools[2]; an index equal to a list's length appends, and maps on the way are created. Without --write the command prints the result and changes nothing.

The graph

The studio draws the plugin as a graph: agents with their tools and the agents they may delegate to, flows with their steps, branches and the steps each reads, hooks and the functions they call, and evals with what they test. It is computed from the files every time, and laid out automatically; nothing about it is stored, so the file stays the source. workspace graph <folder> prints it.

Install a revision

Terminal
oz0 plugin install workspace:support@889c011e    # a revision
oz0 plugin install workspace:support             # the folder's head
oz0 plugin update support                        # the head again, later

From here it is any plugin: the same checks, the contracts check against the installed version, the quality gate when it has evals (a flow's eval with recorded step outputs replays them on the test node and calls nothing), the rollout to canaries, the tool snapshots. plugin list shows its source as workspace:support and the revision as its commit. The admin API takes the same: InstallPlugin with source: "workspace:support" and the revision as ref.

Export to Git

Terminal
oz0 secret set GITHUB_PUSH_TOKEN --host github.com --host api.github.com # a token that may push to the repository
oz0 workspace export support --repo https://github.com/acme/agents --path plugins/support \
  --secret GITHUB_PUSH_TOKEN --pull-request
Pushed branch oz0/support-889c011eb8b6 (commit aac09de0f85a) to https://github.com/acme/agents.
Opened pull request #12: https://github.com/acme/agents/pull/12

The export pushes the revision as a new branch (oz0/<folder>-<revision> unless you name one with --branch) on top of the repository's default branch, or --base. With --path the plugin replaces that folder of the repository; at the root, the files the revision does not have, such as a README, are kept. The commit carries the revision's author and message and an Oz0-Workspace-Revision: line. A branch that exists is refused: the export never force-pushes, and never moves a branch someone else may work on, not even one made while the export runs.

A symbolic link in the base branch on the way to --path is refused too, and so is a --path or a file with a .git folder in it.

--pull-request opens a pull request on GitHub, Gitea or Forgejo, or a merge request on GitLab, from the new branch to the base. The forge is guessed from the host (github.com, gitlab.com or a host with gitlab in its name; Gitea's API otherwise); for a self-hosted forge give --forge github|gitlab|gitea|forgejo and --forge-api https://git.example.com/api/v1. The forge's API must be an https:// URL without a query; the edge follows no redirect from it, and a server in cluster mode reaches no address on its own machine or a link-local one (a dev server may, for a forge on localhost).

The token comes from a tenant secret, as for private plugins, and goes only to hosts the secret is bound to: the edge sends it to git as a header when the repository's host is bound, and to the forge's API when that is the repository's own (derived from its host: api.github.com for github.com, the same host's /api/v4 or /api/v1 for GitLab and Gitea) or a host bound itself, over HTTPS only, and never writes it anywhere.

In cluster mode the push itself, like the forge's API, reaches no address on the server's own machine and no link-local one (a cloud's metadata address among them): the edge resolves the repository's host once, refuses it when any of its addresses is such an address, and holds git to the addresses it checked, following no redirect; private networks' addresses stay allowed, for a Git server inside your company's network, and a dev server may push to one on localhost.

Exporting needs workspace.write; where the token may go is the choice of whoever set the secret with secrets.write, so a role that may export cannot send a tenant's secret elsewhere.

Plugins from Git

Plugins installed from a repository are listed in the workspace read-only, with their repository, folder and commit and a link to that commit on the forge. The studio shows their files, graph and lint findings, and changes happen in their repository. A workspace folder cannot take a Git plugin's name.

Who may do what

Readers of the tenant read the workspace: folders, revisions, files, lint and the graph. Its admins and owners create folders, write drafts, save revisions, install and export (roles). Every revision, install and export is in the audit log.

Copyright © 2026