Skip to content

Manifest Reference

Every component package contains two files in a warmhub/ directory:

  • component.json — Component identity (id, name, version)
  • manifest.json — Declarative resource definitions

Both are validated at install time. You can also validate offline with wh component validate <path>.

Add the $schema field to get IDE autocomplete and inline validation:

{
"$schema": "https://docs.warmhub.ai/schema/component-manifest.v1.json",
"component": { ... },
...
}
{
"id": "com.warmhub.MyComponent",
"name": "my-component",
"version": "1.0.0",
"description": "Optional description",
"author": "Your Name",
"tags": ["research", "ai"]
}
FieldTypeRequiredDescription
idstringYesReverse-DNS identifier (e.g., com.warmhub.MyComponent). Ownership key.
namestringYesDisplay name, typically kebab-case.
versionstringYesSemver version string.
descriptionstringNoHuman-readable description.
authorstringNoAuthor or organization.
tagsstring[]NoDiscovery tags.

The id must match the pattern: one or more lowercase domain segments, followed by one or more PascalCase segments. Examples: com.warmhub.ResearchKnowledge, io.example.MyTool.

Every manifest needs a component object (id, name, version) plus the shapes, credentials, subscriptions, seeds, health, and teardown sections — those six may be empty arrays or objects. $schema, runtimeAccess, and cli are optional.

Earlier manifests also had an actions section. It has been removed from the manifest format: an actions key in an older manifest is ignored — install and reconcile never read it.

{
"$schema": "https://docs.warmhub.ai/schema/component-manifest.v1.json",
"component": {
"id": "com.warmhub.MyComponent",
"name": "my-component",
"version": "1.0.0"
},
"shapes": [],
"credentials": [],
"subscriptions": [],
"seeds": [],
"health": {},
"teardown": {}
}

The component section must match the corresponding fields in component.json.

Declare the WarmHub runtime scopes the component’s minted runtime token needs at execution time. This is used only for registered-component setup flows that mint tokens; local installs can still include the field for portability.

"runtimeAccess": {
"reads": ["Paper", "ComponentConfig"],
"writes": ["Consensus"]
}
FieldTypeRequiredDescription
readsstring[]YesShape names the runtime token may read.
writesstring[]YesShape names the runtime token may write.

Rules:

  • Every shape must be declared in shapes[] or be a known built-in (ComponentInstall, ComponentConfig).
  • A shape may appear in both reads and writes when the runtime needs read-before-write behavior, such as revising existing component-owned assertions.
  • Omitting runtimeAccess is equivalent to no minted runtime token.

shapes, credentials, and subscriptions support a per-resource provisioning field:

  • manifest — default. The normal manifest installer creates the resource in the target repo.
  • setup — the registered component’s setup endpoint creates the resource. When minted tokens are enabled, WarmHub includes a setup token the endpoint can use for those writes.

This allows a manifest to mix installer-created and setup-created resources in one package.

Shapes the component needs in the target repo. Created at install time if they don’t exist.

"shapes": [
{
"name": "Paper",
"fields": { "title": "string", "url": "string", "score": "number" }
}
]
FieldTypeRequiredDescription
namestringYesShape name.
fieldsobjectYesField definitions mapping names to WarmHub type descriptors.
descriptionstringNoHuman-readable description of the shape.
provisioning"manifest" | "setup"NoWhich side creates the shape. Defaults to manifest.

Field types: string, number, boolean, wref (a WarmHub reference string such as Shape/name or Shape/name@v3), arrays, nested objects. See Shapes for details.

Credential sets the component needs for external API access. With the default provisioning: "manifest", the installer creates the set and the user populates its required keys afterward. With provisioning: "setup", the registered component’s setup endpoint creates and fills the set.

"credentials": [
{
"name": "github-creds-<org-name>-<repo-name>",
"description": "GitHub API access for fetching repos",
"provisioning": "manifest",
"requiredKeys": [
{ "key": "github_token", "description": "Personal access token with repo scope" }
]
}
]
FieldTypeRequiredDescription
namestringYesCredential set name.
descriptionstringNoWhat these credentials are for.
requiredKeysarrayYesKeys that must be set.
provisioning"manifest" | "setup"NoWhich side creates the credential set. Defaults to manifest.
requiredKeys[].keystringYesKey name.
requiredKeys[].descriptionstringNoWhat the key is used for.

Credential names may include the template tokens:

  • <org-name>
  • <repo-name>

These are resolved at install/setup time. For example, veritas-webhook-<org-name>-<repo-name> becomes veritas-webhook-acme-world.

After install, populate keys with:

Terminal window
wh credential set github-creds-acme-world github_token --value ghp_... --repo acme/world

Subscriptions that trigger webhooks on write events.

"subscriptions": [
{
"name": "rk/on-paper-add",
"trigger": { "kind": "event", "shape": "Paper" },
"kind": "webhook",
"webhookUrl": "https://handler.example.com/on-paper",
"credentials": ["github-creds-<org-name>-<repo-name>"]
}
]
FieldTypeRequiredDescription
namestringYesSubscription name. Convention: <prefix>/<description>.
triggerobjectYesWhat fires the subscription.
kind"webhook"NoOptional advisory field retained for readability. The CLI derives the effective subscription kind from trigger.kind and ignores this field at install time.
webhookUrlstringYesDestination URL for deliveries.
credentialsstring[]NoCredential sets to bind. Currently limited to one.
fallbackWebhookUrlstringNoOptional fallback delivery target.
provisioning"manifest" | "setup"NoWhich side creates the subscription. Defaults to manifest.

Event trigger:

FieldTypeRequiredDescription
kind"event"Yes
shapestringYesShape to watch for changes.
filterobjectNoAdditional filter criteria.

Initial data created at install time.

"seeds": [
{
"kind": "thing",
"shape": "ComponentConfig",
"name": "my-component",
"data": { "version": "1.0.0", "enabled": true }
}
]
FieldTypeRequiredDescription
kind"thing"YesCurrently only "thing" is supported.
shapestringYesShape name. Must be declared in shapes or be a built-in (ComponentConfig).
namestringYesThing name within the shape.
dataobjectYesField values. Must conform to the shape’s field definitions.

ComponentConfig is a built-in shared shape — you can seed things into it without declaring it in shapes.

Configuration reserved for richer wh component doctor diagnostics in a future CLI version.

"health": {
"requires": {
"shapes": ["Paper", "PaperSummary"],
"things": ["ComponentConfig/my-component"],
"subscriptions": ["rk/on-paper-add"]
}
}
FieldTypeDescription
requires.shapesstring[]Reserved for future doctor checks.
requires.thingsstring[]Reserved for future doctor checks.
requires.subscriptionsstring[]Reserved for future doctor checks.

All fields are optional. The current CLI accepts this section in the manifest schema, but wh component doctor does not read health.requires.* yet. Today, doctor checks the shapes, subscriptions, credentials, and seeds declared elsewhere in the manifest.

Behavior when the component is disabled. The current CLI teardown flow reads subscriptions.onDisable; onUninstall is schema-valid but not executed yet.

"teardown": {
"subscriptions": {
"onDisable": "pause",
"onUninstall": "delete"
}
}
FieldTypeDescription
subscriptions.onDisable"pause"Action when component is disabled.
subscriptions.onUninstall"pause" | "delete"Reserved for a future uninstall flow.

Optional. Declares a CLI surface the component exposes to operators. When present, the listed methods become invokable through wh component exec <component> <method> (or the shorthand wh <component> <method>) once the component is installed. Omit the section if the component has no operator-facing commands.

"cli": {
"description": "Look up and refresh reputation scores",
"methods": [
{
"name": "reputation-get",
"description": "Fetch the current reputation for a subject",
"credentialSet": "reputation-api",
"method": "GET",
"requiresPermission": "repo:read",
"args": [
{ "name": "subject", "type": "string", "required": true, "description": "Subject id to look up" }
]
}
]
}
FieldTypeRequiredDescription
descriptionstringNoOne-line summary of the CLI surface, shown in wh --help.
methodsarrayYesThe invokable methods. May be empty.
methods[].namestringYesMethod name (lowercase kebab, unique within methods).
methods[].descriptionstringNoWhat the method does.
methods[].credentialSetstringYesName of an entry in this manifest’s credentials[] that holds the method’s auth. The referenced set must declare a supported CLI auth scheme.
methods[].argsarrayYesDeclared arguments (see below). May be empty.
methods[].method"GET" | "POST" | "PUT" | "PATCH" | "DELETE"NoDefaults to POST. Use GET for read-only lookups.
methods[].pathstringNoURL path the method routes to, decoupling the route from the method name. One or more lowercase-kebab segments joined by / (e.g. reputations/get). Defaults to the method name. Two methods may share a path only if their method (verb) differs.
methods[].requiresPermission"repo:read" | "repo:write" | "repo:configure" | "repo:admin"NoRepo scope the operator must hold on the install repo. Defaults to repo:read.
methods[].args[].namestringYesArg name (lowercase kebab, unique within the method).
methods[].args[].type"string" | "integer" | "number" | "boolean"YesArg type.
methods[].args[].requiredbooleanNoWhether the arg must be supplied.
methods[].args[].defaultstring | number | booleanNoDefault value when the arg is omitted.
methods[].args[].min / maxnumberNoNumeric bounds for integer/number args.
methods[].args[].patternstringNoRegex the value must match, for string args.
methods[].args[].descriptionstringNoWhat the arg is for.

When methods is non-empty, runtimeAccess.writes must include ComponentConfig. Without it, the component’s CLI methods won’t be callable after install.

{
"$schema": "https://docs.warmhub.ai/schema/component-manifest.v1.json",
"component": {
"id": "com.warmhub.E2eEcho",
"name": "e2e-echo",
"version": "1.0.0"
},
"shapes": [
{ "name": "EchoInput", "fields": { "message": "string", "priority": "number" } },
{ "name": "EchoOutput", "fields": { "echo": "string", "processedAt": "string" } }
],
"credentials": [
{
"name": "echo-api-creds",
"description": "API credentials for echo service",
"requiredKeys": [{ "key": "api_key", "description": "Echo API key" }]
}
],
"subscriptions": [
{
"name": "echo/process-input",
"trigger": { "kind": "event", "shape": "EchoInput" },
"kind": "webhook",
"webhookUrl": "https://echo.example.com/process",
"credentials": ["echo-api-creds"]
}
],
"seeds": [
{
"kind": "thing",
"shape": "EchoInput",
"name": "welcome",
"data": { "message": "Hello from e2e-echo component", "priority": 1 }
}
],
"health": {},
"teardown": { "subscriptions": { "onDisable": "pause" } }
}

Run offline validation before installing:

Terminal window
wh component validate ./my-component

This checks:

  • JSON syntax and required fields
  • Cross-references (subscriptions reference valid credentials, seeds reference valid shapes)
  • Duplicate names within sections
  • Subscription trigger and webhook validation
  • Component ID format (reverse-DNS)
  • Consistency between component.json and manifest.json