Skip to main content
A Harnest Extension participates in three lifecycle layers: The extension manifest must declare every Harnest capability its lifecycle files contribute. Declaration makes ownership inspectable; it does not grant 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.