Knowledge Analytics
Turn the Knowledge Base graph into a recommendation engine — rules rank nodes by user affinity, trend velocity, or conversion rate, all readable through a simple query-time API.
Knowledge Analytics layers a ranking system on top of the Knowledge Base. Rules define scoring signals — per-user affinity for recommendations, aggregate velocity for trends — and readers fetch ranked results at query time with a single call. The graph backbone supplies the nodes and edges; analytics rules decide how to score and order them. The result is a reusable ranking layer that powers product recommendations, trending dashboards, and conversion tracking without building a separate data pipeline.
What you can build with it
- Product recommendations — "top-N products for this user" based on user affinity signals
- Trending topics — "what's rising this week across all users" via aggregate velocity scoring
- Conversion dashboards — which KB nodes convert (browse to engage to buy) and at what rate
- Per-segment ranking — different recommendation models for different user segments
- Feedback loops — record converted recommendations to continuously sharpen scoring over time
Quickstart
Create a recommendation rule, fetch ranked results for a user, then record whether the user acted on a recommendation.
import { Sonzai } from "@sonzai-labs/agents";
const client = new Sonzai({ apiKey: process.env.SONZAI_API_KEY! });
const projectId = "proj_abc123";
// 1. Create a recommendation rule
const rule = await client.knowledge.createAnalyticsRule(projectId, {
rule_type: "recommendation",
name: "product-affinity",
config: { target_entity_type: "product", scoring: "affinity" },
enabled: true,
schedule: "0 * * * *", // recompute hourly
});
// 2. Fetch top-5 recommendations for a user
const recs = await client.knowledge.getRecommendations(
projectId,
rule.rule_id,
"user_123", // source_id — the user whose affinity to score against
5,
);
for (const rec of recs.recommendations) {
console.log(rec.target_id, rec.score);
}
// 3. Record that the user converted on the top result
await client.knowledge.recordFeedback(projectId, {
source_node_id: "user_123",
target_node_id: recs.recommendations[0].target_id,
rule_id: rule.rule_id,
converted: true,
score_at_time: recs.recommendations[0].score,
});Core concepts
- Rule types —
"recommendation"scores nodes per source (e.g. per user), returning a personalised top-N list."trend"aggregates signals across all sources, returning global velocity rankings. - Config is rule-specific — the
configobject is a passthrough shape; its fields depend on the rule type and your scoring model. There is no fixed schema enforced by the SDK — pass whatever your rule implementation expects (e.g.target_entity_type,scoring,decay_factor). - Source and target semantics — recommendations take a
source_id(typically a user node ID) and return ranked nodes of the target entity type. The source must exist as a node in the Knowledge Base graph. - Scheduled vs manual — rules can carry an optional cron
schedulefor batch recomputation (e.g."0 * * * *"for hourly). CallRunAnalyticsRuleat any time to trigger a manual run outside the schedule. - Feedback closes the loop —
RecordFeedbackwrites a signal back against the source, target, and rule. Subsequent recomputation can weight nodes that historically converted higher, sharpening ranking over time. Use theactionfield to record fine-grained user intent:"converted"(user completed the action),"clicked"(user opened the recommendation),"dismissed"(user explicitly rejected it), or"ignored"(recommendation was shown but user did not interact).action: "converted"setsconverted: trueautomatically so existing aggregate conversion queries continue to work without changes.
Full API
| Method | Returns | Description |
|---|---|---|
createAnalyticsRule(projectId, { rule_type, name, config, enabled, schedule? }) | KBAnalyticsRule | Create a new analytics rule. rule_type is "recommendation" or "trend". |
listAnalyticsRules(projectId) | KBAnalyticsRuleListResponse | List all analytics rules for a project. |
getAnalyticsRule(projectId, ruleId) | KBAnalyticsRule | Fetch a single rule by ID. |
updateAnalyticsRule(projectId, ruleId, { name?, config?, enabled, schedule? }) | KBAnalyticsRule | Update rule properties. |
deleteAnalyticsRule(projectId, ruleId) | void | Delete a rule permanently. |
runAnalyticsRule(projectId, ruleId) | void | Trigger an immediate manual run of the rule. |
getRecommendations(projectId, ruleId, sourceId, limit?) | KBRecommendationsResponse | Fetch ranked recommendations for a source node. Returns .recommendations array of { target_id, target_type, score }. |
getTrends(projectId, nodeId) | KBTrendsResponse | Get trend aggregations for a specific node across all windows. Returns .trends array of { node_id, rule_id, window, value, direction }. |
getTrendRankings(projectId, ruleId, rankingType, window, limit?) | KBTrendRankingsResponse | Get the global leaderboard for a trend rule. window is a duration string such as "7d" or "24h". Returns .rankings array with rank and score. |
getConversions(projectId, ruleId, segment?) | KBConversionsResponse | Fetch conversion statistics for a rule, optionally filtered by segment key. Returns { shown_count, conversion_count, conversion_rate } per segment. |
recordFeedback(projectId, { source_node_id, target_node_id, rule_id, converted, score_at_time, action? }) | void | Record whether a recommended node was acted on. converted is a boolean — true means the user engaged with the recommendation. action is an optional string enum: "converted", "dismissed", "clicked", "ignored". Passing action: "converted" also sets converted: true for backward-compatible aggregate queries. |
getStats(projectId) | KBStats | General KB statistics (node counts, document counts, extraction tokens). |
Python keyword arguments
The Python SDK exposes get_recommendations, get_trends, get_trend_rankings, get_conversions, and record_feedback using keyword-only arguments after project_id. For example: client.knowledge.get_recommendations(project_id, rule_id="...", source_id="...", limit=10).
Combines with other features
With Knowledge Base — the graph is the substrate
Analytics rules run over KB nodes and edges. Entity schemas define what types of nodes exist; rules score those nodes. The recommended pattern is to define your entity schema first, then create rules that target it.
// 1. Define a product schema in the KB
await client.knowledge.createSchema(projectId, {
entity_type: "product",
fields: [
{ name: "price", type: "number", required: true },
{ name: "category", type: "string", required: true },
{ name: "in_stock", type: "boolean", required: true },
],
});
// 2. Push some product nodes
await client.knowledge.insertFacts(projectId, {
facts: [
{ entity_type: "product", label: "Razer Blade 16", properties: { price: 2999, category: "laptop", in_stock: true } },
{ entity_type: "product", label: "Razer DeathAdder V3", properties: { price: 79, category: "mouse", in_stock: true } },
],
});
// 3. Create a recommendation rule targeting the product entity type
const rule = await client.knowledge.createAnalyticsRule(projectId, {
rule_type: "recommendation",
name: "product-recs",
config: { target_entity_type: "product" },
enabled: true,
});With Inventory — per-user holdings drive per-user recommendations
Inventory writes create edges from a user node to the nodes they own. Those ownership edges flow into the recommendation model as affinity signals: items a user already owns inform which related nodes score highest.
// 1. User buys a product — record it in inventory
const { fact_id } = await client.agents.inventory.update("agent_abc", "user_123", {
action: "add",
item_type: "product",
description: "Razer DeathAdder V3",
properties: { purchase_date: "2026-04-01" },
});
// 2. The inventory write creates a user→product edge in the KB graph.
// The recommendation rule can now weight products related to the
// DeathAdder higher for this user.
const recs = await client.knowledge.getRecommendations(
projectId,
rule.rule_id,
"user_123",
5,
);
// recs.recommendations may now include accessories or similar peripheralsWith Agent Insights — conversation signals sharpen rankings
Agent Insights extract what users express interest in during conversations. Those interest signals can be passed into recommendation rule config as additional affinity weights, so a user who talks about budget peripherals gets different rankings than one who discusses high-end setups — without any explicit user input.
Tutorials
No dedicated Knowledge Analytics tutorial exists yet. The Knowledge Base tutorial covers schema setup and fact insertion — the prerequisite steps before creating analytics rules.
Next steps
- Knowledge Base — the graph backbone; define schemas and push nodes before creating rules
- Inventory — per-user holdings create user-to-node edges that feed the recommendation model
- Organization Knowledge Base — analytics rules can also run over org-scoped KB nodes for shared ranking across all users
Knowledge Base
Store and search structured facts, documents, and entity graphs that your AI agents query during conversations.
Organization-Global Knowledge Base
One organization-wide knowledge scope that every project under the tenant can read from. Use it for policies, shared lore, playbooks, or facts that belong to the whole organization rather than a single project.