---
title: "Addresses"
description: "Every part has one address, <plugin>/<part>. Where you write one, how the server checks it against the part's owner, and why a part is never renamed in place."
canonical_url: "https://docs.oz0.ai/build/parts/addresses"
---
# Addresses

> Every part has one address, \<plugin>/\<part>. Where you write one, how the server checks it against the part's owner, and why a part is never renamed in place.

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

<table>
<thead>
  <tr>
    <th>
      Part
    </th>
    
    <th>
      Address
    </th>
    
    <th>
      Such as
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      A function
    </td>
    
    <td>
      <code>
        &lt;plugin>/&lt;tool>.&lt;function>
      </code>
      
      , with <code>
        *
      </code>
      
       where a pattern is allowed
    </td>
    
    <td>
      <code>
        github/oz0_github.get_pull_request
      </code>
      
      , <code>
        github/oz0_github.*
      </code>
      
      , <code>
        github/*
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      A whole tool
    </td>
    
    <td>
      <code>
        &lt;plugin>/&lt;tool>
      </code>
      
       (kill switches and the inventory)
    </td>
    
    <td>
      <code>
        github/oz0_github
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      An agent
    </td>
    
    <td>
      <code>
        &lt;plugin>/&lt;agent>
      </code>
    </td>
    
    <td>
      <code>
        pr-reviewer/pr-reviewer
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      A flow
    </td>
    
    <td>
      <code>
        &lt;plugin>/&lt;flow>
      </code>
    </td>
    
    <td>
      <code>
        merge-when-green/merge-when-green
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      A skill
    </td>
    
    <td>
      <code>
        &lt;plugin>/&lt;skill>
      </code>
      
      , or <code>
        &lt;plugin>/*
      </code>
      
       for every one
    </td>
    
    <td>
      <code>
        web/research
      </code>
    </td>
  </tr>
</tbody>
</table>

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:

```yaml [agents/release-notes.yaml]
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
```

```yaml [oz0-plugin.yaml]
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](https://docs.oz0.ai/reference/plugin-manifest/dependencies#addresses)
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's
`StartJob` and 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](https://docs.oz0.ai/govern/tool-policy/conditions#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:

```text
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.


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
