From 0e40d0b67f30fcf49fd0809e7b4c7615bb8b3aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Emre=20Kabakc=C4=B1?= Date: Tue, 26 May 2026 14:16:44 +0100 Subject: [PATCH] fix(examples): use valid event kinds in lobu-crm reactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The funnel-digest and inbound-triage reactions called client.knowledge.save with semantic_type "funnel_digest" / "lead_interaction", which are not registered event kinds. knowledge.save validates semantic_type against the agent's event_kinds and throws ScriptError ("Invalid kind") — and because it runs before client.notifications.send, the reaction aborts and the digest never reaches #leads. Switch to the built-in kinds "summary" (digest) and "observation" (triage) and keep the domain label in metadata.kind so week-over-week queries still work. --- examples/lobu-crm/funnel-digest.reaction.ts | 12 ++++++++---- examples/lobu-crm/inbound-triage.reaction.ts | 10 +++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/lobu-crm/funnel-digest.reaction.ts b/examples/lobu-crm/funnel-digest.reaction.ts index ae49186c8..9f87aff5d 100644 --- a/examples/lobu-crm/funnel-digest.reaction.ts +++ b/examples/lobu-crm/funnel-digest.reaction.ts @@ -4,9 +4,10 @@ * Runs after the weekly Monday-9am window completes. `ctx.extracted_data` is * whatever the watcher's `extraction_schema` produced — funnel snapshot, top * action, stale leads, etc. We: - * 1. persist the digest as a `funnel_digest` event linked to every lead the - * watcher knows about, so the next digest can compare stage_counts - * week-over-week without re-running classification; and + * 1. persist the digest as a `summary` event (tagged `metadata.kind: + * "funnel_digest"`) linked to every lead the watcher knows about, so the + * next digest can compare stage_counts week-over-week without re-running + * classification; and * 2. push it to the team via `client.notifications.send` — which fans out to * the org's active bot connections (the #leads Slack connection) and the * in-app inbox. `watcher_source` attributes it to this window. @@ -43,8 +44,11 @@ export default async ( // CRM data and discoverable from any lead the watcher already touches. entity_ids: ctx.entities.map((e) => e.id), content, - semantic_type: "funnel_digest", + // `semantic_type` must be a registered event kind; "summary" fits a digest. + // The domain label lives in metadata so it stays queryable. + semantic_type: "summary", metadata: { + kind: "funnel_digest", window_id: ctx.window.id, watcher_slug: ctx.watcher.slug, stage_counts: data.stage_counts ?? {}, diff --git a/examples/lobu-crm/inbound-triage.reaction.ts b/examples/lobu-crm/inbound-triage.reaction.ts index 210ff32f4..233be01f6 100644 --- a/examples/lobu-crm/inbound-triage.reaction.ts +++ b/examples/lobu-crm/inbound-triage.reaction.ts @@ -2,8 +2,9 @@ * Reaction for the `inbound-triage` watcher. * * Fires every 2h after the watcher LLM extracts new and enriched leads from - * GitHub/X/HN signals. Persists a `lead_interaction` event per run so the next - * digest can count them, and — when the run is notable — pushes the recommended + * GitHub/X/HN signals. Persists an `observation` event (tagged `metadata.kind: + * "lead_interaction"`) per run so the next digest can count them, and — when + * the run is notable — pushes the recommended * actions to the team via `client.notifications.send` (fans out to the #leads * Slack connection + the in-app inbox). */ @@ -38,8 +39,11 @@ export default async ( await client.knowledge.save({ entity_ids: ctx.entities.map((e) => e.id), content: summary, - semantic_type: "lead_interaction", + // `semantic_type` must be a registered event kind; "observation" fits a + // triage note. The domain label lives in metadata so it stays queryable. + semantic_type: "observation", metadata: { + kind: "lead_interaction", window_id: ctx.window.id, new_lead_count: data.new_leads?.length ?? 0, action_count: actions.length,