Scrydon
Authoring: Org KB

Promoting Content

Promote workspace content into a governed organization knowledgebase domain — via the platform broker client, the finalize-learnings condense, or the manual Workspace-Admin button.

Content reaches an organization knowledgebase domain through the platform broker — a single client surface (@scrydon/better-auth-orgkb plugin) that all apps use instead of hand-rolling api-ontology clients. There are two finalize paths and one user-initiated path.

The broker client — two tiers

The broker exposes two tiers. Choose the right one based on whether there is a user session in scope.

Session tier — user-initiated reads and actions

Use getClientWithAuth({ headers }) for any action taken by a user: browsing promoted rows, submitting a manual promotion, reviewing a pending request, managing markings.

import { getClientWithAuth } from "@scrydon/multi-tenancy/auth/client";

// In a server function or route handler that holds the user's request headers.
const client = getClientWithAuth({ headers });

// List promoted rows from a governed domain.
const { data } = await client.orgKb.partitionRows({
  organizationId,
  partitionSlug: "learnings",
});

// Review a pending promotion request.
await client.orgKb.reviewPromotion({
  organizationId,
  promotionRequestId,
  decision: "approve",
  reason: "Verified — correct insight, no PII.",
});

Available session-tier methods: listPartitions, listPartitionObjectTypes, resolvePromotionTarget, listPromotions, reviewPromotion, cancelPromotion, promote, partitionRows, query, rowHistory, revokeRow, listMarkings, createMarking, deleteDomain, exportAuditBundle, resolveTable.

Do NOT use getAdminClient() for user-facing reads. The admin client is M2M — it carries no user session and api-ontology will 401 when it tries to enforce per-user governed reads (markings, clearance, roles). Always forward the user's session via getClientWithAuth({ headers }).

M2M admin tier — system operations

Use getAdminClient().orgKb.admin.* for system-initiated operations: the learnings condense, enqueuing mutations from a background job, or any operation where there is no user session in scope.

import { getAdminClient } from "@scrydon/multi-tenancy/auth/client";

// Trigger the learnings condense. Pass all pages of the linked workspace KB.
const { data, error } = await getAdminClient().orgKb.admin.promoteLearnings({
  organizationId,         // Always server-derived — never from the client.
  workspaceId,
  workspaceEnvironmentId,
  knowledgeBaseId,
  partitionSlug,          // e.g. "learnings"
  objectTypeSlug,         // e.g. "ProjectLearning"
  pages,                  // { pageId, title, path, body }[]
});
if (error) throw new Error(error.message ?? `promoteLearnings failed (${error.status})`);

Available admin-tier methods: promoteLearnings, enqueueMutation.

Finalize path A — approval action with promoteToOrgKb

Declare the finalize trigger in the process flow manifest. Add promoteToOrgKb: true to an approval action's metadata:

import { defineAction } from "@scrydon/sdk-authoring/process-flows";

defineAction({
  name: "Sign off on project review",
  actionType: "approval",
  isRequired: true,
  metadata: {
    persona: "knowledge-lead",
    promoteToOrgKb: true,   // Triggers learnings condense on approval completion.
  },
})

When the stage containing this task completes (the approval is granted), the platform automatically:

  1. Gathers all pages of the workspace KB linked to this process instance.
  2. DLP-scans the page corpus.
  3. Runs one LLM pass over the whole KB to extract a discrete, deduplicated set of typed learning records shaped to the target object type's property schema.
  4. DLP-scans the produced learnings.
  5. Enqueues each learning via getAdminClient().orgKb.admin.enqueueMutation(...).

The approval IS the human verification gate — no separate promote action is needed.

promoteToOrgKb is valid only on actionType: "approval" actions. Setting it on other action types has no effect.

Finalize path B — Workspace-Admin manual button

A Promote learnings button appears in the workspace KB header for users with the Workspace Admin role. Clicking it triggers the same condense as path A.

This path is useful for iterative promotion during active work — before a process formally finalizes, or for standalone workspace KBs not linked to a process flow.

The route is gated to Workspace Admins only. Non-admins do not see the button, and the underlying route returns 403 for non-admins regardless.

How the condense works

Both paths ultimately call getAdminClient().orgKb.admin.promoteLearnings(...). The platform broker:

  1. DLP-scans the page corpus (before the LLM sees it).
  2. Calls resolvePromotionTarget to fetch the target object type's property schema from api-ontology.
  3. Runs one LLM pass over the whole KB corpus (via getPlatformCapabilityRuntime().completeLlm), producing a content-determined set of discrete learning records — merge duplicates, one record per durable insight, no fixed count.
  4. DLP-scans the produced learnings.
  5. Enqueues each learning via getAdminClient().orgKb.admin.enqueueMutation(...) → api-ontology org_kb_mutation_queue → existing consumer → promotion_request → Review → materializer.

Fail-safe: if the LLM is not configured or its output cannot be parsed, zero learnings are enqueued. Un-extracted content is never written into a typed domain.

Row identity and idempotency

Each learning has a stable row identity:

rowId = "kblearning:" + sha256(canonicalTitle + "|" + objectTypeSlug)

where canonicalTitle = title.toLowerCase().trim().replace(/\s+/g, " ").

Re-finalizing the same workspace KB updates learnings whose content changed, adds new learnings, and no-ops learnings whose content is identical. You will not accumulate duplicate Review items across repeated finalizations.

Each learning automatically carries a references field:

references: Array<{ pageId: string; title: string; path: string }>

References list the workspace KB pages that the learning was derived from. They are assembled by promoteLearnings before the LLM pass — not guessed by the model. partitionRows and query return references alongside the other properties of every promoted row.

references is a reserved system column on every org-KB domain table. Pack authors do not need to declare it; the provisioner creates it on every domain table automatically.

Remove a domain

An organization admin can remove a domain from Settings → Organization → Knowledgebase → Domains: open the domain's menu and choose Remove domain…. This permanently deletes the domain — its content, its managed table in storage, and its signed promotion/revocation audit trail. Because the action is irreversible, the confirm button stays disabled until you type the domain's slug.

This cannot be undone. The domain's own content and lineage are gone. The removal is recorded in the organization audit log, but the individual promotion records are deleted. Export an audit bundle first if you need to retain the record.

Domains provisioned by a pack will be re-created if the pack is re-synced or upgraded. To remove a pack-provisioned domain for good, uninstall the pack as well. Only organization admins can remove a domain.

On this page

On this page