[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6N0WMZB8EMVH7N89V2SPBKX":3,"skill-same:01M6N0WMZB8EMVH7N89V2SPBKX":77},{"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":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":55,"commitSha":56,"skillDirectory":57,"forksCount":58,"repositoryHtmlUrl":59,"repositoryHomepageUrl":6,"ownerHtmlUrl":60,"ownerBlogUrl":61,"ownerDescription":62,"updatedAt":63,"install":64,"resources":76},"01M6N0WMZB8EMVH7N89V2SPBKX","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",32762,"MIT","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\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],"webhook transforms","transforms","webhook","define","generic","for","true","URL","event","sms","register","search","get","signals","social","up","process","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\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":45,"version":48,"mutating":49,"triggers":50,"description":54},[46,47,30],"put_page","add_timeline_entry","1.0.0",true,[51,52,53],"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","master","074ec301549ded4930f04d2c3b22d709a6c095cc","skills\u002Fwebhook-transforms",4884,"https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain","https:\u002F\u002Fgithub.com\u002Fgarrytan","https:\u002F\u002Fblog.garrytan.com","Writes software, dreams. ","2026-11-13 04:05:07",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":49},[66,69,72],{"tool":67,"command":68},"npx","npx skills add garrytan\u002Fgbrain --skill webhook-transforms",{"tool":70,"command":71},"bunx","bunx skills add garrytan\u002Fgbrain --skill webhook-transforms",{"tool":73,"command":74},"pnpm","pnpm dlx skills add garrytan\u002Fgbrain --skill webhook-transforms","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Fskills\u002Fwebhook-transforms\u002FSKILL.md",[],[78,89,95,116,142,156],{"skillNo":79,"name":80,"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":81,"categories":82,"keywords":83,"publishedAt":40},"01M6N109FNGH1PK49T734PZXGB","query-helper","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fquery-helper\u002FSKILL.md",[],[84,85,86,30,37,87,88],"query helper","helper","query","find","false",{"skillNo":90,"name":91,"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":92,"categories":93,"keywords":94,"publishedAt":40},"01M6N108A23GW6NGQEQ0E7GV0A","broken","https:\u002F\u002Fgithub.com\u002Fgarrytan\u002Fgbrain\u002Fblob\u002Fmaster\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fbroken\u002FSKILL.md",[],[91],{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":40},"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",[],[102,103,104,25,105,37,106,107,34,108,86,109,110,111,112,113,114,115,30],"brain ops","brain","ops","attribution","read","write","look","pages","people","with","enrich","web","path","source",{"skillNo":117,"name":118,"nameZh":6,"description":119,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":120,"categories":121,"keywords":127,"publishedAt":40},"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",[122],{"categoryNo":123,"categoryName":124,"taxonomyType":125,"taxonomyTypeDesc":126},"01JBSEEDCAT000000000000034","行政与办公人员","PROFESSION","适用职业",[128,129,130,131,132,30,133,134,135,86,88,136,137,138,139,140,24,141],"meeting","prep","meeting prep","me","prepare","brief","open","build","loops","about","you","briefing","threads","Meet",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":148,"publishedAt":40},"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",[],[149,150,151,30,152,88,153,154,155],"inbox zero","ZeRO","inbox","clear","replies","my","triage",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":162,"publishedAt":40},"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",[],[163,164,165,109,103,166,167,107,168,25,30,169],"deal memo","deal","memo","draft","investment","history","founder"]