Admins can browse a curated catalog of agent roles, import roles/bundles
into a workspace, and update an imported role when the catalog ships a
newer version.
Catalog: a set of JSON files (index.json manifest + bundles/<id>/<lang>.json)
served from a local folder (dev) or a remote http(s) base URL via
AI_AGENT_ROLES_CATALOG_URL. Seeded with the existing 7 RU roles (editorial +
research bundles) plus EN translations.
Server:
- migration: nullable jsonb `source` column on ai_agent_roles
({ slug, language, version }; null => manually created)
- catalog provider: remote fetch with timeout + streaming size cap, or local
read; ^[a-z0-9-]+$ segment guard against path-traversal/SSRF
- admin endpoints: catalog, catalog/bundle, import, update-from-catalog
- import/update match by slug+language; update preserves `enabled`
Client:
- catalog modal with language selector and Import/Installed/Update states
- "Import from catalog" button + empty-state CTA in the roles settings panel
- en-US/ru-RU strings
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Agent roles catalog
This directory is data, not application code. It holds the content of an "agent roles catalog": reusable agent role definitions (system prompts plus a little metadata), grouped into bundles and translated into one or more languages. A separate server reads these files and serves them; nothing here is executable application logic except the validation script.
File layout
agent-roles-catalog/
index.json # the catalog manifest: bundles, languages, role versions
bundles/
<bundle-id>/
<lang>.json # one file per declared language (e.g. ru.json, en.json)
scripts/
check.mjs # validates the catalog (no dependencies)
package.json # defines the `check` script
README.md
Currently shipped bundles:
editorial— the editorial suite (structural-editor, line-editor, copy-editor, fact-checker, proofreader, narrator), languagesru,en.research— a singleresearcherrole, languagesru,en.
index.json schema
{
"schemaVersion": 1,
"bundles": [
{
"id": "editorial", // unique bundle id; matches bundles/<id>/
"name": { "ru": "...", "en": "..." }, // localized display name
"description": { "ru": "...", "en": "..." },
"languages": ["ru", "en"], // which <lang>.json files must exist
"roles": [
{ "slug": "structural-editor", "version": 1 }
// ...
]
}
]
}
version lives here, in index.json, per role. Bump it whenever a role's
content (instructions, name, description, etc.) changes, so consumers can detect
updates.
Bundle (<lang>.json) schema
{
"schemaVersion": 1,
"language": "ru",
"roles": [
{
"slug": "structural-editor", // REQUIRED, unique across the whole catalog
"emoji": "🧱",
"name": "...", // REQUIRED, localized
"description": "...", // localized
"instructions": "...", // REQUIRED, the system prompt, localized
"autoStart": true, // whether the role starts working immediately
"launchMessage": "..." // first message sent on launch (or null)
}
]
}
Notes:
modelConfigis intentionally absent; the server treats an absentmodelConfigasnull.- A role's
slug,emoji, andautoStartare identical across all language files of the same bundle. Onlyname,description,instructions, andlaunchMessageare translated.
Slug uniqueness
Every slug must be UNIQUE ACROSS THE WHOLE CATALOG, not just within a
bundle. A slug appears once per language file of its bundle (same slug in
ru.json and en.json), but no two different bundles may share a slug.
scripts/check.mjs enforces this.
How to add things
Add a role to an existing bundle
- Add an entry to that bundle's
roles[]inindex.jsonwith a new uniqueslugandversion: 1. - Add a role object with the same
slugto every<lang>.jsonof the bundle, translatingname,description,instructions, andlaunchMessage. - Run the check (see below).
Add a bundle
- Add a bundle object to
index.json(id,name,description,languages,roles). - Create
bundles/<id>/<lang>.jsonfor each declared language, with one role object perroles[]entry. - Run the check.
Add a language to a bundle
- Add the language code to that bundle's
languages[]inindex.json. - Create
bundles/<id>/<lang>.jsoncontaining every role of the bundle, translated. - Run the check.
Change a role's content
Edit the role in the relevant <lang>.json file(s) and bump that role's
version in index.json.
Validating
From this directory:
node scripts/check.mjs # or: npm run check
It fails (exit code 1) if any slug is duplicated across the catalog, if a
bundle's index roles[] don't match the slugs present in each language file, if
a declared language file is missing, or if any role is missing a required field
(slug, name, instructions). It prints OK on success.