Branding
White-label primitives — override the brand string, log prefixes, and error-message text the runtime emits so output reads as your product, not as Pleach. configureBranding / getBrandingConfig / resolveLogPrefix / resolveErrorMessage.
White-label primitives let a host override the brand string, log prefixes, and error-message text the runtime emits. Output reads as the host's product instead of as Pleach. The surface is opt-in; with nothing configured, the runtime's output is byte-identical to running without branding.
Two consumer types reach for this earliest. Consultancies ship the
same runtime to N tenants under N brands — agency-style hosts that
need each deployment to wear a different name. ISVs embed
@pleach/core inside a product where exposing the underlying runtime
would dilute their own brand. End-user-facing SaaS rarely needs it;
if your users never see a log line or an error string, there is
nothing to rename.
The contract
Four functions, all from the top-level @pleach/core export.
| Function | Role |
|---|---|
configureBranding(config) | Installs an override. Every field is optional and defaults to identity. |
getBrandingConfig() | Returns the active configuration with defaults filled in. |
resolveLogPrefix(defaultPrefix) | The call-site hook log emitters route through. |
resolveErrorMessage(defaultMessage) | The call-site hook throw new Error(...) sites route through. |
configureBranding({ brandName, logPrefix, errorMessage }) is the
whole installation surface. logPrefix and errorMessage are
transform functions — each receives the default and returns the
branded form, so you rename rather than hard-code.
import { configureBranding } from "@pleach/core"
configureBranding({
brandName: "Acme",
logPrefix: (defaultPrefix) => defaultPrefix.replace("Pleach", "Acme"),
errorMessage: (defaultMessage) => `[Acme] ${defaultMessage}`,
})Adoption is incremental
v0.x ships the contract. You can call configureBranding today and
the resolvers honor it. What's still landing is the substrate
retrofit — replacing every hard-coded [ToolNode] / [SessionRuntime]
literal with a call through resolveLogPrefix — which arrives as part
of the broader logging-refactor track. The override surface widens
transparently as call sites adopt the resolvers; nothing you write
against the contract breaks when they do.
Why it's multi-call, unlike @pleach/observe.init
@pleach/observe.init is single-init: it owns infrastructure state —
destinations, sampling decisions, async-local-storage scope — that
would race or leak across reconfigurations. Branding owns none of
that. It's a UX preference, so the constraint is looser.
configureBranding MAY be called multiple times. The last call wins,
and partial overrides do not merge with the prior config — each
call replaces the whole branding state. A multi-tenant process can
adjust branding at the boundary of a request handler without a process
teardown.
The @pleach/core/branding subpath
The same four functions are available at the @pleach/core/branding
subpath when you only want this slice in your bundle.
import { configureBranding } from "@pleach/core/branding"Where to go next
Runtime strategies
Typed strategy slots on SessionRuntimeConfig — single-shape, single-consumer fields the host fills with domain code. The companion surface to the plugin contract.
Typed auditable-call records
Five audit-ledger records promoted from untyped JSON to typed, stage-correlated slots — Interrupt, TokenCost, ToolSelection, PlanGeneration, SynthesisQuality.