[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6N0ENH6VJHYTC80JEVXDF44":3,"skill-same:01M6N0ENH6VJHYTC80JEVXDF44":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":57,"commitSha":58,"skillDirectory":59,"forksCount":60,"repositoryHtmlUrl":61,"repositoryHomepageUrl":6,"ownerHtmlUrl":62,"ownerBlogUrl":63,"ownerDescription":64,"updatedAt":65,"install":66,"resources":78},"01M6N0ENH6VJHYTC80JEVXDF44","webhook-transforms",null,"Generic framework for converting external events (SMS, meetings, social mentions)\ninto brain-ingestible signals. Define a transform function, register a webhook URL,\nand incoming events get processed through the brain pipeline.","garrytan\u002Fgbrain","garrytan","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F19957?v=4","01M6DJCCDDG53MTYYRTXAXFG17","Garry Tan","01M6MZQZCEN3RRMD33E1X9ZZR9",32847,"MIT","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Fplugin\u002Fskills\u002Fwebhook-transforms\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"webhook transforms","transforms","webhook","when","search","generic","for","true","URL","event","sms","register","define","get","signals","social","up","use","meetings","page","SET","pipeline","2026-11-10 10:12:30",false,"---\nname: webhook-transforms\nversion: 1.0.0\ndescription: |\n  Generic framework for converting external events (SMS, meetings, social mentions)\n  into brain-ingestible signals. Define a transform function, register a webhook URL,\n  and incoming events get processed through the brain pipeline.\ntriggers:\n  - \"set up webhook\"\n  - \"process webhook event\"\n  - \"transform this event\"\ntools:\n  - put_page\n  - add_timeline_entry\n  - search\nmutating: true\nwhen_to_use: \"Use when the user asks: \\\"set up webhook\\\", \\\"process webhook event\\\", \\\"transform this event\\\".\"\n---\n\n# Webhook Transforms\n\n## Contract\n\nThis skill guarantees:\n- External events are transformed into brain pages with proper citations\n- Raw payloads are preserved (dead-letter queue if transform fails)\n- Entity extraction runs on every transformed event\n- Input sanitization: no raw HTML\u002Fscript passes to brain pages\n- Error handling: transform failure logs raw payload, retries once\n\n## Phases\n\n1. **Define transform.** Map event schema to brain page format:\n   - Input: raw webhook payload (JSON)\n   - Output: brain page content (markdown) + metadata (slug, type, citations)\n   - Must sanitize: strip HTML tags, escape script content\n\n2. **Register webhook URL.** Provide the external service with the webhook endpoint.\n\n3. **On event received:**\n   - Parse payload\n   - Run transform function\n   - Write brain page via `gbrain put`\n   - Extract entities, run enrichment\n   - Add timeline entries to mentioned entities\n   - Sync: `gbrain sync`\n\n4. **Error handling:**\n   - If transform throws: log raw payload to `_dead-letter\u002F{timestamp}.md`\n   - Surface error type to agent\n   - Retry once\n   - Don't lose events\n\n## Example Transforms\n\n### SMS Received\n```\nInput: {from: \"+1555...\", body: \"Meeting moved to 3pm\", timestamp: \"...\"}\nOutput: Timeline entry on sender's brain page + task update if action item detected\n```\n\n### Meeting Completed\n```\nInput: {title: \"Weekly sync\", attendees: [...], transcript: \"...\", summary: \"...\"}\nOutput: Delegate to meeting-ingestion skill\n```\n\n### Social Mention\n```\nInput: {platform: \"twitter\", author: \"@handle\", text: \"...\", url: \"...\"}\nOutput: Brain page in media\u002F + entity extraction + backlinks\n```\n\n## Output Format\n\nEvent transformed and written to brain. Report: \"Webhook: {event_type} from {source}\n→ {brain_page_path}\"\n\n## When it fails\n\nFollow the [agent operator protocol](..\u002Fconventions\u002Fagent-operator-protocol.md) for any gbrain error `code`, exit code, `[AGENT]` block or notice block. Specific to this skill:\n\n- A transformed write returns `write_pending` (exit 10): the event is accepted; record the request id and poll it, never replay the event under a new id.\n- `source_binding_required` \u002F `insufficient_scope`: the webhook's token cannot write that source; tell the user which grant the brain host's operator must add.\n- A malformed payload: reject it with the parse error and log it; do not write a partial page.\n\n## Anti-Patterns\n\n- Passing raw HTML\u002Fscript to brain pages (XSS risk)\n- Silently dropping events when transform fails (use dead-letter queue)\n- Processing webhooks without entity extraction\n- Not sanitizing external input before brain writes\n","# Webhook Transforms\n\n## Contract\n\nThis skill guarantees:\n- External events are transformed into brain pages with proper citations\n- Raw payloads are preserved (dead-letter queue if transform fails)\n- Entity extraction runs on every transformed event\n- Input sanitization: no raw HTML\u002Fscript passes to brain pages\n- Error handling: transform failure logs raw payload, retries once\n\n## Phases\n\n1. **Define transform.** Map event schema to brain page format:\n   - Input: raw webhook payload (JSON)\n   - Output: brain page content (markdown) + metadata (slug, type, citations)\n   - Must sanitize: strip HTML tags, escape script content\n\n2. **Register webhook URL.** Provide the external service with the webhook endpoint.\n\n3. **On event received:**\n   - Parse payload\n   - Run transform function\n   - Write brain page via `gbrain put`\n   - Extract entities, run enrichment\n   - Add timeline entries to mentioned entities\n   - Sync: `gbrain sync`\n\n4. **Error handling:**\n   - If transform throws: log raw payload to `_dead-letter\u002F{timestamp}.md`\n   - Surface error type to agent\n   - Retry once\n   - Don't lose events\n\n## Example Transforms\n\n### SMS Received\n```\nInput: {from: \"+1555...\", body: \"Meeting moved to 3pm\", timestamp: \"...\"}\nOutput: Timeline entry on sender's brain page + task update if action item detected\n```\n\n### Meeting Completed\n```\nInput: {title: \"Weekly sync\", attendees: [...], transcript: \"...\", summary: \"...\"}\nOutput: Delegate to meeting-ingestion skill\n```\n\n### Social Mention\n```\nInput: {platform: \"twitter\", author: \"@handle\", text: \"...\", url: \"...\"}\nOutput: Brain page in media\u002F + entity extraction + backlinks\n```\n\n## Output Format\n\nEvent transformed and written to brain. Report: \"Webhook: {event_type} from {source}\n→ {brain_page_path}\"\n\n## When it fails\n\nFollow the [agent operator protocol](..\u002Fconventions\u002Fagent-operator-protocol.md) for any gbrain error `code`, exit code, `[AGENT]` block or notice block. Specific to this skill:\n\n- A transformed write returns `write_pending` (exit 10): the event is accepted; record the request id and poll it, never replay the event under a new id.\n- `source_binding_required` \u002F `insufficient_scope`: the webhook's token cannot write that source; tell the user which grant the brain host's operator must add.\n- A malformed payload: reject it with the parse error and log it; do not write a partial page.\n\n## Anti-Patterns\n\n- Passing raw HTML\u002Fscript to brain pages (XSS risk)\n- Silently dropping events when transform fails (use dead-letter queue)\n- Processing webhooks without entity extraction\n- Not sanitizing external input before brain writes\n",{"name":5,"tools":46,"version":49,"mutating":50,"triggers":51,"description":55,"when_to_use":56},[47,48,23],"put_page","add_timeline_entry","1.0.0",true,[52,53,54],"set up webhook","process webhook event","transform this event","Generic framework for converting external events (SMS, meetings, social mentions)\ninto brain-ingestible signals. Define a transform function, register a webhook URL,\nand incoming events get processed through the brain pipeline.\n","Use when the user asks: \"set up webhook\", \"process webhook event\", \"transform this event\".","master","074ec301549ded4930f04d2c3b22d709a6c095cc","plugin\u002Fskills\u002Fwebhook-transforms",4902,"https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain","https:\u002F\u002Fgithub.com\u002Fgarrytan","https:\u002F\u002Fblog.garrytan.com","Writes software, dreams. ","2026-11-14 04:11:30",{"source":8,"skillName":5,"commands":67,"prompt":77,"zipAvailable":50},[68,71,74],{"tool":69,"command":70},"npx","npx skills add garrytan\u002Fgbrain --skill webhook-transforms",{"tool":72,"command":73},"bunx","bunx skills add garrytan\u002Fgbrain --skill webhook-transforms",{"tool":75,"command":76},"pnpm","pnpm dlx skills add garrytan\u002Fgbrain --skill webhook-transforms","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Fplugin\u002Fskills\u002Fwebhook-transforms\u002FSKILL.md",[],[80,91,97,118,144,158],{"skillNo":81,"name":82,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":85,"publishedAt":41},"01M6N109FNGH1PK49T734PZXGB","query-helper","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fquery-helper\u002FSKILL.md",[],[86,87,88,23,38,89,90],"query helper","helper","query","find","false",{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":41},"01M6N108A23GW6NGQEQ0E7GV0A","broken","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fbroken\u002FSKILL.md",[],[93],{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":41},"01M6N105E88C5K2H03H0CC79G1","brain-ops","Read, enrich, and write brain pages with source attribution.","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fbrain-ops\u002FSKILL.md",[],[104,105,106,26,107,38,108,109,35,110,88,111,112,113,114,115,116,117,23],"brain ops","brain","ops","attribution","read","write","look","pages","people","with","enrich","web","path","source",{"skillNo":119,"name":120,"nameZh":6,"description":121,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":129,"publishedAt":41},"01M6N102GRMF22TVCNT6RK5MRD","meeting-prep","Build a briefing before you meet someone, from their recent threads, open loops and what they care about.","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog-query\u002Fskills\u002Fmeeting-prep\u002FSKILL.md",[124],{"categoryNo":125,"categoryName":126,"taxonomyType":127,"taxonomyTypeDesc":128},"01JBSEEDCAT000000000000034","行政与办公人员","PROFESSION","适用职业",[130,131,132,133,134,23,135,136,137,88,90,138,139,140,141,142,25,143],"meeting","prep","meeting prep","me","prepare","brief","open","build","loops","about","you","briefing","threads","Meet",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":150,"publishedAt":41},"01M6N1005QK7REHX5KGMNR5PF0","inbox-zero","Triage the inbox into replies, delegations and archives.","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog-query\u002Fskills\u002Finbox-zero\u002FSKILL.md",[],[151,152,153,23,154,90,155,156,157],"inbox zero","ZeRO","inbox","clear","replies","my","triage",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":41},"01M6N0ZXQ8RRRW71PNV61T57GP","deal-memo","Draft an investment memo from the deal pages and the founder history already in the brain.","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog-query\u002Fskills\u002Fdeal-memo\u002FSKILL.md",[],[165,166,167,111,105,168,169,109,170,26,23,171],"deal memo","deal","memo","draft","investment","history","founder"]