Skip to main content
A Harnest Extension participates in three lifecycle layers: The extension manifest must project lifecycle files through contributes.lifecycle and declare every Harnest capability those files use. Path declaration makes content visible to the compiler; capabilities authorize what that content may do. Neither grants access to undeclared runtime internals. Storage authorities start first. Harnest then calls Extension.start() in dependency order, followed by contributed @lifecycle.resource factories. Shutdown closes extension resources before calling Extension.stop() in reverse dependency order, then closes storage. ExtensionStartContext therefore exposes only already-live named custom storage and declared continuations, not arbitrary lifecycle resources or invocation credentials.

Declare and implement a hook

Application-owned and extension-owned lifecycle files form one globally validated lifecycle. Lower order values run first. Extension dependency order and source location break ties. Duplicate singleton authorities or named resources fail compilation rather than shadowing one another.

Choose a declared capability

Declare only the rows the extension actually uses. Advanced mode still composes Harnest-owned boundaries, but it cannot intercept an opaque native path that bypasses Harnest.

Audit committed mutations

Wrap committed user- or agent-triggered writes with extension_mutation(...). It emits correlated, payload-free OTEL audit events without recording arguments, credentials, or results:
extensions/warehouse/extension.py
For external work that must survive a replica stopping, declare context.continuations and follow Durable execution. The extension persists bounded continuation metadata; it does not resume a suspended Python process.

Use the extension

Call the bounded public API from an Agent Tool or other trusted invocation code.