Contribution kind: search-type. Ingestion: biome-host parser (SearchTypeParser).

A result-type is the (objectKind, docType) facet a biome makes searchable. It is declarative and boot-time. Document INSTANCES are a separate, runtime, event-fed path — contributing a result-type does not index anything by itself; it teaches the platform how to render, deep-link, and authorize hits of that facet.

Contributing render hints is what makes a new biome fully renderable in search without anyone adding a per-kind branch to the frontend.

manifest

FieldTypeRequiredNotes
objectKindenumnoone of: biome, app, app-client, audience-policy, external-subject, delegated-session, agent, skill, tool, model, model-resolution-rule, workflow, workflow-run, gate-action, connector, connector-binding, mount-source, artifact-type, artifact, output-route, resource, knowledge-space, knowledge-page, chart-runtime, presentation-runtime, widget-kind, capability, execution-environment, capability-grant, approval-rule, memory, memory-relation, session, event-stream, event-subscription, contribution-entry, concept
docTypestringnomax 200 chars
renderHintsobject — see renderHintsyes—
searchableFieldsstring[]yesmax 100 entries; entries: max 200 chars
embeddingEligibleDefaultbooleanyes—
authzobject — see authzyes—
searchReplayCapabilityRefstringnopattern /^[a-z][a-z0-9-]*:[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*@\d+$/

renderHints

FieldTypeRequiredNotes
labelstringyesmax 200 chars
iconstringnomax 200 chars
routeTemplatestringnomax 500 chars
routeParamsenum[]nomax 2 entries; entries one of: orgId, projectId, docType, objectKind, sourceId, slug, title, containerSlug

authz

FieldTypeRequiredNotes
resourceTypestringyesmax 200 chars
defaultVisibilityenumyesone of: owner-only, org-shared, explicit-share

The routeTemplate grammar

A routeTemplate is a site-relative path with {placeholder} segments. The placeholder vocabulary is CLOSED, and both the syntax and the SATISFIABILITY are validated at contribution-parse time — a broken deep link is rejected at boot, never discovered in production.

Placeholder syntax: \{([A-Za-z0-9_]+)\}.

Variables

Each variable has exactly one supply route. scope and identity variables are derived by the platform from the hit or object ref and are never declared. projected variables can only come from the owning source, so a template that references one MUST declare it in renderHints.routeParams — and the producer must stamp it on the indexed document.

VariableSourceMust be declared in routeParams
{orgId}scope (SearchRouteVariableSource.Scope)no
{projectId}scope (SearchRouteVariableSource.Scope)no
{docType}identity (SearchRouteVariableSource.Identity)no
{objectKind}identity (SearchRouteVariableSource.Identity)no
{sourceId}identity (SearchRouteVariableSource.Identity)no
{slug}projected (SearchRouteVariableSource.Projected)yes
{title}identity (SearchRouteVariableSource.Identity)no
{containerSlug}projected (SearchRouteVariableSource.Projected)yes

Rejected at parse time — syntax

TemplateRejected because
(empty)must be non-empty
relative/pathmust be a site-relative path starting with "/"
/a bmust not contain whitespace
/a//bmust not contain an empty path segment ("//")
/{oopscontains a malformed placeholder — every placeholder must be "{name}" with name matching [A-Za-z0-9_]+
/{notAVariable}unknown placeholder "{notAVariable}" — allowed placeholders are: containerSlug, docType, objectKind, orgId, projectId, slug, sourceId, title

Rejected at parse time — supply contract

Enforced in both directions: a template may not reference a projected variable the result-type does not declare, and a declared variable the template never references is a dead declaration.

DeclarationRejected because
/x/{slug} with routeParams: []placeholder "{slug}" is projected by the owning source, but this result-type does not declare it in renderHints.routeParams — the template could never expand. Either declare it (and stamp it on IndexableDocument.routeParams) or drop it from the template.
/x/{orgId} with routeParams: ["orgId"]route param "orgId" must not be declared — it is supplied by the platform (source "scope"), not by the producer. Only containerSlug, slug may be declared.
/x/{slug} with routeParams: ["slug", "slug"]route param "slug" is declared more than once
/x/{slug} with routeParams: ["slug", "containerSlug"]route param "containerSlug" is declared but never referenced by the template — remove the dead declaration

Worked example

json
1{
2  "renderHints": {
3    "label": "Runbook",
4    "routeTemplate": "/projects/{projectId}/documents/{containerSlug}/{slug}",
5    "routeParams": ["containerSlug","slug"]
6  }
7}

Expanding it for a hit in project proj_42, container runbooks, slug incident response yields:

/projects/proj_42/documents/runbooks/incident%20response

Every substituted value occupies a single path segment and is URL-encoded, so a value containing /, ?, #, or a space can never change the shape of the path. Expansion is all-or-nothing: a missing value throws rather than emitting a half-substituted URL.