Skip to content

Plugins

Source: docs/plugins/README.md · Status: current.

How to ship packs for the Inhuman harness — surfaces, install, commands, and reference sketches.

Target design: plugins/hooks-notify-vs-transform-2026-09-20.md, revised 2026-09-22, is authoritative for the proposed API. Interception comes in two kinds: guards stand on the critical path, see raw values, may narrow or replace, fail closed, and are content-addressed and bound to a host-owned consent store — so a change to a guard is reviewed at install or update; hooks declare :pre / :post / :post-fail, run in parallel, receive filtered values only, fail open, and never block. It uses guard/turn and guard/round for chain position at lifecycle boundaries with self/notify contributed by parallel hook/turn / hook/round, single-use invoke, and per-lineage re-entrancy limits. Tool-argument schema repair and read caching are host machinery, not plugin surfaces. There is no react or producer registration. Behavior is selected per bot: a definition chooses plugin.scm, optional environment, configuration, and receiver bindings; each running agent pins the revision and owns its registrations, private state, and notifications. plugin.json additionally declares session/project/global Scheme state modules with define/method APIs. Bots use call/method or injected callables without needing a target bot or exposing model tools. State scope owns the log and rollback semantics; packages supply trusted code and optional shared resources. Follow the plugins/plugin-surface-implementation-2026-09-21.md for migration and acceptance scenarios.

polish.md, lifecycle.md, and plugins/reference/ describe the behavior capability in packages/harness-server/src/plugin-surface. It is an Arrival EnvCapability: author-facing forms are symbol.macro, and handler lambdas cross with toJS. A callback passed into one of those lambdas is reverse Rosetta. The session loop stores the pin and joins behavior notes with loopEnd. It does not call loadProgram or dispatchBoundary. plugins/tldr.md documents InhumanPlugin. Host builtins (shell, toolkit, scheme-repl, and the JS tasks projection) still construct that class and compile it with applyPackPlugins. The pack loader does not import plugins[]. loopEnd still joins until a later removal. The plugins/plugin-shape-2026-09-20.md and plugins/hooks-design-review-2026-09-20.md are historical context.

Author guides:

  1. polish.md — behavior selection, guards, hooks, state methods, consent
  2. lifecycle.md — register vs callback, turn/round, tool chain, replay
  3. plugins/reference/ — plugin.json and hooks.scm. Shipped slash-commands stay in packages/harness-server/src/defaults/commands/
  4. plugins/tldr.md — module bag the host builtins still load
  5. install.md — npm into the kernel folder + config.json
  6. commands.md — Client Scheme sandbox vs JSON-RPC commit

Extension plugins are not driver providers. Drivers are not the behavior surface. drivers[] is still parsed and projected onto DriverSpec. That merge is unsupported; no exemplar pack declares a driver. A driver provider is a runtime package registered by product composition — not a pack loaded through plugin manifests or the plugin loader. Exterior for a behavior pack is connections on existing drivers (/connect, MCP servers), pack tools, and commands. Internal doc: ../runtime/drivers.md.

Product nouns (locked — link, do not re-host):

Noun home Path
Grain / regions / catalog ../canon/grain.md
Proposals ../canon/proposals.md
Permission / LICENSE WHEN ../runtime/approval.md
Always-on FS toolkit ../canon/standard-toolkit.md

Not this tree: operator day-to-day → ../client/operate.md.
Exemplar packs: ../plugins/.
Tool constructor: ../packages/harness-plugin-sdk/README.md.