Skip to main content
Sonzai Docs
教程·约 15 分钟

资源库存 + 知识库

追踪每个用户拥有的工具、许可证和订阅,并通过知识库中的实时成本数据进行丰富。 完成本教程后,您将拥有一个能告诉用户其总订阅支出、成本变化以及 应考虑的替代方案的智能体——所有这些都基于真实数据。

您将构建什么

  • → 一个包含 market_price 和层级信息的 software_license 实体知识库架构
  • → 一个通过 bulkUpdate 将实时定价数据推送到知识库的成本同步管道
  • → 一个具有 inventory 能力的智能体,在对话中自动追踪已分配的工具
  • → 一个将用户分配与当前知识库定价数据关联的组合查询

1. 定义实体架构

架构告诉知识库应为每种实体类型提取和索引哪些字段。 为 software_license 创建一个架构,以便平台知道如何存储和搜索您的许可证数据。

import { Sonzai } from "@sonzai-labs/agents";

const client = new Sonzai({ apiKey: process.env.SONZAI_API_KEY! });
const PROJECT_ID = "proj_abc123";

await client.knowledge.createSchema(PROJECT_ID, {
  entity_type: "software_license",
  display_name: "Software License",
  fields: [
    { name: "market_price",  type: "number",  indexed: true  },
    { name: "tier",          type: "string",  indexed: true  },
    { name: "category",      type: "string",  indexed: true  },
    { name: "license_type",  type: "string",  indexed: false },
    { name: "trend_30d",     type: "string",  indexed: false },
  ],
});

您只需创建一次架构。之后平台会自动验证和索引该类型的每个实体。

2. 注入初始数据

使用 insertFacts 插入第一批实体。这也是在上线前加载历史数据的方式。 包含关系信息,以便知识库能推荐替代或互补工具。

await client.knowledge.insertFacts(PROJECT_ID, {
  entities: [
    {
      type: "software_license",
      label: "Figma Enterprise",
      properties: {
        market_price: 75,
        tier: "Enterprise",
        category: "Design Tools",
        license_type: "per-seat-annual",
        trend_30d: "+5%",
      },
    },
    {
      type: "software_license",
      label: "Slack Business+",
      properties: {
        market_price: 12.50,
        tier: "Business",
        category: "Communication",
        license_type: "per-seat-monthly",
        trend_30d: "+3%",
      },
    },
    {
      type: "category",
      label: "Design Tools",
      properties: { vendor_count: 18, avg_seat_cost: 45 },
    },
  ],
  relationships: [
    { from_label: "Figma Enterprise",  to_label: "Design Tools", edge_type: "belongs_to" },
    { from_label: "Slack Business+",   to_label: "Communication", edge_type: "belongs_to" },
    { from_label: "Figma Enterprise",  to_label: "Slack Business+", edge_type: "commonly_bundled" },
  ],
  source: "seed_v1",
});

3. 使用 bulkUpdate 保持定价更新

按计划(如每日 cron)运行成本同步任务,从供应商数据源获取当前定价并推送到知识库。bulkUpdate 通过标签匹配将属性合并到现有节点——无需删除和重新插入。

// cost-sync.ts — run daily
import { Sonzai } from "@sonzai-labs/agents";
import { fetchLatestPricing } from "./vendor-api"; // your data source

const client = new Sonzai({ apiKey: process.env.SONZAI_API_KEY! });
const PROJECT_ID = "proj_abc123";

async function syncPricing() {
  const pricing = await fetchLatestPricing(); // [{ name, price, trend }]

  await client.knowledge.bulkUpdate(PROJECT_ID, {
    updates: pricing.map((license) => ({
      entity_type: "software_license",
      label: license.name,
      properties: {
        market_price: license.price,
        trend_30d: license.trend,
        last_synced: new Date().toISOString(),
      },
      // upsert: true — creates the node if it doesn't exist yet
      upsert: true,
    })),
  });

  console.log(`Synced ${pricing.length} license prices`);
}

syncPricing();

批量大小

小于等于 100 项的批次会同步处理(即时响应)。更大的批次会排队异步处理—— 响应中包含一个可轮询完成状态的任务 ID。

4. 在智能体上启用库存功能

在智能体上启用 inventoryknowledge 能力。 这会自动为智能体提供 sonzai_inventory_updatesonzai_inventory 工具—— 无需提示工程。

const AGENT_ID = "agent_xyz";

await client.agents.updateCapabilities(AGENT_ID, {
  inventory: true,   // enables sonzai_inventory_update + sonzai_inventory tools
  knowledge: true,   // enables knowledge_search tool
  project_id: PROJECT_ID,  // which KB to join against
});

您也可以在仪表板中设置:前往 智能体 → 您的智能体 → 能力 并 启用 库存

5. 让智能体在对话中追踪资源

启用库存后,当用户提到他们使用的工具或订阅时,智能体会自动调用 sonzai_inventory_update。您只需正常聊天—— 平台会处理知识库解析和存储。

// Your backend chat endpoint
for await (const event of client.agents.chatStream(AGENT_ID, {
  userId: "user_123",
  messages: [
    {
      role: "user",
      content: "We just provisioned 10 Figma Enterprise seats at $75/seat.",
    },
  ],
})) {
  // The agent streams its reply — and internally calls
  // sonzai_inventory_update({ action: "add", item_type: "software_license",
  //   description: "Figma Enterprise", properties: { plan: "Enterprise",
  //   purchase_price: 75, quantity: 10 } })
  // The platform resolves the KB node, stores the link, and the agent
  // continues the conversation without interruption.
  process.stdout.write(event.choices?.[0]?.delta?.content ?? "");
}

知识库解析原理:平台在知识库中搜索物品描述。 如果恰好匹配一个节点,则自动关联。如果有多个候选,响应会返回 status: "disambiguation_needed" 和候选列表, 以便智能体向用户确认。

6. 查询丰富后的组合

使用 mode="value" 获取每个用户资源与最新知识库定价数据的关联。 平台自动计算 gain_loss(market_price - purchase_price) × quantity

const portfolio = await client.agents.inventory.query(AGENT_ID, "user_123", {
  mode: "value",
  project_id: PROJECT_ID,
});

// portfolio.items:
// [
//   {
//     fact_id: "fact_abc",
//     item_label: "Figma Enterprise",
//     kb_node_id: "node_xyz",
//     user_properties: { plan: "Enterprise", purchase_price: 75, quantity: 10 },
//     market_properties: { market_price: 80, tier: "Enterprise", trend_30d: "+5%" },
//     gain_loss: 50,
//   },
// ]
// portfolio.totals: { "market_price:sum": 800, "*:count": 10 }

console.log(`Portfolio value: $${portfolio.totals?.["market_price:sum"]}`);
console.log(`Total cost change: $${portfolio.items.reduce((s, i) => s + i.gain_loss, 0)}`);

您还可以使用 mode="aggregate" aggregations 参数获取组合级别的汇总,无需列出每个资源—— 适用于拥有大量订阅的组织。

// Aggregate: total count + total subscription cost, grouped by item_type
const agg = await client.agents.inventory.query(AGENT_ID, "user_123", {
  mode: "aggregate",
  aggregations: "market_price:sum,*:count",
  group_by: "item_type",
  project_id: PROJECT_ID,
});
// agg.totals: { "market_price:sum": 875, "*:count": 12 }
// agg.groups: [{ group: "software_license", values: { sum: 875, count: 12 } }]

7. 批量导入现有订阅

如果用户已有一组现有订阅(来自 CSV、采购系统导出等), 请批量导入而非等待智能体在对话中发现每个资源。

await client.agents.inventory.batchImport(AGENT_ID, "user_123", {
  item_type: "software_license",
  project_id: PROJECT_ID,
  items: [
    {
      description: "Figma Enterprise",
      properties: { quantity: 10, plan: "Enterprise", purchase_price: 75 },
    },
    {
      description: "GitHub Enterprise",
      properties: { quantity: 25, plan: "Enterprise", purchase_price: 21 },
    },
  ],
});

每批最多 1,000 项

批量端点每次调用最多处理 1,000 项。对于更大的导入, 请拆分为多次调用或使用仪表板中的 CSV 导入功能。

下一步

  • → 在知识库中设置推荐规则,向用户推荐替代工具
  • → 添加趋势追踪(7天/30天/90天)以支持"最大成本增长"报告
  • → 在 仪表板 → 智能体 → 您的智能体 → 用户 → 选择用户 → 库存/资产 中查看每用户库存
  • → 阅读 知识库 参考了解架构、分析规则和全文搜索