/docs / platform / packaging

Packaging & Marketplace

This guide covers the packaging format for all Nebo marketplace artifacts, artifact naming, and the artifact hierarchy.

Hierarchy

APP  >  AGENT  >  WORK  >  SKILL
(UI)   (job)   (procedure) (knowledge + actions)

This is the design direction — the order in which you think about building. Start with knowledge and actions (Skill), chain those into procedures (Workflow), compose procedures into a job (Agent), and add a dedicated UI when chat isn't enough (App). The > represents conceptual priority, not a runtime dependency.

Each layer auto-installs its dependencies downward:

  • App — an Agent with a frontend UI and optional sidecar binary
  • Agent — installs Workflows and Skills declared in agent.json
  • Workflow — installs Skills declared in workflow.json dependencies
  • Skill — leaf node. No dependencies to auto-install.

Plugins are shared native binaries that bundle skills and provide platform capabilities (Google Workspace CLI, browser automation, etc.). They sit alongside the hierarchy — skills and agents declare which plugins they need.

Platform Capabilities (storage, network, vision, calendar, email, browser) are provided by Nebo itself — they are infrastructure, not marketplace artifacts. Skills declare which capabilities they need; the platform provides them. See Platform Capabilities.

Artifact Naming

Every artifact has two identifiers: a qualified name (canonical, for engineering) and an install code (alias, for sharing).

Qualified Names

The qualified name is the canonical identifier for every artifact. It is human-readable, org-scoped, type-aware, and versioned.

Format: @org/type/name@version

@acme/skills/sales-qualification@1.0.0
@acme/skills/crm-lookup@1.0.0
@acme/workflows/lead-qualification@2.1.0
@nebo/agents/executive-assistant@1.0.0

Read left to right: who published it, what kind of artifact it is, what it's called, what version.

SegmentDescriptionRules
@orgPublisher org (scoped)Lowercase, alphanumeric + hyphens
typeArtifact typeskills, workflows, agents
nameArtifact nameLowercase, alphanumeric + hyphens
@versionSemver version (optional)Omit for latest; supports semver ranges

Version Resolution

ReferenceResolves To
@acme/skills/crm-lookupLatest published version
@acme/skills/crm-lookup@1.0.0Exact version 1.0.0
@acme/skills/crm-lookup@^1.0.0Compatible with 1.0.0 (>=1.0.0 <2.0.0)
@acme/skills/crm-lookup@>=1.0.0Any version 1.0.0 or higher

Semver range semantics follow npm conventions. Exact versions pin to a specific release. Caret (^) allows patch and minor updates. Tilde (~) allows patch updates only.

Namespacing: Two publishers can build artifacts with the same name without collision:

@acme/skills/crm-lookup
@nebo/skills/crm-lookup

Different artifacts, no conflict. The org scope prevents name collisions as the marketplace grows.

Install Codes (Aliases)

Install codes are short, shareable aliases assigned by the marketplace. They exist for one purpose: so a non-technical user can text a code to a friend and have it work.

Format: PREFIX-XXXX-XXXX — Crockford Base32, case-insensitive.

PrefixArtifactExample
NEBOLink bot to NeboAI accountNEBO-A1B2-C3D4
SKILInstall a skillSKIL-R7KP-2M9V
WORKInstall a workflowWORK-5TG2-XBJK
AGNTInstall an agentAGNT-SNTW-WY0B
APPSInstall an appAPPS-3FKT-7WNP
COLLInstall a collection (bundle of artifacts)COLL-9DCE-4MPA
CONNInstall a connector (MCP)CONN-4HVT-8KRP
LOOPJoin bot to a LoopLOOP-7YSR-6WN3
PLUGInstall a pluginPLUG-4HVT-8KRP

Install codes always resolve to @latest. They are detected case-insensitively in chat messages and dispatched automatically.

Install codes are marketing artifacts. Qualified names are engineering identifiers. Inside workflow.json, agent.json, dependency declarations, and all structured data — use qualified names. Install codes are for users, not for code.

Package Format

Skills — Directory Format (Agent Skills Standard)

Skills follow the Agent Skills standard. A skill is a directory containing a SKILL.md file and optional supporting resources. No manifest.json is required — the SKILL.md frontmatter is the source of truth.

skill-name/
├── SKILL.md           # Required — YAML frontmatter + markdown instructions
├── scripts/           # Optional — executable scripts (Python, TypeScript)
├── references/        # Optional — docs loaded on demand
├── assets/            # Optional — templates, images, fonts
└── examples/          # Optional — sample data, examples

Skills from Anthropic, OpenAI, OpenClaw, and other Agent Skills-compatible platforms can be installed directly with no modification. See Skills for the full format spec.

Apps — Agent + Frontend UI

Apps are agents with their own UI. They use the agents qualified name type with "type": "app" in their manifest.

my-app/
├── AGENT.md              # Required — persona + instructions
├── manifest.json         # Required — identity, permissions, window config
├── agent.json            # Optional — workflows, skills, pricing
├── ui/                   # Required — static frontend
│   ├── index.html
│   ├── style.css
│   └── app.js
└── sidecar/              # Optional — native backend binary

The manifest.json extends the standard agent manifest with app-specific fields:

{
  "id": "deal-tracker",
  "name": "@acme/agents/deal-tracker",
  "version": "1.0.0",
  "description": "Track real estate deals with AI-powered analysis.",
  "type": "app",
  "permissions": ["storage:readwrite", "subagent:invoke", "network:outbound"],
  "window": {
    "title": "Deal Tracker",
    "width": 1024,
    "height": 768,
    "resizable": true
  }
}
FieldDescription
typeOptional. Set to "app" to distinguish an app from a regular agent (drives UI window handling)
permissionsCapabilities the app requires (storage, network, subagent, etc.)
windowDefault window dimensions and title for the desktop app

Workflows and Agents — .napp Archive

Workflows and agents are distributed as .napp files — signed tar.gz archives.

@acme/workflows/lead-qualification-1.0.0.napp
  → manifest.json
  → workflow.json
  → WORKFLOW.md

@nebo/agents/executive-assistant-1.0.0.napp
  → manifest.json
  → agent.json
  → AGENT.md
  → skills/
  →   skills/crm-lookup/SKILL.md

.napp Envelope Format

Every .napp file wraps the inner tar.gz in a binary envelope that is verified before the payload is touched:

[4B magic "NAPP"] [1B version 0x01] [64B ED25519 signature] [32B SHA256 hash] [payload...]

Verification order:

  • SHA256 — cheap integrity check of the payload bytes.
  • ED25519 — proves the archive was signed by NeboAI. The signature covers hash || payload.

The NeboAI public key is embedded at compile time so verification works offline (first launch, air-gapped installs). A SigningKeyProvider also fetches the key from GET /api/v1/apps/signing-key with a 24-hour cache for key rotation.

Sealed Archives

For workflows and agents, the .napp is never extracted. Nebo reads files directly from the archive at runtime. The signed archive is the running artifact — if someone tampers with the file, the next read fails signature verification. This provides continuous integrity, not just point-in-time verification at install.

ArtifactStorageIntegrity Model
SkillDirectory on disk (marketplace: sealed .napp)Frontmatter is source of truth; marketplace archives are signed
Workflow.napp sealedArchive is the signed artifact — continuous integrity
Agent.napp sealedArchive is the signed artifact — continuous integrity
AppDirectory (dev) / .napp sealed (marketplace)Same as agent — includes ui/ directory contents

License-Key Sealed Archives

Paid marketplace artifacts use an additional encryption layer on top of the .napp envelope. After envelope verification, the inner payload is AES-256-GCM encrypted with a per-artifact license key:

.napp envelope  →  unwrap (verify ED25519 + SHA256)  →  sealed payload  →  unseal (AES-256-GCM)  →  plain tar.gz

Key derivation: derive_license_key(master_secret, artifact_id) uses HKDF-SHA256 with the artifact ID as salt and neboai-license-v1 as info. The same key works regardless of who holds the license — authorization is server-side, so .napp files never need re-download on license transfer.

Detection: Plain .napp payloads start with gzip magic bytes (0x1f 0x8b). Sealed payloads start with a 12-byte random nonce, which won't match. is_sealed() checks this.

Partial extraction: For sealed skill archives, only executables (scripts/, bin/, binary) and metadata (manifest.json, plugin.json, signatures.json) are extracted to disk. IP-sensitive files (SKILL.md, references, assets) stay inside the sealed .napp and are read in memory at runtime — plaintext never touches disk.

Versioned Storage

Artifacts are stored by qualified name and version:

nebo/                                    # From NeboAI marketplace
  skills/
    @acme/skills/sales-qualification/
      1.0.0.napp
      1.1.0.napp
  workflows/
    @acme/workflows/lead-qualification/
      1.0.0.napp
  agents/
    @nebo/agents/executive-assistant/
      1.0.0.napp

user/                                    # User-created (dev/sideload path)
  skills/
    my-custom-skill/
      SKILL.md                           # Loose directory — no archive
      scripts/
      references/
  agents/
    my-agent/
      agent.json
      AGENT.md
      skills/
    my-app/
      manifest.json                      # type: "app"
      AGENT.md
      ui/
        index.html
      sidecar/

Marketplace artifacts (nebo/) are sealed .napp files. Signed, versioned, read from archive at runtime.

User artifacts (user/) are loose files on disk. No archive, no signatures. This is the development path — edit directly, hot-reload picks up changes.

Runtime Data — appdata/

Artifact runtime data (databases, caches, user files) lives in a completely separate tree:

appdata/                                 # Runtime data — NEVER touched by updates
  plugins/
    gws/                                 # Plugin data (survives all version upgrades)
      cache.db
      sidecar.log
  skills/
    my-custom-skill/                     # Skill data (survives reinstalls)
      output.json
  agents/
    deal-tracker/                        # Agent app data (survives upgrades)
      deals.db
      sidecar.log

This follows the iOS model: code and data live in physically separate containers. The update system operates on nebo/ and user/ but never touches appdata/. Artifacts own their data and are responsible for their own schema migrations across versions.

Version Resolution

When a qualified name with a version range is referenced, the resolution logic is:

  • Scan installed versions under that qualified name
  • Pick the highest version satisfying the semver range
  • If nothing matches, fetch from NeboAI marketplace
  • If fetch fails and nothing is installed, error

This resolution applies everywhere a versioned qualified name appears — workflow dependencies, activity skills arrays, agent workflows refs, and agent-level skills arrays.

manifest.json

Workflows, agents, and apps ship a manifest.json as their marketplace identity envelope. Skills do not use manifest.json — their identity comes from SKILL.md frontmatter.

{
  "name": "@acme/workflows/lead-qualification",
  "version": "1.0.0",
  "description": "Qualifies inbound leads through research, scoring, and routing",
  "signature": {
    "algorithm": "ed25519",
    "key_id": "nebo-prod-2026"
  }
}

Fields

FieldTypeRequiredDescription
namestringyesQualified name: @org/type/artifact-name
versionstringyesSemantic version
descriptionstringnoShort description
tagsstring[]noCategorization tags
signatureobjectnoED25519 signing metadata

The name field is the canonical identifier. The org, type, and artifact name are all parsed from it. There is no separate id, type, or author field — the qualified name carries all of that.

Install codes are not part of the package. They are assigned by NeboAI when the manifest is submitted and are stored server-side as an alias that resolves to the qualified name. The publisher never sets the code — they submit their package and NeboAI assigns one.

Separation of Concerns

Each artifact type has a clear split between identity, domain logic, and prose:

  • SkillsSKILL.md frontmatter (identity + runtime config) + body (knowledge) + optional bundled resources. No manifest.json. Compatible with the Agent Skills standard.
  • Workflowsmanifest.json (marketplace identity) + workflow.json (procedure definition) + WORKFLOW.md (agent docs). Sealed archive.
  • AgentsAGENT.md (persona prose, the only required file) + optional agent.json (event bindings, pricing, defaults, sidecar tools, scopes, memory config) + optional manifest.json (marketplace identity) + optional bundled skills. Sealed archive.
  • Apps — everything an Agent has + "type": "app" in manifest + ui/ directory (static frontend) + optional sidecar binary.

Quick Reference

Timeout Constants

OperationTimeout
Hook call500 ms
Hook circuit breaker3 consecutive failures
Hook circuit breaker recovery5 minutes
Signing key cache24 hours
Revocation cache1 hour
Plugin tool default timeout120 seconds
Plugin max timeout (permissions)300 seconds

Qualified Name Format

@org/type/name@version — org and name are lowercase alphanumeric + hyphens. Type is one of: skills, workflows, agents. Version follows semver.

Install Code Format

PREFIX-XXXX-XXXX — Crockford Base32, case-insensitive. Always resolves to @latest.

Prefixes: NEBO, SKIL, WORK, AGNT, APPS, COLL, CONN, LOOP, PLUG