# Contribution namespaces (/docs/plugins/namespaces)



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.

<SourceMeta source="{ label: &#x22;src/plugins/&#x22;, href: &#x22;https://github.com/pleachhq/core/tree/main/src/plugins&#x22; }" />

This is the orthogonal view to [Authoring a HarnessPlugin](/docs/plugins/authoring).
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 [#the-nine-namespaces]

| Namespace    | When it runs                        | What lives here                                                                  |
| ------------ | ----------------------------------- | -------------------------------------------------------------------------------- |
| `prompts`    | Prompt-construction time            | System-prompt assembly, context bridges, section generators                      |
| `stream`     | Against the live token stream       | Per-chunk observers/filters/handlers, end-of-turn analyzers, finalization passes |
| `safety`     | Before something is allowed to fire | Policy gating, PII redaction, approval flows                                     |
| `audit`      | When recording an event             | Event-log emitters, event-type registries, domain projection                     |
| `intent`     | At dispatch-classification time     | Intent detection, classifiers, parameter resolvers, keyword/synonym registries   |
| `tools`      | Around tool dispatch                | The tool catalog, tool-loop strategy, post-tool enrichment                       |
| `middleware` | Wrapping a lifecycle boundary       | Model-call, tool-call, and sandbox interception bundles                          |
| `policy`     | When the runtime reads a decision   | Retry, continuation, family-pivot, citation rules — data the runtime consults    |
| `lifecycle`  | At a discrete lifecycle event       | Chat 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` [#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](/docs/prompts) and [Prompt builder](/docs/prompt-builder).

## `stream` [#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](/docs/plugins/stream-observers)
and [Fabrication detection](/docs/fabrication-detection).

## `safety` [#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](/docs/scrubbers) and [Safety](/docs/safety).

## `audit` [#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 `safety` — `safety` is
preventative, `audit` is recording.

Representative hooks: `contributeAuditEmitter`,
`contributeEventTypes`, `eventResolver`,
`contributeRefClassValidators`.

What a plugin contributes here is exactly what the
[config manifest](/docs/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](/docs/event-log) and
[Audit ledger](/docs/audit-ledger).

## `intent` [#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](/docs/plugins/routing-decisions).

## `tools` [#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](/docs/tools) and [Post-tool tier](/docs/plugins/post-tool-tier).

## `middleware` [#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` [#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](/docs/family-lock) for the pivot ladder.

## `lifecycle` [#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](/docs/interrupts) and [Async tasks](/docs/async-tasks).

## The typed namespaced form [#the-typed-namespaced-form]

<StatusBadge status="in-flight">
  additive · rolling out
</StatusBadge>

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:

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

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

<Callout title="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.
</Callout>

## Where to go next [#where-to-go-next]

<Cards>
  <Card title="Authoring a HarnessPlugin" href="/docs/plugins/authoring" description="The practical authoring story — the canonical no-op for each hook shape and the empty-plugin scaffold." />

  <Card title="Plugin contract" href="/docs/plugin-contract" description="The structural-invariant view — what plugins can and can't do." />

  <Card title="Config manifest" href="/docs/config-manifest" description="The snapshot that records which plugins contributed which hooks." />

  <Card title="Plugin bundles" href="/docs/plugin-bundles" description="composePlugin() and the thematic facet sub-paths for larger plugins." />
</Cards>
