App Store
The App Store is the distribution and runtime layer for Operaide Apps. As a developer, it is how your code gets from npm publish to a running App Instance — and how other developers discover and build on your work.
The App Store is the package registry, deployment pipeline, and runtime host rolled into one. If you want to understand how your code is structured and executed, see Aktor Framework.
Architecture Overview
The App Store connects four key entities:
- AppDefinition — the immutable package stored in the registry. One entry per
packageName@version. Contains the TypeScript source files,package.jsonmetadata, and integrity hashes. - App Instance — a named, per-organization installation of an AppDefinition. Multiple instances of the same package can coexist with different configurations.
- Deployment — a configured, running instance of a single ReaktorDefinition. Each App Instance owns one Deployment per Reaktor registered by the App.
- ReaktorDefinition — the async function your
main.tsregisters viaregisterReaktorDefinition().
Package Format
Every App is a standard npm package. The naming convention is mandatory:
operaide-app-<name> # must match ^operaide-app-[a-z0-9-]+$
Minimal package.json:
{
"name": "operaide-app-my-workflow",
"version": "1.0.0",
"description": "My custom workflow",
"main": "src/main.ts",
"peerDependencies": {
"@operaide/aktor": "^0.5.7"
},
"operaide": {
"category": "custom",
"quality": "reference"
}
}
The peerDependencies on @operaide/aktor controls compatibility: the platform checks this semver range against its own version and blocks installation if they don't match.
The operaide field carries metadata for the App Store UI:
| Field | Values | Purpose |
|---|---|---|
category | core, custom, ... | Grouping in the UI |
quality | reference, template, experimental, needs-review, uncataloged | Signals maturity level |
notes | free text | Shown in the details drawer |
Publishing
Two paths to get your App into the App Store:
Via npm publish (recommended)
Point your .npmrc at the Operaide registry and publish like any npm package:
# .npmrc
registry=https://your-operaide-instance/api/v1/registry
//your-operaide-instance/api/v1/registry/:_authToken=${OPERAIDE_DEPLOY_API_KEY}
npm publish
The API key must carry the NPM Registry Publisher role (or a role that implies it, such as App Developer). Keys without it get 403 Forbidden on publish. Issue a reader-only key with NPM Registry Reader for pull-only CI that runs npm install but never publishes.
The App appears in the App Store immediately after publishing.
Dependencies from external registries
If your App depends on libraries hosted on a private npm registry (e.g. shared operaide-* libraries on another Operaide instance, a Verdaccio server, or GitHub Packages), the Operaide instance must be configured to forward requests to that upstream. This is an administrator task — see Upstream NPM Registry for the required environment variables (NPM_UPSTREAM_REGISTRY_URL, NPM_UPSTREAM_REGISTRY_AUTH_TOKEN).
As a developer, you do not need to configure .npmrc for upstream resolution. When you npm publish your App, the platform resolves dependencies from the configured upstream at install time. If a dependency cannot be found, the App installation fails with a missing-package error — ask your administrator to verify the upstream registry configuration.
Via Direct Deploy
For faster iteration during development:
npm run deploy # one-shot upload
npm run deploy-watch # watches for changes, re-deploys automatically
This sends your source files directly to POST /api/v1/deploy-reaktor, bypassing the npm packaging step. Useful during active development, but npm publish is the canonical distribution path.
Code Loading and Sandbox
When an App is installed, the platform automatically transpiles your TypeScript and runs it in an isolated sandbox. Only a fixed set of modules is available — you cannot add arbitrary npm packages beyond this list:
| Category | Modules |
|---|---|
@operaide/* | aktor, ai, document, database, vector, mail |
| npm packages | ai, axios, zod, pdf-lib, @libsql/client, fast-xml-parser, @modelcontextprotocol/sdk |
| Node.js builtins | node:buffer, node:crypto, node:path, node:stream, node:url, node:util |
Other operaide-* | Any published operaide-* package (as library dependency) |
Your registerReaktorDefinition() calls are intercepted and prefixed with the App ID to avoid naming collisions across Apps.
You can expose configuration to the person installing your App via registerAppSettings() with a Zod schema. These settings are editable per App Instance and available at runtime through getAppInstanceSettingsForReaktor().
App Instance Lifecycle
Installation
From the App Store UI, clicking Install opens a three-step wizard:
- Select App — version, instance name (
URL-safe, unique per org), optional display label - App Settings — form generated from your
registerAppSettings()schema - Deploy — creates the App Instance and all Deployments
Runtime
Each Reaktor in an App Instance is exposed via REST:
GET|POST /api/v2/orgs/{orgId}/apps/{instanceName}/reaktors/{reaktorName}
App Instance status transitions: deploying → active (or error). Instances can be stopped and restarted.
Updating
methodUpdateInstanceVersion handles version upgrades by diffing old vs. new ReaktorDefinitions: it adds new Reaktors, removes deleted ones, and updates existing Deployments in place.
Uninstalling
Removes all Deployments, their settings, and the App Instance document. The AppDefinition in the registry remains untouched — other organizations or future installs can still use it.
You can install the same App multiple times with different names and configurations. This is useful for running the same workflow against different AI providers, datasets, or customer-facing configurations.
Core Apps vs. Custom Apps
Every Operaide installation ships with Core Apps (op-core-*) — reference implementations like Basic Chat, Knowledge Chat, and Web Search. These are automatically published to the registry on startup from the bundled operaide-packages/ directory.
As a developer, Core Apps serve as working examples. You can open any Core App in Studio (via the Open in Studio action) to read the source, understand patterns, and use them as a starting point for your own Apps.
Quick Reference
| What | Where |
|---|---|
| App Store UI | Bottom menu → "App-Store" |
| App Instances list | Bottom menu → "App Instances" |
| Package naming | operaide-app-<name> (lowercase, hyphens only) |
| Runtime API | /api/v2/orgs/{orgId}/apps/{instanceName}/reaktors/{reaktorName} |
For CI/tooling use:
| What | Endpoint |
|---|---|
| Publish to registry | PUT /api/v1/registry/:name |
| Direct deploy | POST /api/v1/deploy-reaktor |
| Download source (Studio) | GET /api/v1/download-reaktor-code/:id |