pleach
Plugins

Contribution namespaces

The nine namespaces that organize every HarnessPlugin contribution hook — the canonical, audit-gated map of where a plugin plugs into the runtime.

A HarnessPlugin plugs into the runtime by filling named slots. There are a lot of slots — prompt contributors, stream observers, tool definitions, safety policies, retry strategies, lifecycle callbacks. This page is the map: every contribution hook belongs to exactly one of nine namespaces, grouped by when and against what it runs.

The grouping isn't cosmetic. It's the contract layout an audit:plugin-hook-category-assigned gate enforces — every hook on the HarnessPlugin interface must resolve to exactly one namespace, and a new hook with no namespace fails the build. So the nine namespaces stay an exhaustive, drift-free partition of the contribution surface.

This is the orthogonal view to Authoring a HarnessPlugin. The authoring page groups hooks informally so you can scan for the one you need; this page is the canonical, audit-gated layout the substrate organizes them by. Same hooks, one map.

The nine namespaces

NamespaceWhen it runsWhat lives here
promptsPrompt-construction timeSystem-prompt assembly, context bridges, section generators
streamAgainst the live token streamPer-chunk observers/filters/handlers, end-of-turn analyzers, finalization passes
safetyBefore something is allowed to firePolicy gating, PII redaction, approval flows
auditWhen recording an eventEvent-log emitters, event-type registries, domain projection
intentAt dispatch-classification timeIntent detection, classifiers, parameter resolvers, keyword/synonym registries
toolsAround tool dispatchThe tool catalog, tool-loop strategy, post-tool enrichment
middlewareWrapping a lifecycle boundaryModel-call, tool-call, and sandbox interception bundles
policyWhen the runtime reads a decisionRetry, continuation, family-pivot, citation rules — data the runtime consults
lifecycleAt a discrete lifecycle eventChat start, job dispatch/complete, sandbox readiness, interrupts

The line between two adjacent namespaces is what the hook does, not what it's about. middleware intercepts (wraps a boundary with before/after); policy is data the runtime reads. safety prevents (gates before execution); audit records (after the fact). intent classifies which tool to consider; tools is the catalog itself.

prompts

Everything that feeds the system-prompt builder or runs at prompt-construction time. Static blocks, per-turn runtime-aware sections, synthesis-time directive blocks, and the host-config → agnostic-context bridges that make a runtime-aware prompt authorable.

Representative hooks: contributePrompts, contributeRuntimeAwarePrompts, contributePromptHints, contributePromptSections, contributePromptContextBridge, contributeSynthesisDirectiveBlocks, prePlanPrimer.

See Prompts and Prompt builder.

stream

Everything that runs against the live stream — inside the chunk loop (the synchronous onChunk contract), at end-of-turn aggregation, or at the post-stream sanitizer pass. Observers, filters, chunk handlers, hallucination and fabrication detectors, garble recorders, finalization passes.

Representative hooks: contributeStreamObservers, contributeStreamChunkHandlers, contributeFinalizationPasses, contributeHallucinatedToolDetectors, contributeFabricationDetectors, contributeFabricationGuard.

Stream hooks are deliberately co-located despite distinct contract shapes (read-only observe vs 1:1 amend vs verdict) because they share the lifecycle. See Stream observers and Fabrication detection.

safety

Hooks that gate whether something is allowed to fire, or shape what gets recorded for redaction and compliance — preventative, as distinct from stream (post-emit shaping) and audit (recording).

Representative hooks: contributeSafetyPolicies, contributeScrubbers, contributeApprovalFlow, contributeFabricationDetectorRules.

The split inside the fabrication family is by execution, not topic: the detectors and guard that fire against stream content live in stream; the pure rule-data slot (contributeFabricationDetectorRules) lives in safety. See Scrubbers and Safety.

audit

Hooks that bind an event-log emitter, register the event types the emitter accepts without warning, or contribute domain-specific event projection. Distinct from safetysafety is preventative, audit is recording.

Representative hooks: contributeAuditEmitter, contributeEventTypes, eventResolver, contributeRefClassValidators.

What a plugin contributes here is exactly what the config manifest's plugin_manifest snapshot records — so the namespace a hook lives in is also the lens you audit it through. See Event log and Audit ledger.

intent

The dispatch-classification layer — hooks that feed the intent-detection stage or the tools that consult an intent label. Distinct from tools (the catalog); intent decides which tool to consider.

Representative hooks: contributeDetectionRules, contributeIntentClassifiers, contributeIntentToolMap, contributeIntentParameterResolvers, contributeIntentKeywordClasses, contributeDomainClassifierPatterns.

See Routing decisions.

tools

The widest namespace, because tool dispatch is the runtime's primary substrate. Hooks here contribute to the tool registry, the plan-to-tool ordering, per-tool execution strategy, or post-tool result enrichment.

Representative hooks: contributeTools, contributeToolCouplingHints, contributePostToolTier, contributeEntityExtractors, contributeGuestDeniedTools, extraGraphNodes, registerAsyncExecutors.

See Tools and Post-tool tier.

middleware

Hooks that return an object whose methods wrap a lifecycle boundary — model calls, tool calls, sandbox completion, sandbox init. Distinct from policy: middleware intercepts behavior, policy is data the runtime reads.

Representative hooks: contributeMiddleware, contributeRuntimeAwareMiddleware, contributeSandboxBridge, contributeSandboxInitialization.

policy

Hooks that return a value or strategy the runtime reads — a retry policy, a continuation decision, a family-pivot ladder, a citation rule set, a chat-manifest provider. Distinct from middleware (which wraps) and intent (which classifies).

Representative hooks: contributeRetryPolicy, contributeContinuationPolicy, contributeFamilyPivot, contributeCitationRuleSet, contributeChatManifestProvider.

See Family lock for the pivot ladder.

lifecycle

Hooks that fire at a discrete lifecycle event — chat start, job dispatch, job complete, sandbox readiness, data-channel refetch, interrupt — rather than per-token, per-chunk, or per-tool.

Representative hooks: onJobDispatch, onJobComplete, postSynthesisGuard, contributeSandboxAvailabilityEvaluator, contributeGetDataHandlerFactory, contributeInterruptUIHandlers.

See Interrupts and Async tasks.

The typed namespaced form

additive · rolling out

Today every hook is a flat field on HarnessPlugin (contributeStreamObservers, contributeTools, …), and that flat form stays valid. The nine namespaces are landing additively as a typed accessor form so a plugin author gets nine-bucket autocomplete instead of paging the full interface:

// Both forms compile clean during the overlap window.
definePleachPlugin({
  contributeStreamObservers: () => [/* ... */],          // flat (today)
});

definePleachPlugin({
  stream: { contributeStreamObservers: () => [/* ... */] }, // namespaced (rolling out)
});

Additive, with a deprecation runway

The namespaced form lands alongside the flat form, not instead of it. During the overlap window the collector reads the namespace bucket first and falls back to the flat field, so a hook is reachable from either path and existing plugins keep loading unchanged. The flat form gets a deprecation warning, then retires, over a multi-minor cadence — the same path contributeTools already took to replace the bare tools field.

Where to go next

On this page