Addresses
For: plugin authors.
Name another plugin's part with its full address: the plugin name, a slash and the part name. Use this form in manifests, commands, console fields and tool policy rules.
A bare name refers to a part of the same plugin.
The forms
| Part | Address | Such as |
|---|---|---|
| A function | <plugin>/<tool>.<function>, with * where a pattern is allowed | github/oz0_github.get_pull_request, github/oz0_github.*, github/* |
| A whole tool | <plugin>/<tool> (kill switches and the inventory) | github/oz0_github |
| An agent | <plugin>/<agent> | pr-reviewer/pr-reviewer |
| A flow | <plugin>/<flow> | merge-when-green/merge-when-green |
| A skill | <plugin>/<skill>, or <plugin>/* for every one | web/research |
Names hold no /, so an address has exactly one. A function's name inside its tool keeps its own form:
github/oz0_github.get_pull_request is plugin github, tool oz0_github, function get_pull_request. An address
can read twice, as in github/oz0_github.get_file, because authors start their tool IDs with the plugin's name to keep
them apart in a tenant; that is expected.
A bare name means the same plugin
Inside a plugin, oz0_github.get_pull_request means this plugin's function, and review this plugin's agent. A
reference to another plugin's part names its plugin:
name: acme-release-notes
description: Writes release notes from the merged pull requests.
model:
use: default
instructions: prompts/release-notes.md
tools:
- github/oz0_github.list_pull_requests # github's function, granted under uses:
- oz.delegate
delegation:
allow: [github/oz0-github] # github's agent
uses:
github:
version: ">=1.1, <2"
tools: [oz0_github.list_pull_requests] # under the plugin's own key, its parts are bare
agents: [oz0-github]
A bare name of another plugin's part still works, since names are unique in a tenant, and plugin lint warns with the
address to write (plugin lint --fix writes it); for a verified plugin it is an error. The plugin in an address is the
plugin itself or one its manifest lists under uses:. The manifest reference
lists every field that takes one.
The owner check
Tool IDs and agent and flow names are unique per tenant: an install that would add a second one is refused. So the server always knows which plugin owns a part, and wherever a part is named after the plugin is installed, it checks the address against that owner before it acts:
- Starting a job:
oz0 run github/oz0-github "...",oz0 chat pr-reviewer/pr-reviewer, the runtime API'sStartJoband the catalog's lookup by name. - Calling a tool by hand:
oz0 tool call github/oz0_github.get_pull_request --args '{...}'. - Kill switches and the inventory:
oz0 kill agent pr-reviewer/pr-reviewer,oz0 kill tool github/oz0_github,oz0 inventory set agent pr-reviewer/pr-reviewer --purpose .... - Tool policy rules:
oz0 policy ask 'github/oz0_github.*'decides only github's functions; see a rule by address. - Lists:
oz0 job search --agent pr-reviewer/pr-reviewer.
An address that names another plugin is refused, with the owner the server found:
github/triage is not an agent of github: triage is support-triage's
The check comes after the caller's permission: someone who may not start jobs is refused for that first, and a key scoped to some agents learns nothing about an agent outside its scopes. Once the address is checked, the server acts on the bare name exactly as it always has: the job, its history, its child jobs, the calls a node makes and what is stored all carry the bare name, so nodes of an older version and jobs that were running before see no change.
The console, oz0 job get, oz0 job trace, oz0 catalog, oz0 approval list and oz0 plugin inspect show parts by
address, from the owner the server knows. The console's pages stay where they were (/t/<tenant>/agents/<name>).
Two plugins that define one name
An install refuses a second agent or flow of a name, and a second tool ID. A tenant that has two anyway, from before installs refused it or written to the store some other way, runs neither: the edge and every node withhold the name, and a job of it fails at its start with the reason ("plugins a and b each define an agent or flow named triage, so neither runs"). Remove one of the plugins, or update one to a version whose part has another name.
The names a model sees
A model sees a function as <tool>__<function>, never with its plugin. Model providers limit a function's name: 64
characters for OpenAI's formats, 128 for Anthropic's Messages API. A node leaves out a function whose name a model
would see as longer than 64 characters, saying which, and plugin lint warns about one in the plugin's measured
listing (tools.listing.json). Keep tool IDs and function names short enough for both.
Renaming a part
Do not rename a part in place. An agent's name is in its model calls' activity names in every running job's history,
in its child jobs' IDs, and in the tenant's routes and policies: a job that started under the old name needs it until
the job ends. Ship the new name beside the old one in a new version, move what starts it (routines, other plugins'
uses:, your own scripts) to the new name, and remove the old part in a later version, once its jobs have ended
(oz0 job search --agent <plugin>/<old name> --status running shows them).
The same holds for a tool's ID and a function's name: other plugins' uses: grants and the tenant's tool policy name
them, and an update that drops a function another installed plugin names is refused unless forced with a reason.
Records and start-up text
Keep versioned records from your plugin's tools through the platform, under the tenant's retention, holds and erasure, and add text to the start-up context of the agents that use your plugin.
Define a routine
Bind a scheduled or event-driven job to an identity, tools and limits.