Manifest spec

manifest.json is the technical contract that lets asset packs enter the solution network

Creators, buyers, Agents, delivery services, and local runners use the manifest to understand what an asset pack is, how it runs, which credentials it needs, what it outputs, and how it can be reused as a solution component. Relicex uses one unified standard, relicex.pack.v0, with kind selecting memory, experience, or capability packs.

One unified standardThree kindsSolution component layer

One standard, three pack kinds

Do not treat memory, experience, and capability packs as three incompatible manifest formats. They are relicex.pack.v0 variants selected by kind.

memory_pack

Long-term memory, project history, preferences, context, and factual material.

experience_pack

Workflows, methods, templates, prompts, examples, and best practices.

capability_pack

Executable capabilities, tools, workflows, input/output schemas, and evaluation.

How it connects to solutions

The manifest does not own pricing or sales, but it tells Relicex what role an asset pack can play inside a solution. Solution pages, checkout, and settlement use these technical facts to explain capability, entitlement, and reuse boundaries.

asset_kind

memory / experience / capability identifies the pack's base kind.

component_role

Solution composition can describe whether it acts as a data source, workflow, agent skill, evaluation, template, or runnable capability.

entitlement_policy

Whether a solution purchase grants standalone asset entitlement is decided by checkout and solution composition.

Core fields

All packs should use the same top-level field model. Listing price, supply, publication status, and solution composition do not belong in the manifest; they live in marketplace records, solution records, and checkout quotes.

api_version

Always relicex.pack.v0.

kind

memory_pack, experience_pack, or capability_pack.

id / version

Stable package identity and version.

title / description

Human- and Agent-readable summary.

runtime

Execution entrypoint for runnable packs; usually null otherwise.

files

Index of README, code, templates, examples, and assets.

manifest.json
{
  "api_version": "relicex.pack.v0",
  "kind": "capability_pack",
  "id": "my_pack",
  "version": "0.1.0",
  "title": "My Pack",
  "description": "What this pack does.",
  "author": { "name": "creator", "id": "creator_id" },
  "tags": ["capability"],
  "mode": "code",
  "runtime": {
    "kind": "interpreted",
    "profile": "python311-base@1",
    "entry": { "kind": "python", "value": "code/main.py:run" }
  },
  "inputs_schema": { "type": "object" },
  "outputs_schema": { "type": "object" },
  "files": { "readme": "README.md", "code": ["code/main.py"] },
  "secret_requirements": [],
  "secret_groups": [],
  "runtime_permissions": {
    "network": { "required": false, "allow_domains": [] },
    "filesystem": { "reads": ["./inputs"], "writes": ["./outputs", "./artifacts", "./logs", "./tmp"] }
  },
  "redaction": { "enabled": true, "patterns": [] }
}

How runtime credentials are declared

A pack only declares what credentials it needs. It must never contain real API keys, tokens, passwords, or private keys. The key matching field is placement[].name.

One name connects three places

manifest.secret_requirements[].placement[].name = the buyer Credential Vault credential name / env name = the environment variable injected by the runner.

placement[].nameCredential Vault env_namerunner env
secret_requirements
{
  "secret_requirements": [
    {
      "id": "openai_api_key",
      "label": "OpenAI API Key",
      "provider": "openai",
      "type": "api_key",
      "required": true,
      "sensitive": true,
      "description": "Used by this package to call OpenAI.",
      "placement": [{ "type": "env", "name": "OPENAI_API_KEY" }]
    }
  ]
}
One credential = one environment variable name = one real value.
Direct Resolve matches by env_name first.
No match asks the user to add a credential; multiple matches ask the user to bind one in package credential configuration.
provider and type are metadata and legacy fallbacks, not the primary matching key.

Capability runtime I/O folders

inputs_schema and outputs_schema are the primary contract. When a capability reads user files or generates Markdown, CSV, PDF, images, or other non-JSON artifacts, use the standard runtime workspace so runners, Agents, and users can find results consistently.

runtime workspace
relicex_runs/<package_name>_<timestamp>/
├── inputs/
│   ├── input.json
│   └── files/
├── outputs/
│   └── result.json
├── artifacts/
├── logs/
└── tmp/
inputs/input.json and outputs/result.json must be JSON objects matching inputs_schema / outputs_schema.
Large user-provided files go under inputs/files/; generated reports, charts, CSV, PDF, and images go under artifacts/.
Output JSON must reference artifacts by relative paths such as artifacts/report.md.
Do not use absolute paths, ~, ../ traversal, or unredacted logs.

Multiple credentials and provider choices

If one service needs multiple values, do not add a credential_bundle field. Declare multiple secret_requirements and use secret_groups to express configuration rules.

all_of

all_of means all listed credentials must be configured, such as BYBIT_API_KEY + BYBIT_API_SECRET.

multiple requirements
{
  "secret_requirements": [
    {
      "id": "bybit_api_key",
      "label": "Bybit API Key",
      "provider": "bybit",
      "type": "api_key",
      "required": true,
      "sensitive": true,
      "placement": [{ "type": "env", "name": "BYBIT_API_KEY" }]
    },
    {
      "id": "bybit_api_secret",
      "label": "Bybit API Secret",
      "provider": "bybit",
      "type": "api_secret",
      "required": true,
      "sensitive": true,
      "placement": [{ "type": "env", "name": "BYBIT_API_SECRET" }]
    }
  ],
  "secret_groups": [
    {
      "id": "bybit_credentials",
      "label": "Bybit API credentials",
      "mode": "all_of",
      "required": true,
      "members": ["bybit_api_key", "bybit_api_secret"]
    }
  ]
}

one_of

one_of means the user chooses one service, such as OpenAI or Anthropic.

provider choices
{
  "secret_groups": [
    {
      "id": "llm_provider",
      "label": "LLM Provider",
      "mode": "one_of",
      "required": true,
      "options": [
        { "id": "openai", "label": "OpenAI", "members": ["openai_api_key"] },
        { "id": "anthropic", "label": "Anthropic", "members": ["anthropic_api_key"] }
      ]
    }
  ]
}

Legacy fields and safety boundaries

Older packs may contain requires.secret_slots. It remains compatibility-only; new packs should use secret_requirements.

Active starter templates no longer include requires.secret_slots.
If secret_requirements is present, it is the source of truth for credential declarations.
Do not put price, supply, listing status, or publication visibility in manifest.
Do not package .env, .relicex, private keys, cookies, or real credential values.

Relicex

What should creators do next?

Start from a starter template, then validate the manifest with relicex_skill validate_pack.