agentsclimarketplace

Glean webhooks events

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/glean-pack/skills/glean-webhooks-events

'Implement event-driven Glean indexing triggered by source system webhooks fromFrom its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill glean-webhooks-events

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

4.2 KB, 887 tokens by cl100k_base, as published. Nobody here has run it

Glean Webhooks & Events

Overview

Glean uses an event-driven indexing model where source system webhooks trigger incremental updates to the Glean Indexing API. Instead of emitting its own webhooks, Glean receives document changes from platforms like GitHub, Confluence, and Notion. You can also monitor internal Glean events such as document indexing completion, permission changes, connector sync status, and search anomalies through the admin API.

Webhook Registration

// Register a source system webhook that pushes to Glean Indexing API
const response = await fetch("https://yourapp.com/admin/webhooks", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    url: "https://yourapp.com/webhooks/glean-indexer",
    events: ["document.indexed", "permission.changed", "connector.synced", "search.anomaly"],
    secret: process.env.GLEAN_WEBHOOK_SECRET,
  }),
});

Signature Verification

import crypto from "crypto";
import { Request, Response, NextFunction } from "express";

function verifyGleanSignature(req: Request, res: Response, next: NextFunction) {
  const signature = req.headers["x-glean-signature"] as string;
  const expected = crypto.createHmac("sha256", process.env.GLEAN_WEBHOOK_SECRET!)
    .update(req.body).digest("hex");
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).json({ error: "Invalid signature" });
  }
  next();
}

Event Handler

import express from "express";
const app = express();

app.post("/webhooks/glean-indexer", express.raw({ type: "application/json" }), verifyGleanSignature, (req, res) => {
  const event = JSON.parse(req.body.toString());
  res.status(200).json({ received: true });

  switch (event.type) {
    case "document.indexed":
      confirmIndexStatus(event.data.datasource, event.data.doc_id); break;
    case "permission.changed":
      reindexPermissions(event.data.datasource, event.data.object_id); break;
    case "connector.synced":
      logSyncMetrics(event.data.connector_name, event.data.docs_processed); break;
    case "search.anomaly":
      alertOps(event.data.query_pattern, event.data.anomaly_type); break;
  }
});

Event Types

EventPayload FieldsUse Case
document.indexeddatasource, doc_id, index_time_msConfirm content is searchable
permission.changeddatasource, object_id, new_aclRe-sync access controls
connector.syncedconnector_name, docs_processed, errorsMonitor connector health
search.anomalyquery_pattern, anomaly_type, severityDetect unusual search behavior
document.deleteddatasource, doc_id, deleted_byAudit content removal

Retry & Idempotency

const processed = new Set<string>();

async function handleIdempotent(event: { id: string; type: string; data: any }) {
  if (processed.has(event.id)) return;
  await routeEvent(event);
  processed.add(event.id);
  if (processed.size > 10_000) {
    const entries = Array.from(processed);
    entries.slice(0, entries.length - 10_000).forEach((id) => processed.delete(id));
  }
}

Error Handling

IssueCauseFix
Index rejectedDocument exceeds size limitChunk large documents before indexing
Permission deniedStale OAuth token for connectorRefresh connector credentials in admin
Duplicate documentsSource sends create + update rapidlyDeduplicate by doc_id before indexing
Connector timeoutSource API rate limitedImplement exponential backoff in connector

Resources

Next Steps

See glean-security-basics.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.