§3 Manifest

Normative schema for surface.json (identity, adapter, Binding, commands, triggers, protocol metadata) and the validation a runtime performs.

On this page

The manifest is surface.json at the pack root. It MUST be a JSON object.

3.1 Top-level fields#

FieldTypeReqConstraint
idstringMUSTpack_id, 1 to 128 chars, lower-case
namestringMAYDisplay name
cliBinstringSHOULDThe CLI binary the Skill teaches
kindenumSHOULDwrap | composite | openapi | sense_only. Alias adapter_kind. Default composite
planeenumMAYruntime | control. Default runtime
transportsarrayMAYSubset of cli, json_exec, mcp; at most 4 entries
bindingobjectSHOULD§3.3
wrapobjectconditionalMUST when kind is wrap
openapiobjectconditionalMUST when kind is openapi
pass_throughobjectMAY§3.5; wrap only
verbsobjectMUSTMap verb_key → command (§3.4). MAY be empty only when kind is sense_only
stimulusTriggersarrayMAY{ ref: string }[]
skill_urlstringMAYURL to a hosted copy of the Skill
harnessstringMAYInline Skill text (deprecated in favour of HARNESS.md)

Runtimes MUST ignore unknown top-level fields in surface.json for forward compatibility, and SHOULD report them.

3.2 Adapter fields#

wrap#

FieldTypeReqConstraint
binstringMUST1 to 128 chars. Relative paths (.-prefixed) resolve against the pack root
argv_templatestring[]MAY≤ 64 entries. {{verb}} and {{name}} placeholders. Default ["{{verb}}"]
agent_envobjectMAYString → string. Merged into the child environment

openapi#

FieldTypeConstraint
urlstring (URL)One of url or path MUST be present
pathstringRelative to the pack root

3.3 Binding fields#

FieldTypeConstraint
modeenumuser | mothership | local | public | mock
hubenumkeyring | local-credential | public | none
familystring1 to 128 chars
connect_provider_idstring1 to 128 chars

Unknown Binding fields MUST fail validation.

3.4 Command entry#

Each value of verbs is an object.

FieldTypeReqConstraint
descriptionstringSHOULDOne sentence
clistring[]SHOULD for wrapFirst token is the bin. Placeholders {{name}} and --flag={{name}}
argsobjectMAYJSON Schema for the command's arguments
policyenumMAYread | write. Informative hint; policy.json is authoritative

3.5 Pass-through (HCP/1.1)#

FieldTypeReq
allowedSubcommandsstring[]MUST, ≥ 1
maxArgvintegerMUST, > 0
  1. A wrap pack MUST declare either a non-empty verbs map or pass_through.
  2. A pack relying on pass_through MAY be installed as a bootstrap but is not a conforming HCP/1.1 pack until its hot path is promoted to named commands.

3.6 Protocol metadata#

A manifest MAY carry, or a runtime MUST derive, the following object. It is validated strictly: unknown fields MUST fail.

TypeScript
type HarnessPackMeta = {
  hcp: 1
  pack_id: string                         // = id
  adapter_kind: 'composite' | 'wrap' | 'openapi' | 'sense_only'
  binding?: HarnessBinding
  wrap?: HarnessWrapTarget
  openapi?: HarnessOpenApiRef
  pass_through?: HarnessPassThrough
  plane?: 'runtime' | 'control'
  transports?: ('cli' | 'json_exec' | 'mcp')[]
  skill_url?: string
}

3.7 Validation#

A runtime MUST reject the manifest when any of the following holds.

ConditionIssue
id missing or ≠ Policy surface_idinvalid_meta / missing_verb (id)
kind: wrap without wrap.binbinding: wrap adapter requires wrap.bin
kind: wrap with empty verbs and no pass_throughwrap: wrap requires named commands or pass_through
plane: control with binding.mode ≠ mothershipbinding: control plane packs default Binding mothership
kind: openapi without openapiinvalid_meta: openapi adapter requires openapi ref
kind: sense_only with no stimulusTriggersinvalid_meta: sense_only adapter requires at least one stimulus trigger_ref
Metadata schema violationinvalid_meta

3.8 Example (informative)#

JSON
{
  "id": "ledger",
  "name": "Ledger",
  "kind": "wrap",
  "cliBin": "ledger",
  "plane": "runtime",
  "transports": ["cli", "json_exec"],
  "binding": { "mode": "local", "hub": "local-credential", "family": "ledger" },
  "wrap": { "bin": "../../bins/ledger.mjs", "argv_template": ["{{verb}}"] },
  "verbs": {
    "setup.status": { "description": "Idempotent installer status.", "cli": ["ledger", "setup", "status"] },
    "setup.apply":  { "description": "Apply installer.", "cli": ["ledger", "setup", "all", "-y"], "policy": "write" },
    "connect":      { "description": "Connect Binding.", "cli": ["ledger", "connect", "{{provider}}"], "policy": "write" },
    "status":       { "description": "Connect health.", "cli": ["ledger", "status"] },
    "list":         { "description": "Domain read.", "cli": ["ledger", "list"] },
    "transfer":     { "description": "Gated write.", "cli": ["ledger", "transfer", "{{amount}}", "--to", "{{payee}}", "--confirm"], "policy": "write" }
  }
}