Registry
A registry is a GitHub project holding an index of things you can import into a Mindconnect installation: LLM configs, agents, workflows, and packages that bundle all of them.
There is no registry server. A registry is a repository — fork it, send a pull request, pin a tag — and everything a hosted catalogue would need (review, history, ownership) is what Git already does. Reading one is a plain HTTPS GET of raw files, so a private registry needs nothing but a token.
Using one
Registry in the admin UI lists the registries this installation knows. Add one
by its owner/repo:
| Typed | Reads |
|---|---|
acme/agent-registry | main, registry.json |
acme/agent-registry@v1.2.0 | the tag v1.2.0 |
acme/agent-registry@main:catalog/index.json | another index path |
https://github.com/acme/agent-registry | same as the first row |
Pin a tag for a registry you do not control: a branch is whatever its owner pushed last.
Open a registry to see what it offers — filed under Agents, LLM configs, Workflows and Packages — search or filter by kind, and import an entry. Each row carries the button that installs it: Import for something new, Overwrite — with a confirmation — for something already here, and no button at all for a kind this installation has no installer for. A badge beside the name says which of the three it is.
The import runs from the row and lands back on the same list: the report above it, line by line, the row's badge flipped to Already here, and the search and the kind filter as they were. Opening an entry is for reading it first — its warning, its description, a package's contents — not a station every import has to pass through. A package's row always reads Import: whether a package as such is here is not something an installation knows, only whether its members are, so overwriting one is done from its page.
Each rubric carries Import missing (n) beside its heading — everything of that kind the list is showing that this installation could install and has not. It asks first, because it is the one button whose reach is wider than the row it sits on, and it imports in one walk: an LLM config three of the agents point at is fetched once and the report says so once. The set is recomputed when the button is pressed, not taken from what the page counted. Packages has no such button — a package is already a bulk import, and "what is missing" is not a question an installation can answer about one.
A package opens on two tabs: its details, and Contents — everything importing it would install, the entries its members require included, each marked New or Already here. Every entry has an Include box, ticked by default; untick one to leave it out. A left-out entry is not installed at all, not even as what another entry requires, and the report lists it as skipped.
Remove takes a package out again: it deletes the included entries that are here — workflows first, then agents, then the LLM configs they run on — and leaves the unticked ones in place.
An entry that something outside the package still uses says so — Used by Agent 'default-chat', Agent 'planner' and 13 more — and starts unticked, so that removing a package does not take the model away from every other agent. The check follows the chain: when a shared alias stays, the config it delegates to stays too. What counts as a use: an agent's LLM config, the agents it calls and its reviewers, an alias's target, and a workflow's agent calls, inline agents and called workflows. A reference kept anywhere else — a tool setting, an application property naming a default agent — is not seen, so read the list before you press Remove.
Importing has two modes:
- Import keeps what is already here under the same name, and installs the rest. The default; it cannot destroy anything.
- Import and overwrite replaces entities of the same name, keeping their local ids — so the agents, aliases and sessions pointing at them keep working.
Nothing is rolled back if one member of a package fails: the others are installed, and the report says line by line what happened.
What a registry repository looks like
registry.json ← the index
llm-configs/
default.json
agents/
web-researcher.json
research-lead.json
workflows/
summarize.json
skills/
weekly-report/
SKILL.md ← a skill: front matter + instructions
packages/
research-kit.json ← a package manifest
registry.json
{
"schemaVersion": 1,
"name": "Acme agent registry",
"description": "Agents and workflows we use in-house",
"entries": [
{
"id": "default-llm",
"type": "llm-config",
"name": "default",
"description": "Claude Sonnet, our house default",
"version": "1.0.0",
"path": "llm-configs/default.json"
},
{
"id": "web-researcher",
"type": "agent",
"name": "web-researcher",
"description": "Searches the web and reports with citations",
"version": "1.2.0",
"path": "agents/web-researcher.json",
"tags": ["research"],
"author": "acme",
"homepage": "https://github.com/acme/agent-registry",
"requires": ["default-llm"]
},
{
"id": "research-kit",
"type": "package",
"name": "Research kit",
"description": "A research lead, its sub-agents and the model they share",
"path": "packages/research-kit.json"
}
]
}
| Field | Meaning |
|---|---|
id | the entry's address inside this registry — what requires and packages refer to |
type | llm-config, agent, workflow, skill or package |
name | the name the entity is installed under; the screen warns when it is taken |
path | where the entity's file sits in the repository |
version, author, homepage, tags, description | for the person deciding |
requires | ids of entries installed first, in order |
An entry whose type this installation does not know — written for a newer
Mindconnect — is left out and counted, and the screen says how many; the rest
of the index reads as usual. A registry can therefore gain a kind of entry
without breaking the installations that have not caught up.
Unknown fields are ignored, so an index written against a later schema still reads.
Entity files
An entity file is exactly what the installation stores — the same JSON the admin UI shows under Agents and LLM configs, and the same file the workflow admin writes. Two fields are taken away on the way in:
- Ids. A new entity gets a fresh local id; re-importing over an existing one keeps the local id, so nothing pointing at it breaks.
- A literal API key in an LLM config. A registry config is meant to carry
${ANTHROPIC_API_KEY}, which resolves against this installation's environment at call time. A key that is not a placeholder is somebody else's credential — it is dropped, and the import report says so.
A skill is the one entry that is not JSON: its file is a SKILL.md —
front matter with name, description and tools, then the instructions —
the same file the Skills screen offers for download, so a skill
travels between a repository's .mindconnect/skills/, a registry and an
installation unchanged. Imported, it is stored as a managed skill under the
entry's name (lower-cased) — the name the screen checks and a package removes
it by; a front matter that calls it something else is noted in the import
report. Only
the file is fetched: a skill that keeps scripts or templates beside its
SKILL.md in the repository has to carry them in its own text to be usable
from a registry. Re-importing keeps the local id and the enabled flag — a
skill an operator switched off stays off when a newer text arrives.
Packages
A package manifest names everything that has to arrive together. A useful agent is rarely one file: it points at an LLM config by name, calls two sub-agents, and one of those runs a workflow.
{
"name": "Research kit",
"description": "A research lead, its sub-agents and the model they share",
"version": "1.0.0",
"includes": ["default-llm", "web-researcher", "verifier"],
"items": [
{
"id": "research-lead",
"type": "agent",
"name": "research-lead",
"path": "agents/research-lead.json"
}
]
}
includes are ids from the same index — reuse, so the same agent can be a member
of three packages and exist once. items are entries written into the manifest
itself, for parts that are only ever this package's. They install in that order,
each with its own requires, and an entry reached twice is installed once.
Private registries
Set Token variable on the registry to the name of an environment variable holding a GitHub token — the name, never the token. The installation reads it at request time, so the store that holds the registry can never hold a secret.
export ACME_REGISTRY_TOKEN=ghp_…
Configuration
| Property | Default | What it does |
|---|---|---|
mindconnect.registry.enabled | true | false takes the whole feature away, screen included |
mindconnect.registry.default-source | — | owner/repo[@ref][:index-path], added on first start when no registry is configured yet |
mindconnect.registry.cache-ttl | PT10M | how long a fetched index or file is reused; the screen's Refresh drops it |
mindconnect.registry.timeout | PT20S | per-request HTTP timeout |
Registries are stored per namespace under
<data-base-dir>/<namespace>/system/registries/<id>.json. With
mindconnect.persistence=postgres they are rows of mc_registry_source, keyed
by (namespace, id) (mc-agent-registry-pg, brought in by
mc-agent-starter-postgres). A namespace that has no row yet imports its
system/registries/*.json once, on first use; the files are left in place.
Shipping a registry with an application
An application ships its registries the way it ships its seed agents and MCP
servers: one file per registry under initial-data/registries/ on its
classpath. On start, every registry not configured yet is installed; one that
is — pinned to a tag, disabled — is left as the operator made it, and one that
was deleted comes back on the next start (disable it instead to keep it quiet).
{
"name": "Mindconnect registry",
"owner": "mindconnect-ai",
"repo": "mc-registry",
"ref": "main"
}
The file name is the registry's id — owner-repo, as the screen names a
registry you add by hand, so the two cannot end up as duplicates. The admin UI
ships mindconnect-ai/mc-registry
this way.
What importing means
A registry is somebody else's repository. Nothing runs by being imported, but everything imported is here afterwards:
- An agent is a system prompt and a tool list somebody else wrote. Imported, it runs on your models with your tools. Read its prompt before you let it run.
- A workflow is executable — its steps call tools, agents and scripts.
- An LLM config names a provider and a base URL: the address this installation would send prompts to.
- A skill is instructions an agent loads on demand — steps to follow, commands to run. Imported, every agent whose skills mode is ALL is offered it; an agent naming its skills has to name it.
The import screen says this above the buttons, once, before the click.
Modules
| Module | Purpose |
|---|---|
mc-agent-registry-core | What a registry is: domain, the three ports, the import service that walks packages and dependencies |
mc-agent-registry | The GitHub client, the file-backed store of registries, the installers for LLM configs, agents and skills |
mc-agent-registry-admin-ui-rest | The /registry screen |
Installers are contributed by the module that owns the entity, so an installation
that has no workflow engine simply has no workflow installer — its registry then
lists workflows it cannot import, and says so, instead of dragging the engine in
as a dependency. The workflow installer lives in mc-agent-tools-workflow.