Agotalk Role Package — Creator Guide (v0.4)
This is the public creator guide for creating an Agotalk role package. The stable package file contract lives at /docs/role-package.md. Audience: AI agents and developers. Read this whole file before generating anything.
A role package is a plain directory of files, shipped as a plain zip. The package truth is role.md plus the file tree. agotalk.role.toml is the machine contract that adds identity, preview metadata, and (for applications) a launchable entry. There is no other manifest. Do not invent one.
0. Authoring principles
Four principles sit above every rule in this guide. If a later section seems to conflict with one of these, the principle wins and the guide has a bug.
Treat the user's machine as brand new
Assume nothing is installed, nothing is downloaded, nothing is configured. A package that works because you happen to have ffmpeg, a font, or a model file on your laptop is a package that breaks for everyone else — and the failure lands on the user, who did nothing wrong.
- Bundle what you need into the package, or ship a download link plus a check that
tells the user exactly what is missing and where it comes from.
- Never assume network access at launch. Bundle fonts, styles, and data; do not fetch them
from a CDN when the app opens.
- Never assume a system Python, a system Node, or a globally installed CLI.
Use the environment Agotalk gives you, do not install into the user's system
Agotalk ships a curated, version-locked toolchain and puts it first on PATH. Reach for it before you reach for the user's machine:
| Available | Typical use |
|---|---|
python (3.11), node | scripts your skills invoke |
ffmpeg | audio/video probe, convert, extract frames |
magick (ImageMagick) | image convert, resize, inspect |
rg, fd, jq | search files, find files, query JSON |
sqlite3 | local structured data |
git, curl, bash | version control, HTTP, scripting |
| GNU coreutils | timeout, shuf, nproc, GNU date/stat/readlink |
Third-party libraries do not go through the user's system package manager. Declare them with dependency_mode = "locked" and a lockfile; Agotalk installs them into an environment keyed to your role and removes them with the app. See the contract's Dependencies section. A package that runs pip3 install has moved its problem onto the user's computer.
Use local HTML when text is the wrong shape for the content
A page in the package can carry what a chat message cannot: a grid of options, a rendered preview, a form, a comparison table, a chart. Ship it as a self-contained page and point the user at it. This is what the numbered-gallery pattern below is a special case of.
Make your HTML readable to the agent
Agotalk's browser tools let the agent observe a page and act on it, so the user can click around and the agent can then read what they chose. That only works if your markup gives the agent stable handles.
inspect_browser builds a ref for every interactive element by this rule (input, textarea, select, button, a[href], [role], [contenteditable]):
| Element has | Its ref | Stability |
|---|---|---|
id="pick-3" | id:pick-3 | stable — survives re-render and reordering |
only name="style" | name:style:7 | index-bound — shifts if the list changes |
| neither | div:12 | positional — breaks on any layout change |
So: give every interactive element a meaningful, stable id. It costs one attribute and it is the difference between the agent clicking your option 3 and the agent guessing at coordinates.
Along with ref, the agent reads back checked, value, selectedText, disabled, label, role, text, and type. Use them:
<!-- The agent can read: ref=id:template-3, checked, and the label text -->
<label for="template-3">03 · Editorial</label>
<input type="radio" id="template-3" name="template" value="03-editorial" />
<!-- Status regions are collected separately: [role=status], [aria-live], <output> -->
<output id="selection-summary" role="status" aria-live="polite">No template selected</output>
- Put the user's current choice somewhere machine-readable — a
value, acheckedradio,
or a [role="status"] region — not only in styling. A tile that is "selected" purely because it has a CSS class is invisible to the agent.
- Keep ids stable across renders. Regenerating ids on every paint makes every ref stale.
- Ordinary semantic HTML and ARIA are the protocol. Do not invent a private attribute
convention and expect Agotalk to honor it.
1. Three capabilities — pick exactly one path
Importable, launchable, and publishable are three different contracts. Decide what you are building first:
- Path A — minimal local candidate (importable only).
A single directory with a valid role.md and NO agotalk.role.toml. Agotalk imports it into the local Role Library as a candidate. Not launchable. Not publishable to the website (publishing requires the machine contract).
- Path B — launchable application (importable + launchable + publishable).
kind = "application" with an [entry] that is a complete, valid static_browser entry. Applications get a Launch button.
- Path C — conversational role (importable + publishable, no Launch).
kind = "role" with NO [entry] section at all. role.md is the sole behavior source: the role talks, it does not launch. The publisher accepts it exactly like an application. In the Role Library it appears as a normal selectable candidate without a Launch button.
Hard rule behind the paths, dispatched by kind:
kind = "application"—[entry]is mandatory and only
entry.kind = "static_browser" passes the contract parser. Unknown entry kinds fail loudly with ROLE_ENTRY_KIND_UNSUPPORTED.
kind = "role"—[entry]is forbidden. Declaring any[entry]fails
with ROLE_CONTRACT_FIELD_INVALID; a missing role.md fails with ROLE_BEHAVIOR_FILE_MISSING. There is no system_prompt entry kind and there never was a working one — the behavior contract is role.md itself.
Publishable examples: typing-word-game, english-conversation-teacher, visual-media-assistant Import-only examples: any Path A directory (role.md without agotalk.role.toml)
The live published examples are typing-word-game (https://roles.agotalk.com/roles/typing-word-game), a Path B application, and english-conversation-teacher (https://roles.agotalk.com/roles/english-conversation-teacher), a Path C conversational role. Their official sources live in the separate agotalk-roles repository (https://github.com/42atom/agotalk-roles), not in the Agotalk app repository. Clone it and put your package under roles/<role-id>/ — every npm run role:* command in these docs runs from that checkout.
2. Package layout
<role-id>/
role.md # REQUIRED. Role intro, boundaries, how to start. Import entry.
agotalk.role.toml # Path B/C: machine contract (identity, preview; entry for B only)
avatar.png # optional role avatar at the package root (recommended 512x512 PNG)
intro.html # optional rich presentation page (static HTML only)
skills/ # optional agent instructions (*.md). No software here.
agapps/ # optional browser apps, one subdirectory per app
contents/ # optional scripts, templates, locks, or existing apps
assets/ # optional presentation media (covers, screenshots)
Rules:
<role-id>is lowercasea-z0-9words joined by single hyphens
(example: typing-word-game). The directory name IS the role id.
skills/*.mdonly explain how to use or modifyagapps/andcontents/; they never
contain the software itself.
intro.htmlis presentation only. It never replacesrole.mdand never
declares runtime dependencies.
- Extra content directories are allowed when they serve the role (example:
english-conversation-teacher ships curriculum under resources/). Keep everything inside the package directory.
- The role avatar is a single
avatar.pngat the package root (not under
assets/), recommended 512×512 PNG. If omitted the role shows the default Agotalk avatar. Do NOT declare an avatar: field in role.md front matter — that field is retired and the import gate rejects any package still carrying it with ROLE_PACKAGE_LEGACY_AVATAR_FIELD.
3. role.md (required)
Front matter with title and description, then the role narrative: what the role does, its boundaries, and how a session should start. The Role Library shows title and summary from this file. title must describe a profession, capability, or system identity — not a person's name. Package files do not name the conversational agent; name a member in the app instead. For Path C roles this file IS the entire behavior contract — write it with care.
The only front matter keys consumed are title and description. The avatar: key is retired: the avatar is the package-root avatar.png, never a front matter value. A package whose role.md front matter still contains avatar: is rejected at import with ROLE_PACKAGE_LEGACY_AVATAR_FIELD — delete the line and place avatar.png at the package root instead.
Front matter field status (the parser is the contract):
| Key | Status | Notes |
|---|---|---|
title | consumed | Falls back to the role id (directory name) if absent/empty. |
description | consumed | Falls back to "" if absent/empty. |
id | ignored as identity | Role identity is ALWAYS the directory name (path.basename); a front matter id is tolerated but never overrides it. |
avatar | retired | Hard-rejected at import (ROLE_PACKAGE_LEGACY_AVATAR_FIELD); installed roles only log. Use package-root avatar.png instead. |
| any other key | tolerated, ignored | Unknown keys do not error; they are simply not read. Do not rely on them carrying meaning. |
4. agotalk.role.toml (machine contract)
Path B — launchable application:
schema_version = 1 # fixed
id = "typing-word-game" # must equal the top-level directory name
version = "0.1.0" # SemVer string
title = "Typing Word Game"
summary = "Typing word game bundled as role package content."
kind = "application" # dispatches the entry contract
license = "free" # v0.2: "free"
min_app_version = "0.1.57" # optional: minimum Agotalk App version
[entry] # mandatory for kind = "application"
kind = "static_browser" # the only kind that parses and publishes today
target = "agapps/word-pop-game/index.html" # relative, must stay inside the package
address_bar = "hidden" # "visible" | "hidden"
[preview]
intro_html = "intro.html"
cover_image = "assets/screenshots/word-pop-game-preview.png"
screenshots = ["assets/screenshots/word-pop-game-preview.png"]
[state]
remembers_progress = false # declare true only if the app really saves progress
[environment]
manager = "agotalk" # fixed
dependency_mode = "none" # static content needs nothing else
Path C — conversational role (note: NO [entry] section):
schema_version = 1
id = "english-conversation-teacher"
version = "0.1.0"
title = "English Conversation Teacher"
summary = "A warm but exacting English teacher."
kind = "role" # conversational: role.md is the behavior source
license = "free"
min_app_version = "0.1.57" # optional: minimum Agotalk App version
[preview]
intro_html = "intro.html"
[state]
remembers_progress = true
[environment]
manager = "agotalk"
dependency_mode = "none"
Notes:
- The entry contract is dispatched by
kind: applications must declare a
complete [entry]; conversational roles must not declare one at all.
min_app_version("x.y.z") is optional. It is shown on the role page as the
Agotalk version your package needs; declare it only if you know you rely on a specific one.
[preview]is consumed by the Agotalk App import preview, and the publisher
also projects avatar.png, preview.cover_image, and preview.screenshots into the website presentation assets (converted to WebP and served from the catalog) — package images DO drive the website. Recommended specs (not enforced by the parser): - avatar.png at the package root — 512×512, 1:1, PNG. - cover_image — 1280×720, 16:9, PNG. - screenshots — 1 to 3 images, 1280×720, 16:9, PNG. - 16:9 at 1280×720 matches og:image / Twitter card / Steam capsule conventions; authors can drop a 16:9 capture without re-cropping. - Keep each image under ~1 MB. - Avoid JPEG for screenshots (lossy edges blur text) and avoid SVG for screenshots (use SVG only for logos/icons). GIF is accepted but not recommended for detailed captures. - Keep source images PNG; the publisher converts website presentation copies to WebP automatically. Authors never pre-convert to WebP.
[i18n."<locale>"](optional) localizes the displaytitle/summaryper
locale — e.g. [i18n."zh-CN"] with exactly title and summary keys (same length limits as the top-level fields). Locale keys look like en or zh-CN; at most 8 locales. Top-level title/summary are the canonical fallback — write them in the role's primary language. The catalog and the website language pages pick the locale entry when present.
static_browseris the ONLY entry kind that exists today. Any other value
(including anything you may have seen in older drafts) fails loudly with ROLE_ENTRY_KIND_UNSUPPORTED. Do not experiment with entry kinds that are not in this guide — the parser is the contract.
- All referenced paths (
entry.target,preview.*) are relative to the
package root and must stay inside it.
schema_versionmust be exactly1andlicenseis currently locked to
"free". Any other value fails with ROLE_CONTRACT_FIELD_INVALID.
environment.managermust be exactly"agotalk".
environment.dependency_mode is "none" or "locked": - "none" — the package needs no third-party libraries. - "locked" — the package ships pyproject.toml + uv.lock at its root and Agotalk installs the declared dependencies for you. Do not write those two files by hand: npm run role:env-init -- --package roles/<role-id> --add <pkg> builds them with the same uv and Python your users run. See the contract's Dependencies section. Any entry kind that would imply a dev server or local backend is still rejected by the parser — apps ship as self-contained static builds.
5. Authoring app content and role-specific skills
This section is for Path B packages (and Path C roles that ship reference content). It describes what the app running inside Agotalk can and cannot do, and how to write the role-specific Markdown under skills/.
What the app environment can and cannot do
A static_browser app opens inside Agotalk's bundled browser view. That view is a sandboxed web page: it renders HTML/CSS/JS from files inside the package, with no access to the local machine. Specifically:
- The page has no general Node/Electron bridge and no shell access. It
cannot spawn processes, read arbitrary files, run installed tools, or start a backend / dev server.
- The page cannot reach Agotalk's bundled runtime tools (node, python,
tmux, git, ffmpeg, mise, etc.). Those tools serve the agent's workspace shell, which is a separate channel from the role-package app.
- The page may use ordinary browser APIs:
localStorage,IndexedDB,
fetch of package-relative resources, canvas, WebGL, Web Workers, service workers, FileReader, drag-and-drop, clipboard, and so on.
- The page runs fully offline at launch. Do not fetch scripts, styles,
fonts, templates, or data from a CDN or any network endpoint when the app starts — bundle everything into the package.
A local static_browser page may register a narrow, structured surface for the role agent through window.agotalk.expose(...). The role can invoke only methods that its page explicitly registers and documents. This is not a general host bridge and does not grant machine access. Read the Page Agent API contract before using it.
For a page button that should wake the role agent, supported Agotalk App builds also accept window.agotalk.post("thread_notify", { message }) from a local file page in a thread-owned tab. Save the page action first, then send the notification. In the role's role.md or skills/, tell the agent to read the page through its documented expose(...) method and write its result back through another method. A writing app, for example, can save a review request, send { message: "请点评作文" }, then have its role call observe and submit_review. Check the post result: queued confirms input acceptance, not a completed review. Show a fallback instruction when the topic is unavailable or delivery fails. Standalone tabs and external pages cannot notify a thread. The Page Agent API contract gives the full boundary and response shape.
Two different things used to be lumped together here; they have different answers:
- A local backend or dev server — still not shippable. Convert the app to a
self-contained static build (vendored libraries, build output only) before packaging.
- Third-party library dependencies — supported. Declare them with
dependency_mode = "locked" and a lockfile; Agotalk prepares the environment before your code runs. Do not write a setup step that installs them. See the contract's Dependencies section.
Note the boundary: the static_browser page itself is still a sandboxed web page with no shell access, so declared dependencies serve the agent-side code in your package (scripts under contents/bin/, tools your skills invoke), not the page.
Putting browser apps into agapps/
agapps/ is optional. A role with no browser apps does not need the directory. When present, it groups the browser pages a role can use. Each application has its own directory and self-contained resources. There is no install step at launch.
<role-id>/
agapps/
<app>/
index.html # entry.target points here
app.js # built or hand-written; vendored, not installed
style.css
vendor/ # third-party JS/CSS copied in at a pinned version
assets/ # app-local media (icons, fonts, templates)
Rules:
- If the default app lives here,
entry.targetpoints at itsindex.html. - The current manifest has one
[entry], even ifagapps/contains several
applications. Other pages need explicit paths in role.md or skills/; this folder does not automatically create app shortcuts or a dock.
- Existing apps that save browser data can stay at their original package
paths. Moving a page may change its browser storage scope; plan and verify data migration before changing its path.
- For each carried app, state a stable
agAppId, a human-readableagAppName,
its HTML path inside the package, and its purpose in role.md or a skill. These are role instructions, not extra manifest fields. A kind = "role" package may carry AGApps without adding [entry].
- After installation, the member's first-session hint says whether its AGApps
dock is established. When it is not, introduce the role, check the actual installed HTML files, then call agapps_setup with agApps entries containing agAppId, agAppName, and agAppEntryRef. The entry ref is relative to the workspace, for example .agotalk/roles/<role-id>/agapps/<app>/index.html; replace the placeholders and verify the file exists. It is not a package-relative manifest path.
``json {"agApps":[{"agAppId":"word-pop","agAppName":"Word Pop","agAppEntryRef":".agotalk/roles/<role-id>/agapps/word-pop/index.html"}]} ``
If the role carries no apps, an empty agApps list establishes an empty dock when the host asks for initialization. If the dock is already established, skip automatic initialization; later additions or changes can use the same tool when requested. agapps_setup merges by ID and preserves other entries.
- Ship the HTML, scripts, styles, vendored libraries, and assets the page needs.
Do not package a member's dock configuration or user-saved app data. The host derives each shortcut's initial and color from its name and position; the package does not need icon or color fields. A successful agapps_setup only confirms that shortcuts were saved, not that the pages opened.
- Ship the built output, not the toolchain. If you build from TS/JSX or
a bundler, the compiled bundle is what goes under agapps/<app>/; source and build instructions stay in a separate folder or repo. The package must never require npm install / pnpm install / pip install at launch.
- Third-party libraries must be vendored into
agapps/<app>/vendor/at
the exact version you tested. Record the pinned versions (a comment in index.html or a note under skills/) so the package stays auditable.
- If the app persists user data via the browser APIs above, declare
[state] remembers_progress = true only if that data actually survives a reload; otherwise leave it false.
Offering many templates: ship a numbered gallery
If your role hands the user a choice among many generated-content templates (poster layouts, video styles, report skins, prompt presets), do not describe them in prose and do not make the user read a directory listing. Ship a single self-contained HTML gallery:
contents/templates/
gallery.html # thumbnails in a grid, each tile labelled with its number
01-minimal/…
02-editorial/…
03-neon/…
- Number every entry, and make the number the thing the user says back. "用 3" is a
complete instruction; "the neon one, the third from the left" is not.
- The gallery is one HTML file that loads only package-relative assets — same offline rule
as any other packaged page. It can be opened directly, and for kind = "application" packages it can be the entry.target itself.
- Say in
role.mdhow to open it and that the user answers with a number, so the agent
offers the gallery instead of paraphrasing twenty template names into chat.
The point is bandwidth: a grid of thumbnails settles in one glance what a paragraph of descriptions cannot, and a number is the shortest unambiguous thing a user can type back.
What "Agotalk's bundled runtime" means here
Agotalk ships a curated, version-locked toolchain (node, python, pnpm, mise, tmux, git, ImageMagick, ffmpeg, rg, fd, jq, sqlite, and more) that the agent can call from its workspace shell to do real work on the user's machine. That is a powerful capability — but it belongs to the agent channel, not to the role-package app.
- A Path B/C role's
skills/*.mdcan instruct the agent to use those tools
to maintain, regenerate, or extend the app's agapps/ files (for example, "rebuild the bundle with pnpm build", "generate sprites with ImageMagick"). The agent runs these in its workspace shell.
- The app's own page (what the Launch button opens) cannot call them. Keep
these two channels separate in your design: the agent maintains the artifact, the browser view runs it.
Writing role-specific skills
skills/*.md are Markdown instructions that tell the agent how to use or modify the agapps/ or contents/ shipped with this role. They are NOT software. Put one Markdown file per distinct job, named after the job.
<role-id>/
skills/
<job-name>.md # one file per job; e.g. rebuild-bundle.md, export-data.md
Each file should state: the job, the exact files or UI it touches, the step sequence (including any bundled tools the agent should call from its workspace shell), and how to verify it worked. Keep them short and concrete — they are read by an agent at session time.
Hard rule (repeated from §2): skills/ holds only Markdown. Any executable, script, stylesheet, image, or binary belongs in agapps/, contents/, or assets/, never in skills/.
6. What publishing consumes
The official publisher runs the full contract parse dispatched by kind (Path B and Path C both pass; Path A has no contract file and cannot publish), then the catalog and website use: id, version, title, summary, min_app_version (from the manifest or explicit publisher input), plus the computed zip sha256 and sizes. Website preview media is curated on the site side. Publication itself happens through the official publisher pipeline; this guide only defines the package you hand over.
7. Transport zip
typing-word-game-0.1.0.zip
typing-word-game/
role.md
agotalk.role.toml
avatar.png
intro.html
skills/
agapps/
contents/
assets/
Rules:
- The zip contains exactly one single top-level directory named
<role-id>. - Zip name convention:
<role-id>-<version>.zip. - Plain zip, regular files only: no symlinks, no absolute paths, no
..
entries, no .DS_Store.
- The zip is a transport container, not a second manifest.
Import behavior you must expect: Agotalk unpacks the zip into the local Role Library (roles-lib) as a candidate, validates role.md, and shows the candidate. Importing an id that already exists is rejected with ROLE_IMPORT_DUPLICATE — versions never silently overwrite. A candidate never becomes the active workspace role without explicit user action.
8. Hard boundaries
- The user's machine is never a dependency source. A
static_browserpage may rely only on
bundled browser capabilities and package files. Agent-side code may additionally rely on the environment Agotalk prepares from dependency_mode = "locked".
- **Secrets, tokens and API keys must never be put into a package you intend
to publish.** A published package is public — anything inside it is exposed. If you are building a package strictly for your own local use and you choose to embed your own keys, that is your call and your risk; but such a package must not be published through the official pipeline. The official publisher does not scan for secrets, so the discipline is yours.
- Never rely on network calls at launch time for a
static_browserapp. - Never auto-activate the role or instruct Agotalk to bypass user confirmation.
- When a fact you need is missing (id, version, entry target), stop and say so
loudly. Do not guess silently.
9. Generation instruction (hand this to an agent)
Create an Agotalk role package.
1. Read https://roles.agotalk.com/role-package-creator.md fully first.
2. Pick the capability path: launchable web app for the website -> Path B
(kind = "application" with a static_browser [entry]); conversational role
for the website -> Path C (kind = "role", role.md as behavior, NO [entry]);
local-only experiment -> Path A (role.md, NO agotalk.role.toml).
3. Choose <role-id> (lowercase a-z0-9 and hyphens) and create the directory <role-id>/.
4. Write role.md: front matter (title, description), then the role narrative,
boundaries, and session start guidance. For Path C this file is the whole
behavior contract.
5. If the role ships a browser app, put it under agapps/<app>/ unless an existing
app must keep its path for saved data. In role.md or a skill, name each app's
stable agAppId, agAppName, HTML path, and purpose; explain first-session
agapps_setup using the installed workspace-relative HTML path. No apps means
no agapps/ directory is needed. Put other real content under contents/,
agent how-to notes under skills/, and presentation media under assets/.
6. Path B/C: add agotalk.role.toml exactly as specified above. Path B needs a
complete [entry] with an existing HTML target inside the package; Path C
must not contain any [entry] section.
7. Zip as <role-id>-<version>.zip with the single top-level directory <role-id>/.
8. Run the self-check below. Fix every failure before delivering. If a required
fact is unknown, report it instead of inventing it.
10. Self-check before delivery
- [ ] Zip holds exactly one top-level directory; its name equals
idin
agotalk.role.toml (when present).
- [ ]
<role-id>/role.mdexists and carries title + description front matter. - [ ]
role.mdfront matter does NOT contain anavatar:key (retired).
The avatar, if any, is a package-root avatar.png (recommended 512x512 PNG). An avatar: line inside the role narrative body is fine; only the front matter block is gated.
- [ ] Path A packages have NO
agotalk.role.toml. Path B packages have a
complete [entry] with kind = "static_browser" and an existing .html target inside the package. Path C packages declare kind = "role" and contain NO [entry] section at all.
- [ ]
schema_versionis exactly1,licenseis exactly"free", and
environment.manager is exactly "agotalk". These three are fixed today; any other value fails the contract.
- [ ]
environment.dependency_modeis"none"or"locked". If"locked":
uv.lock and pyproject.toml sit at the package root. Do not "fix" a locked package back to "none" to pass this checklist — that silently drops the dependency declaration.
- [ ] Every path referenced by
agotalk.role.tomlexists inside the package
(entry.target, intro_html, cover_image, every screenshot).
- [ ] If you provide preview media, follow the recommended specs: avatar
512×512 1:1 PNG, cover + screenshots 1280×720 16:9 PNG, each image under ~1 MB. If the website needs WebP, convert curated website media in the website release chain; the role package source contract stays PNG. (Not enforced by the parser.)
- [ ]
min_app_version(when present) is a plainx.y.zstring. - [ ] No symlinks, no absolute paths, no
.., no.DS_Store. - [ ] If you plan to publish: no secrets, tokens or API keys anywhere in the
package. Local-only packages are your own risk but must not be published.
- [ ]
skills/contains only Markdown instructions; browser apps live inagapps/
(existing apps may retain their original paths), and other software lives in contents/.
- [ ] For every carried AGApp,
role.mdor a skill names its stable ID, display
name, HTML path, and purpose. All HTML, JS, CSS, and local assets are in the package; member dock configuration and user data are not.
- [ ] In an installed workspace, follow the host's unestablished-dock hint to
register the real workspace-relative HTML paths with agapps_setup. Verify that each shortcut appears, click it, and complete one real page action. For a page with saved work, close and reopen it to verify recovery. A successful setup response alone is not a page-open test.
- [ ] Stable failure codes you may see and must not paper over:
ROLE_IMPORT_ROLE_MD_MISSING, ROLE_IMPORT_DUPLICATE, ROLE_PACKAGE_LEGACY_AVATAR_FIELD, ROLE_CONTRACT_MISSING, ROLE_CONTRACT_INVALID, ROLE_CONTRACT_FIELD_MISSING, ROLE_CONTRACT_FIELD_INVALID, ROLE_BEHAVIOR_FILE_MISSING, ROLE_ID_DIR_MISMATCH, ROLE_ENTRY_KIND_UNSUPPORTED, ROLE_ENTRY_ADDRESS_BAR_INVALID, ROLE_ENTRY_TARGET_NOT_FOUND, ROLE_ENTRY_TARGET_NOT_FILE, ROLE_ENTRY_TARGET_OUTSIDE_PACKAGE, ROLE_ENVIRONMENT_INVALID, ROLE_PREVIEW_INVALID, ROLE_PREVIEW_NOT_FOUND, ROLE_PREVIEW_NOT_FILE, ROLE_PREVIEW_OUTSIDE_PACKAGE, ROLE_STATE_REMEMBERS_PROGRESS_INVALID, ROLE_IMPORT_ZIP_TOP_LEVEL_INVALID, ROLE_IMPORT_ZIP_ENTRY_INVALID, ROLE_KIND_NOT_LAUNCHABLE.