Skip to Content
ExtendingPlugin Manifest

Plugin Manifest

Every plugin requires a pandora.manifest.json at its package root. This file declares the plugin’s identity, what it provides, and what it needs to run. Pandora reads the manifest to discover, validate, and load plugins automatically.

Example

{ "manifestVersion": 1, "id": "@pandorakit/weather", "name": "Weather", "description": "Get current weather for any city", "author": "You", "version": "0.1.0", "license": "MIT", "pandora": ">=0.0.1", "provides": { "tools": { "entry": "./src/index.ts", "sandbox": "compartment", "permissions": { "network": ["api.openweathermap.org"], "env": ["OPENWEATHER_API_KEY"] } } }, "envVars": [{ "name": "OPENWEATHER_API_KEY" }], "configFields": [ { "key": "units", "label": "Units", "type": "enum", "options": [ { "value": "metric", "label": "Metric" }, { "value": "imperial", "label": "Imperial" } ] } ] }

Metadata

FieldTypeRequiredDescription
manifestVersion1YesSchema version. Currently always 1.
idstringYesUnique plugin identifier. Use your npm package name (e.g. @pandorakit/weather). Must not contain colons.
namestringYesHuman-readable display name shown on the Plugins page.
descriptionstringNoShort description of what the plugin does.
authorstringNoAuthor name.
iconstringNoIcon URL or reference.
versionstringNoPlugin version (semver).
homepagestringNoHomepage URL.
repositorystringNoSource code repository URL.
licensestringNoLicense identifier (e.g. MIT).
pandorastringYesSemver range specifying compatible Pandora versions (e.g. >=0.0.1).

The id field should match your npm package name. This ID is used for namespacing — all tools, agents, and channels are registered as pluginId:entityId.

Provides

The provides object declares what your plugin contributes. Each key maps to a capability type:

{ "provides": { "tools": { ... }, "agents": [{ ... }], "channels": { ... } } }

Each capability accepts either a single entry object or an array of entries.

Tool / Channel Entry

FieldTypeRequiredDescription
entrystringYesRelative path to the entry module (e.g. ./src/index.ts).
sandbox'compartment' | 'host'NoExecution mode. compartment (default) runs sandboxed with no capabilities by default. host gives full process access.
permissionsobjectNoCapabilities granted in compartment mode. Ignored in host mode.
requireApprovalbooleanNoDefault approval requirement for all tools in this entry.

Agent Entry

FieldTypeRequiredDescription
entrystringYesPath to the file that exports the agent definition.
useToolsstring[]NoTool IDs from the global registry. Use fully-qualified names: pluginId:toolId.
modelToolsstring[]NoModel-native capability keys (e.g. "search" for the provider’s built-in web search).

Permissions

Compartment-sandboxed tools declare what they need. All capabilities are off by default:

PermissionTypeWhat it grants
timebooleanAccess to Date, Date.now(), and Intl.DateTimeFormat.
networkstring[]fetch scoped to declared hostnames only (e.g. ["api.example.com"]). SSRF-protected.
envstring[]Access to declared environment variable keys only (snapshot at load time).
fsstring[]Filesystem read access scoped to declared path prefixes only.
randombooleanAccess to Math.random(). Cryptographic randomness is never available in compartments.
{ "permissions": { "time": true, "network": ["api.openweathermap.org"], "env": ["API_KEY"], "random": true } }

Environment Variables

The envVars array declares environment variables the plugin depends on:

{ "envVars": [ { "name": "OPENWEATHER_API_KEY" }, { "name": "OPTIONAL_KEY", "required": false } ] }
FieldTypeRequiredDescription
namestringYesEnvironment variable name.
requiredbooleanNoWhether this variable is required. Defaults to true.

Plugins with missing required env vars are skipped at load time.

Config Fields

The configFields array declares user-configurable settings that render on the Plugins page:

{ "configFields": [ { "key": "units", "label": "Temperature Units", "type": "enum", "description": "Choose metric or imperial", "options": [ { "value": "metric", "label": "Metric (°C)" }, { "value": "imperial", "label": "Imperial (°F)" } ] }, { "key": "maxResults", "label": "Max Results", "type": "number", "placeholder": "10" } ] }
FieldTypeRequiredDescription
keystringYesField key in the config object passed to your plugin.
labelstringYesHuman-readable label shown in the UI.
type'text' | 'number' | 'password' | 'enum'YesInput type. enum renders a dropdown select.
requiredbooleanNoWhether the field is required.
placeholderstringNoPlaceholder text for the input.
descriptionstringNoHelp text shown below the input.
options{ value: string; label: string }[]NoAllowed values for type: 'enum'.

Plugins with missing required config fields are skipped until the user fills them in on the Plugins page.

Last updated on