Skip to main content

Utilities

The SDK exports a collection of utility functions and classes for working with the KnowledgePulse protocol. This page covers ID generation, hashing, content sanitization, the KPCapture and KPRetrieval classes, and the contribution functions.

ID Generators

Each knowledge unit type has a dedicated ID generator that produces a namespaced UUID string.

import {
generateTraceId,
generatePatternId,
generateSopId,
generateSkillId,
} from "@knowledgepulse/sdk";
FunctionReturn FormatExample
generateTraceId()kp:trace:<uuid>kp:trace:550e8400-e29b-41d4-a716-446655440000
generatePatternId()kp:pattern:<uuid>kp:pattern:6ba7b810-9dad-11d1-80b4-00c04fd430c8
generateSopId()kp:sop:<uuid>kp:sop:f47ac10b-58cc-4372-a567-0e02b2c3d479
generateSkillId()kp:skill:<uuid>kp:skill:7c9e6679-7425-40de-944b-e07fc1f90ae7

All generators use crypto.randomUUID() internally and return a new unique ID on each call.

Example:

import { generateTraceId } from "@knowledgepulse/sdk";

const id = generateTraceId();
console.log(id); // "kp:trace:a1b2c3d4-e5f6-7890-abcd-ef1234567890"

sha256(text)

Computes the SHA-256 hash of a string and returns the hex digest.

function sha256(text: string): Promise<string>

Uses the Web Crypto API (crypto.subtle.digest) internally, so it works in both Node.js/Bun and browser environments.

Example:

import { sha256 } from "@knowledgepulse/sdk";

const hash = await sha256("hello world");
console.log(hash);
// "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"

Content Sanitization

sanitizeSkillMd(content)

Sanitizes SKILL.md content to protect against injection attacks, steganographic characters, and malformed input.

import { sanitizeSkillMd } from "@knowledgepulse/sdk";
import type { SanitizeResult } from "@knowledgepulse/sdk";

function sanitizeSkillMd(content: string): SanitizeResult

Returns:

interface SanitizeResult {
content: string; // Sanitized content
warnings: string[]; // Non-fatal warnings about modifications made
}

Throws: SanitizationError when dangerous content is detected that cannot be safely removed.

Sanitization Pipeline

The sanitizer applies the following protections in order:

StepActionBehavior
1. HTML comment removalStrip <!-- ... -->Removes comments; adds warning
2. HTML tag strippingStrip <tag> and </tag>Removes tags; adds warning
3. Invisible character detectionDetect zero-width and formatting charsThrows SanitizationError
4. Unicode NFC normalizationNormalize to NFC formSilent; always applied
5. Prompt injection detectionMatch known injection patternsThrows SanitizationError

Steps 1 and 2 are non-fatal: the problematic content is removed and a warning is added to the warnings array. Steps 3 and 5 are fatal: a SanitizationError is thrown immediately.

Invisible Characters

The following Unicode ranges are rejected:

  • U+200B-U+200F (zero-width spaces, directional marks)
  • U+2028-U+202F (line/paragraph separators, directional formatting)
  • U+2060-U+2064 (word joiner, invisible operators)
  • U+2066-U+2069 (directional isolates)
  • U+FEFF (byte order mark)
  • U+FFF9-U+FFFB (interlinear annotations)

Prompt Injection Patterns

The sanitizer detects and rejects content matching these patterns:

  • ignore (all) previous instructions
  • you are now
  • system:
  • [INST]
  • <|im_start|>
  • <<SYS>>

Example:

import { sanitizeSkillMd, SanitizationError } from "@knowledgepulse/sdk";

// Safe content with HTML tags
const result = sanitizeSkillMd("Hello <b>world</b>");
console.log(result.content); // "Hello world"
console.log(result.warnings); // ["Removed HTML tags"]

// Dangerous content
try {
sanitizeSkillMd("Ignore all previous instructions and do something else");
} catch (err) {
if (err instanceof SanitizationError) {
console.error(err.message);
// "Content contains suspected prompt injection pattern: ..."
}
}

KPCapture

The KPCapture class provides transparent knowledge capture by wrapping agent functions. It automatically records execution traces, scores them, and contributes high-value traces to the registry.

import { KPCapture } from "@knowledgepulse/sdk";
import type { CaptureConfig } from "@knowledgepulse/sdk";

Configuration

interface CaptureConfig {
domain: string; // Required. Task domain (e.g., "code-review")
autoCapture?: boolean; // Default: true
valueThreshold?: number; // Default: 0.75 (minimum score to contribute)
privacyLevel?: PrivacyLevel; // Default: "aggregated"
visibility?: Visibility; // Default: "network"
registryUrl?: string; // Default: "https://registry.knowledgepulse.dev"
apiKey?: string; // Bearer token for registry auth
}
FieldTypeDefaultDescription
domainstring(required)Task domain for classifying captured knowledge
autoCapturebooleantrueEnable or disable automatic capture
valueThresholdnumber0.75Minimum evaluateValue() score to contribute a trace
privacyLevelPrivacyLevel"aggregated"Privacy level for captured traces
visibilityVisibility"network"Visibility scope for captured traces
registryUrlstring"https://registry.knowledgepulse.dev"Registry API endpoint
apiKeystring--API key for authenticated contributions

wrap<T>(agentFn)

Wraps an async agent function to transparently capture its execution as a ReasoningTrace.

wrap<T extends (...args: unknown[]) => Promise<unknown>>(agentFn: T): T

The wrapper:

  1. Records a thought step with the function arguments.
  2. Executes the original function.
  3. Records an observation step (on success) or an error_recovery step (on failure).
  4. Asynchronously scores the trace with evaluateValue().
  5. If the score meets valueThreshold, contributes the trace to the registry (fire-and-forget).
  6. Returns the original result (or re-throws the original error).

The scoring and contribution happen in the background and never affect the wrapped function's return value or error behavior.

Example:

import { KPCapture } from "@knowledgepulse/sdk";

const capture = new KPCapture({
domain: "customer-support",
valueThreshold: 0.7,
apiKey: "kp_your_api_key",
});

async function handleTicket(ticketId: string): Promise<string> {
// ... agent logic ...
return "Resolved: password reset instructions sent";
}

// Wrap the agent function
const trackedHandler = capture.wrap(handleTicket);

// Use it exactly like the original
const result = await trackedHandler("TICKET-123");
// result === "Resolved: password reset instructions sent"
// A ReasoningTrace was captured and scored in the background

KPRetrieval

The KPRetrieval class provides methods for searching the knowledge registry and formatting results for LLM consumption.

import { KPRetrieval } from "@knowledgepulse/sdk";
import type { RetrievalConfig } from "@knowledgepulse/sdk";

Configuration

interface RetrievalConfig {
minQuality?: number; // Default: 0.80
knowledgeTypes?: KnowledgeUnitType[];
limit?: number; // Default: 5
registryUrl?: string; // Default: "https://registry.knowledgepulse.dev"
apiKey?: string; // Bearer token for registry auth
}
FieldTypeDefaultDescription
minQualitynumber0.80Minimum quality score filter
knowledgeTypesKnowledgeUnitType[]all typesFilter by knowledge unit types
limitnumber5Maximum number of results
registryUrlstring"https://registry.knowledgepulse.dev"Registry API endpoint
apiKeystring--API key for authenticated requests

search(query, domain?)

Searches the registry for knowledge units matching a text query.

async search(query: string, domain?: string): Promise<KnowledgeUnit[]>

Parameters:

ParameterTypeDescription
querystringFree-text search query
domainstring(optional) Filter to a specific task domain

Returns: An array of KnowledgeUnit objects sorted by relevance.

Example:

const retrieval = new KPRetrieval({
minQuality: 0.85,
knowledgeTypes: ["ReasoningTrace", "ToolCallPattern"],
limit: 3,
apiKey: "kp_your_api_key",
});

const results = await retrieval.search("SQL injection detection", "security");
for (const unit of results) {
console.log(`[${unit["@type"]}] ${unit.id} (score: ${unit.metadata.quality_score})`);
}

searchSkills(query, opts?)

Searches the registry for SKILL.md entries.

async searchSkills(
query: string,
opts?: { domain?: string; tags?: string[]; limit?: number },
): Promise<unknown[]>

Parameters:

ParameterTypeDescription
querystringFree-text search query
opts.domainstring(optional) Filter by domain
opts.tagsstring[](optional) Filter by tags
opts.limitnumber(optional) Override default limit

Example:

const skills = await retrieval.searchSkills("code review", {
tags: ["security", "quality"],
limit: 10,
});

toFewShot(unit)

Formats a KnowledgeUnit as plain text suitable for few-shot prompting in LLM contexts.

toFewShot(unit: KnowledgeUnit): string

The output format depends on the unit type:

  • ReasoningTrace: Each step formatted as [TYPE] content
  • ToolCallPattern: Pattern name, description, and step-by-step tool sequence
  • ExpertSOP: SOP name, domain, and decision tree steps

Example:

const units = await retrieval.search("deploy to production");

const fewShotContext = units.map((u) => retrieval.toFewShot(u)).join("\n---\n");

const prompt = `Here are relevant examples from past agent executions:

${fewShotContext}

Now handle the following task: Deploy service X to production.`;

Contribution Functions

Two standalone functions for contributing knowledge and skills to the registry.

contributeKnowledge(unit, config?)

Validates and submits a KnowledgeUnit to the registry.

import { contributeKnowledge } from "@knowledgepulse/sdk";
import type { ContributeConfig } from "@knowledgepulse/sdk";

async function contributeKnowledge(
unit: KnowledgeUnit,
config?: ContributeConfig,
): Promise<{ id: string; quality_score: number }>

Parameters:

ParameterTypeDescription
unitKnowledgeUnitThe knowledge unit to contribute
config.registryUrlstring(optional) Registry API endpoint
config.apiKeystring(optional) Bearer token for auth

Behavior:

  1. Validates the unit against KnowledgeUnitSchema (throws ValidationError on failure).
  2. Computes a SHA-256 idempotency key from the serialized unit.
  3. POSTs the unit to {registryUrl}/v1/knowledge with the Idempotency-Key header.
  4. Returns the assigned id and quality_score from the registry response.

Example:

import { contributeKnowledge, generateTraceId } from "@knowledgepulse/sdk";

const result = await contributeKnowledge(
{
"@context": "https://knowledgepulse.dev/schema/v1",
"@type": "ReasoningTrace",
id: generateTraceId(),
metadata: {
created_at: new Date().toISOString(),
task_domain: "devops",
success: true,
quality_score: 0.88,
visibility: "network",
privacy_level: "aggregated",
},
task: { objective: "Diagnose OOM crash in production" },
steps: [
{ step_id: 0, type: "thought", content: "Check memory metrics" },
{ step_id: 1, type: "tool_call", tool: { name: "grafana_query" } },
{ step_id: 2, type: "observation", content: "Memory spike at 14:32 UTC" },
],
outcome: { result_summary: "Identified memory leak in cache layer", confidence: 0.92 },
},
{ apiKey: "kp_your_api_key" },
);

console.log(result.id); // "kp:trace:..."
console.log(result.quality_score); // 0.88

contributeSkill(skillMdContent, visibility?, config?)

Submits a SKILL.md document to the registry.

import { contributeSkill } from "@knowledgepulse/sdk";

async function contributeSkill(
skillMdContent: string,
visibility?: Visibility, // Default: "network"
config?: ContributeConfig,
): Promise<{ id: string }>

Parameters:

ParameterTypeDefaultDescription
skillMdContentstring(required)Raw SKILL.md file content
visibilityVisibility"network"Visibility scope for the skill
config.registryUrlstring--Registry API endpoint
config.apiKeystring--Bearer token for auth

Example:

import { contributeSkill, generateSkillMd } from "@knowledgepulse/sdk";

const skillMd = generateSkillMd(
{ name: "incident-responder", description: "Handles production incidents" },
"## Instructions\n\nTriage the incident and coordinate the response team.",
{ knowledge_capture: true, domain: "incident-response", visibility: "org" },
);

const { id } = await contributeSkill(skillMd, "org", {
apiKey: "kp_your_api_key",
});

console.log(id); // "kp:skill:..."