diff --git a/iii-directory/README.md b/iii-directory/README.md
index 7ace3c410..f870092c8 100644
--- a/iii-directory/README.md
+++ b/iii-directory/README.md
@@ -9,7 +9,7 @@ into three sub-namespaces (all MCP-agnostic):
|---|---|---|
| **Skills** (`directory::skills::*`) | Enriched listing via `directory::skills::list` (`{ id, title, type, description, bytes, modified_at }` per row), a single-skill reader `directory::skills::get { id }` returning `{ id, title, type, description, body, modified_at }`, and `directory::skills::index` which renders a short per-worker overview document (one `##
` + first paragraph + `read more` link per `type: index` skill). `title` prefers the YAML frontmatter `title:` over the body H1; `type` is lifted from frontmatter `type:` (e.g. `index`, `how-to`, `reference`) and serialised as `null` when absent. | Orientation: "when and why to use my worker's tools" |
| **Prompts** (`directory::prompts::*`) | Static prompt templates listed by `directory::prompts::list` and read by `directory::prompts::get` | Parametric command templates the *user* invokes |
-| **Registry** (`directory::registry::*`) | HTTP proxy over `api.workers.iii.dev` with `workers::{list,info}`. Rows share the core `name` / `description` / `version` fields with the engine's `engine::workers::list` and add publication metadata (`type`, `config`, `supported_targets`, `total_downloads`, `dependencies`, optional `image`). `workers::list` is cursor-paginated with a server-authored page size. | "What's published in the public registry?" |
+| **Registry** (`directory::registry::*`) | HTTP proxy over `api.workers.iii.dev` with `workers::{list,info}`. Rows share the core `name` / `description` / `version` fields with the engine's `engine::workers::list` and add publication metadata (`type`, `config`, `supported_targets`, `total_downloads`, `dependencies`, `tags`, optional `image`). `workers::list` is cursor-paginated with a server-authored page size. | "What's published in the public registry?" |
Engine introspection (functions / triggers / registered triggers /
workers) is served by the engine natively at
@@ -30,7 +30,7 @@ downloaded, files belong to the developer — edit them however you want.
share the core `name` / `description` / `version` fields so a parser
that touches only those keys works against either surface; the
registry view also surfaces publication metadata (`type`, `config`,
-`supported_targets`, `total_downloads`, `dependencies`, optional
+`supported_targets`, `total_downloads`, `dependencies`, `tags`, optional
`image`) and the engine view adds runtime / connection state.
## Table of contents
diff --git a/iii-directory/src/functions/registry.rs b/iii-directory/src/functions/registry.rs
index 795e946b8..14a6c24cb 100644
--- a/iii-directory/src/functions/registry.rs
+++ b/iii-directory/src/functions/registry.rs
@@ -139,6 +139,11 @@ pub struct Worker {
pub dependencies: Vec,
#[serde(default)]
pub author: Option,
+ /// Discovery tags from the worker's `iii.worker.yaml` manifest,
+ /// passed through from the registry envelope (omitted when the
+ /// publisher declared none).
+ #[serde(default, skip_serializing_if = "Vec::is_empty")]
+ pub tags: Vec,
}
fn default_config_object() -> Value {
@@ -347,7 +352,7 @@ fn register_worker_info(iii: &Arc, cfg: &SharedConfig, cache: Registr
"Fetch full registry metadata for one worker: worker envelope \
(same core fields as the engine's `engine::workers::list` row \
shape, plus registry-only `type` / `config` / `supported_targets` / \
- `total_downloads` / `dependencies` / `image`), readme, full \
+ `total_downloads` / `dependencies` / `image` / `tags`), readme, full \
API reference (functions + triggers schemas), and the tree \
of skill / prompt file paths fetched from the registry's \
/w/{slug}/skills endpoint. Pass either `version` or `tag` \
@@ -623,6 +628,7 @@ pub fn parse_worker_info_response(
total_downloads: 0,
dependencies: Vec::new(),
author: None,
+ tags: Vec::new(),
});
let readme = detail