[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-google-cloud-recaptcha-transaction-defense-integrator":3,"mdc--70ia16-key":36,"related-org-google-cloud-recaptcha-transaction-defense-integrator":1094,"related-repo-google-cloud-recaptcha-transaction-defense-integrator":1281},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":26,"repoUrl":27,"updatedAt":28,"license":29,"forks":30,"topics":31,"repo":32,"sourceUrl":34,"mdContent":35},"recaptcha-transaction-defense-integrator","integrate reCAPTCHA Enterprise transaction defense","Integrates reCAPTCHA Enterprise Transaction Defense and automates ground truth via PSP chargeback webhooks (Stripe, Adyen). Use when a user wants to protect transactions from fraud and close the feedback loop with automated annotations. Don't use for generic reCAPTCHA v2 checkbox integrations or non-transactional bot protection.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"google-cloud","Google Cloud","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fgoogle-cloud.png","GoogleCloudPlatform",[13,17,20,23],{"name":14,"slug":15,"type":16},"Security","security","tag",{"name":18,"slug":19,"type":16},"Payments","payments",{"name":21,"slug":22,"type":16},"API Development","api-development",{"name":24,"slug":25,"type":16},"Stripe","stripe",41,"https:\u002F\u002Fgithub.com\u002FGoogleCloudPlatform\u002Frecaptcha-enterprise-mobile-sdk","2026-07-12T07:40:50.58887",null,8,[],{"repoUrl":27,"stars":26,"forks":30,"topics":33,"description":29},[],"https:\u002F\u002Fgithub.com\u002FGoogleCloudPlatform\u002Frecaptcha-enterprise-mobile-sdk\u002Ftree\u002FHEAD\u002Fskills\u002Frecaptcha-transaction-defense-integrator","---\nname: recaptcha-transaction-defense-integrator\ndescription: Integrates reCAPTCHA Enterprise Transaction Defense and automates ground truth via PSP chargeback webhooks (Stripe, Adyen). Use when a user wants to protect transactions from fraud and close the feedback loop with automated annotations. Don't use for generic reCAPTCHA v2 checkbox integrations or non-transactional bot protection.\n---\n\n# reCAPTCHA Transaction Defense Integrator\n\nThis skill helps you integrate reCAPTCHA Transaction Defense into your Node.js\napplication and automate the \"ground truth\" feedback loop by listening to\nchargeback notifications from Payment Service Providers (PSPs) like Stripe and\nAdyen.\n\n## Prerequisites\n\n1.  **Google Cloud Project**: reCAPTCHA Enterprise must be enabled. The Fraud\n    Prevention feature must also be enabled in the reCAPTCHA settings for the\n    project.\n2.  **Authentication**: Your server must be authenticated to Google Cloud. The\n    easiest way is to set the `GOOGLE_APPLICATION_CREDENTIALS` environment\n    variable pointing to a downloaded Service Account JSON key.\n3.  **IAM Roles**: The authenticated Service Account requires the **`reCAPTCHA\n    Enterprise Agent`** (`roles\u002Frecaptchaenterprise.agent`) role to create and\n    annotate assessments. During the execution of this agent skill,\n    **`roles\u002Flogging.viewer`** is required so that the skill can automatically\n    validate the success of implementation.\n4.  **Environment Separation**: Create **two** reCAPTCHA keys: one for **Test**\n    (allowed domains: `localhost`, `127.0.0.1`) and one for **Prod** (your real\n    domain). Map these to environment variables (e.g., `RECAPTCHA_SITE_KEY_TEST`\n    and `RECAPTCHA_SITE_KEY_PROD`) to avoid \"Invalid Domain\" errors during\n    development.\n5.  **Node.js Dependencies**: Run `npm install\n    @google-cloud\u002Frecaptcha-enterprise` to install the required client library.\n\n## Workflows\n\n### 1. Integrate reCAPTCHA\n\nFirst check if the user is using a V3 key. This skill so far only supports the\nV3 integration.\n\n**Codebase Survey**: Passively inspect the user's codebase and dependencies\n(`package.json`, environment files, structure) to understand: 1. **Frontend\nFramework**: React, Vue, Angular, or Vanilla JS? 2. **State Management**: How is\nform state handled? 3. **Entry Point**: Where is the best place to inject the\n`\u003Cscript>` tag? 4. **Secrets Management**: Determine how the backend application\nmanages secrets (e.g., `.env`, Secret Manager). Adapt the secret loading when\ninjecting the integration logic to match this pattern.\n\nThen use [v3.md](references\u002Fv3.md) to understand common integration gotchas.\n\n**Action**: Read the text in `assets\u002Ffrontend-snippets.html` and\n`assets\u002Ffrontend-snippets.js`. **Instruction**: Inject those snippets directly\ninto the user's *existing* frontend code, adapting them on the fly to match the\ndiscovered Framework and State Management patterns.\n\n### 2. Integrate Transaction Protection (Best Practice: Multi-Stage)\n\nProtecting a transaction is most effective when done in two stages:\n\n1.  **Stage 1: Initial Frontend Assessment**: Collect the reCAPTCHA token on the\n    frontend (using `enterprise.js`) and send it to your backend. Perform a\n    `createAssessment` with the token and user identifiers (email). Block bots\n    and high-risk requests immediately.\n2.  **Stage 2: Post-Authorization Enriched Assessment**: Use a Payment Service\n    Provider (PSP) like Stripe with **manual capture**. After the user\n    authorizes the payment, use the webhook to retrieve real card data (last 4\n    digits, billing zip). Perform a **second** `createAssessment` with this\n    enriched data to catch \"stolen instrument\" fraud before capturing funds.\n\n**Codebase Survey (Database & Architecture)**: You must store the\n`assessmentName` or reCAPTCHA token to close the loop later. 1. **Architecture\nCheck**: Is the payment processing in the same service as the frontend serving?\nIf separated (Microservices), ensure you identify how to pass the\n`transactionId` across the boundary. 2. **Schema Check**: Identify the\n**Database Schema** and **ORM** (e.g., Prisma, Sequoia, TypeORM). *\n**CRITICAL**: `assessmentName` can be long. Use `VARCHAR(255)` or `TEXT`.\nConverting it to a standard UUID column (36 chars) will cause truncation and\nfailures. 3. **Mapping Strategy**: Determine where to store the `transactionId`\n\u003C-> `assessmentName` mapping.\n\n> **CRITICAL WARNING: Token Storage** Do **NOT** store the reCAPTCHA token in\n> Stripe's `metadata` field. The token is often larger than 2000 characters,\n> which exceeds Stripe's 500-character limit for metadata values, causing the\n> request to fail.\n>\n> **Solution**: 1. Generate a unique `transactionId` on your server. 2. Store\n> the token in a server-side store (e.g., Redis, Database, or in-memory map)\n> using the `transactionId` as the key. 3. Pass only the `transactionId` in the\n> Stripe metadata. 4. In your webhook, retrieve the token using the\n> `transactionId` from the metadata.\n\n**Reference**: See [recaptcha-api.md](references\u002Frecaptcha-api.md) for\nrequest\u002Fresponse schemas and the `expectedAction` requirement.\n\n**Action**: Read `assets\u002Frecaptcha-integration.js` and generate an equivalent\nNode.js integration within the user's backend codebase.\n\n> **Note**: The template uses placeholders (e.g., `'YOUR_PROJECT_ID'`). You must\n> manually wire these to the user's environment variables (e.g.,\n> `process.env.CLOUD_PROJECT_ID`).\n\n**Wiring**: 1. Import the generated `recaptcha-integration.js` in your payment\nprocessing route. 2. Call `createAssessment` **before** authorizing the charge\nwith your PSP.\n\n**Best Practice**: Adopt a **Fail Open** strategy. If the reCAPTCHA API fails or\nreturns an error (other than a fraudulent verdict), allow the transaction to\nproceed to avoid blocking legitimate users during outages. (The generated code\nincludes a try\u002Fcatch block for this purpose).\n\n### 3. Automate Ground Truth & Feedback Loop\n\nThe reCAPTCHA model improves when you provide feedback:\n\n1.  **Annotate**: When a transaction is confirmed as legitimate or fraudulent\n    (e.g., via a chargeback), call `annotateAssessment`.\n2.  **Webhooks**: Map PSP events (like Stripe's `charge.dispute.created`) to the\n    original reCAPTCHA assessment name.\n\n**Reference**: See [psp-webhooks.md](references\u002Fpsp-webhooks.md) for\nPSP-specific webhook handling.\n\n**Action**: Determine if the user is using `stripe` or `adyen` by reading\n`package.json`. Read the corresponding template (`assets\u002Fwebhook-stripe.js` or\n`assets\u002Fwebhook-adyen.js`) and inject the endpoint into their backend.\n\n> **Note**: If neither are detected directly in `package.json` (e.g., wrapped\n> via another library), look for imports or environment variables containing\n> \"Stripe\", \"Adyen\", or \"Payment\" to identify the integration point manually\n> before proceeding.\n\n### 4. Verify Integration Health & End-to-End Test\n\n**Step 1: Metric Check** To confirm that your keys are active and receiving\ntraffic, query the reCAPTCHA Enterprise API for metrics. **Action**: Read\n`assets\u002Fcheck-status.js`. Create this script temporarily in their workspace and\nexecute it via `node` (ensuring environment variables are populated). Review the\noutputs and delete the script.\n\n**Step 2: Logic Verification (Unit Test)** Verify your integration logic handles\ngood, bad, and invalid tokens correctly without needing real traffic.\n**Action**: Read `assets\u002Fverify-logic.js`. Create a temporary verification\nscript with the contents in the user's workspace, modifying the\n`require('.\u002Frecaptcha-integration')` line to match wherever you injected the\nintegration module in the previous step. Execute it via `node`, then delete it.\nThis checks the `createAssessment` function against various scenarios (high\nscore, low score, wrong action).\n\n**Step 3: End-to-End Transaction Test (Mandatory)** Do not consider the task\ncomplete until you have verified the full flow: 1. **Frontend**: Load the page,\ncheck browser console for reCAPTCHA token generation. 2. **Backend**: Process a\ntest transaction (e.g., using Stripe Test Mode card numbers). 3. **Logs**: Check\nserver logs to confirm `createAssessment` was called and returned a verdict. 4.\n**Webhook (Optional)**: Trigger a test dispute in the PSP dashboard and verify\nyour webhook receives it.\n\n## Resources\n\n-   **API Documentation**: [recaptcha-api.md](references\u002Frecaptcha-api.md)\n-   **PSP Webhooks Guide**: [psp-webhooks.md](references\u002Fpsp-webhooks.md)\n-   **Integration Asset**: `assets\u002Frecaptcha-integration.js`\n-   **Frontend Assets**: `assets\u002Ffrontend-snippets.html`,\n    `assets\u002Ffrontend-snippets.js`\n-   **Verification Asset**: `assets\u002Fverify-logic.js`\n-   **Webhook Assets**: `assets\u002Fwebhook-stripe.js`, `assets\u002Fwebhook-adyen.js`\n-   **Status Check Asset**: `assets\u002Fcheck-status.js`\n",{"data":37,"body":38},{"name":4,"description":6},{"type":39,"children":40},"root",[41,49,55,62,218,224,231,236,298,312,353,359,364,424,529,596,622,639,668,699,716,722,727,766,782,828,847,853,885,930,975,981],{"type":42,"tag":43,"props":44,"children":45},"element","h1",{"id":4},[46],{"type":47,"value":48},"text","reCAPTCHA Transaction Defense Integrator",{"type":42,"tag":50,"props":51,"children":52},"p",{},[53],{"type":47,"value":54},"This skill helps you integrate reCAPTCHA Transaction Defense into your Node.js\napplication and automate the \"ground truth\" feedback loop by listening to\nchargeback notifications from Payment Service Providers (PSPs) like Stripe and\nAdyen.",{"type":42,"tag":56,"props":57,"children":59},"h2",{"id":58},"prerequisites",[60],{"type":47,"value":61},"Prerequisites",{"type":42,"tag":63,"props":64,"children":65},"ol",{},[66,78,97,137,200],{"type":42,"tag":67,"props":68,"children":69},"li",{},[70,76],{"type":42,"tag":71,"props":72,"children":73},"strong",{},[74],{"type":47,"value":75},"Google Cloud Project",{"type":47,"value":77},": reCAPTCHA Enterprise must be enabled. The Fraud\nPrevention feature must also be enabled in the reCAPTCHA settings for the\nproject.",{"type":42,"tag":67,"props":79,"children":80},{},[81,86,88,95],{"type":42,"tag":71,"props":82,"children":83},{},[84],{"type":47,"value":85},"Authentication",{"type":47,"value":87},": Your server must be authenticated to Google Cloud. The\neasiest way is to set the ",{"type":42,"tag":89,"props":90,"children":92},"code",{"className":91},[],[93],{"type":47,"value":94},"GOOGLE_APPLICATION_CREDENTIALS",{"type":47,"value":96}," environment\nvariable pointing to a downloaded Service Account JSON key.",{"type":42,"tag":67,"props":98,"children":99},{},[100,105,107,116,118,124,126,135],{"type":42,"tag":71,"props":101,"children":102},{},[103],{"type":47,"value":104},"IAM Roles",{"type":47,"value":106},": The authenticated Service Account requires the ",{"type":42,"tag":71,"props":108,"children":109},{},[110],{"type":42,"tag":89,"props":111,"children":113},{"className":112},[],[114],{"type":47,"value":115},"reCAPTCHA Enterprise Agent",{"type":47,"value":117}," (",{"type":42,"tag":89,"props":119,"children":121},{"className":120},[],[122],{"type":47,"value":123},"roles\u002Frecaptchaenterprise.agent",{"type":47,"value":125},") role to create and\nannotate assessments. During the execution of this agent skill,\n",{"type":42,"tag":71,"props":127,"children":128},{},[129],{"type":42,"tag":89,"props":130,"children":132},{"className":131},[],[133],{"type":47,"value":134},"roles\u002Flogging.viewer",{"type":47,"value":136}," is required so that the skill can automatically\nvalidate the success of implementation.",{"type":42,"tag":67,"props":138,"children":139},{},[140,145,147,152,154,159,161,167,169,175,177,182,184,190,192,198],{"type":42,"tag":71,"props":141,"children":142},{},[143],{"type":47,"value":144},"Environment Separation",{"type":47,"value":146},": Create ",{"type":42,"tag":71,"props":148,"children":149},{},[150],{"type":47,"value":151},"two",{"type":47,"value":153}," reCAPTCHA keys: one for ",{"type":42,"tag":71,"props":155,"children":156},{},[157],{"type":47,"value":158},"Test",{"type":47,"value":160},"\n(allowed domains: ",{"type":42,"tag":89,"props":162,"children":164},{"className":163},[],[165],{"type":47,"value":166},"localhost",{"type":47,"value":168},", ",{"type":42,"tag":89,"props":170,"children":172},{"className":171},[],[173],{"type":47,"value":174},"127.0.0.1",{"type":47,"value":176},") and one for ",{"type":42,"tag":71,"props":178,"children":179},{},[180],{"type":47,"value":181},"Prod",{"type":47,"value":183}," (your real\ndomain). Map these to environment variables (e.g., ",{"type":42,"tag":89,"props":185,"children":187},{"className":186},[],[188],{"type":47,"value":189},"RECAPTCHA_SITE_KEY_TEST",{"type":47,"value":191},"\nand ",{"type":42,"tag":89,"props":193,"children":195},{"className":194},[],[196],{"type":47,"value":197},"RECAPTCHA_SITE_KEY_PROD",{"type":47,"value":199},") to avoid \"Invalid Domain\" errors during\ndevelopment.",{"type":42,"tag":67,"props":201,"children":202},{},[203,208,210,216],{"type":42,"tag":71,"props":204,"children":205},{},[206],{"type":47,"value":207},"Node.js Dependencies",{"type":47,"value":209},": Run ",{"type":42,"tag":89,"props":211,"children":213},{"className":212},[],[214],{"type":47,"value":215},"npm install @google-cloud\u002Frecaptcha-enterprise",{"type":47,"value":217}," to install the required client library.",{"type":42,"tag":56,"props":219,"children":221},{"id":220},"workflows",[222],{"type":47,"value":223},"Workflows",{"type":42,"tag":225,"props":226,"children":228},"h3",{"id":227},"_1-integrate-recaptcha",[229],{"type":47,"value":230},"1. Integrate reCAPTCHA",{"type":42,"tag":50,"props":232,"children":233},{},[234],{"type":47,"value":235},"First check if the user is using a V3 key. This skill so far only supports the\nV3 integration.",{"type":42,"tag":50,"props":237,"children":238},{},[239,244,246,252,254,259,261,266,268,273,275,281,283,288,290,296],{"type":42,"tag":71,"props":240,"children":241},{},[242],{"type":47,"value":243},"Codebase Survey",{"type":47,"value":245},": Passively inspect the user's codebase and dependencies\n(",{"type":42,"tag":89,"props":247,"children":249},{"className":248},[],[250],{"type":47,"value":251},"package.json",{"type":47,"value":253},", environment files, structure) to understand: 1. ",{"type":42,"tag":71,"props":255,"children":256},{},[257],{"type":47,"value":258},"Frontend\nFramework",{"type":47,"value":260},": React, Vue, Angular, or Vanilla JS? 2. ",{"type":42,"tag":71,"props":262,"children":263},{},[264],{"type":47,"value":265},"State Management",{"type":47,"value":267},": How is\nform state handled? 3. ",{"type":42,"tag":71,"props":269,"children":270},{},[271],{"type":47,"value":272},"Entry Point",{"type":47,"value":274},": Where is the best place to inject the\n",{"type":42,"tag":89,"props":276,"children":278},{"className":277},[],[279],{"type":47,"value":280},"\u003Cscript>",{"type":47,"value":282}," tag? 4. ",{"type":42,"tag":71,"props":284,"children":285},{},[286],{"type":47,"value":287},"Secrets Management",{"type":47,"value":289},": Determine how the backend application\nmanages secrets (e.g., ",{"type":42,"tag":89,"props":291,"children":293},{"className":292},[],[294],{"type":47,"value":295},".env",{"type":47,"value":297},", Secret Manager). Adapt the secret loading when\ninjecting the integration logic to match this pattern.",{"type":42,"tag":50,"props":299,"children":300},{},[301,303,310],{"type":47,"value":302},"Then use ",{"type":42,"tag":304,"props":305,"children":307},"a",{"href":306},"references\u002Fv3.md",[308],{"type":47,"value":309},"v3.md",{"type":47,"value":311}," to understand common integration gotchas.",{"type":42,"tag":50,"props":313,"children":314},{},[315,320,322,328,330,336,338,343,345,351],{"type":42,"tag":71,"props":316,"children":317},{},[318],{"type":47,"value":319},"Action",{"type":47,"value":321},": Read the text in ",{"type":42,"tag":89,"props":323,"children":325},{"className":324},[],[326],{"type":47,"value":327},"assets\u002Ffrontend-snippets.html",{"type":47,"value":329}," and\n",{"type":42,"tag":89,"props":331,"children":333},{"className":332},[],[334],{"type":47,"value":335},"assets\u002Ffrontend-snippets.js",{"type":47,"value":337},". ",{"type":42,"tag":71,"props":339,"children":340},{},[341],{"type":47,"value":342},"Instruction",{"type":47,"value":344},": Inject those snippets directly\ninto the user's ",{"type":42,"tag":346,"props":347,"children":348},"em",{},[349],{"type":47,"value":350},"existing",{"type":47,"value":352}," frontend code, adapting them on the fly to match the\ndiscovered Framework and State Management patterns.",{"type":42,"tag":225,"props":354,"children":356},{"id":355},"_2-integrate-transaction-protection-best-practice-multi-stage",[357],{"type":47,"value":358},"2. Integrate Transaction Protection (Best Practice: Multi-Stage)",{"type":42,"tag":50,"props":360,"children":361},{},[362],{"type":47,"value":363},"Protecting a transaction is most effective when done in two stages:",{"type":42,"tag":63,"props":365,"children":366},{},[367,393],{"type":42,"tag":67,"props":368,"children":369},{},[370,375,377,383,385,391],{"type":42,"tag":71,"props":371,"children":372},{},[373],{"type":47,"value":374},"Stage 1: Initial Frontend Assessment",{"type":47,"value":376},": Collect the reCAPTCHA token on the\nfrontend (using ",{"type":42,"tag":89,"props":378,"children":380},{"className":379},[],[381],{"type":47,"value":382},"enterprise.js",{"type":47,"value":384},") and send it to your backend. Perform a\n",{"type":42,"tag":89,"props":386,"children":388},{"className":387},[],[389],{"type":47,"value":390},"createAssessment",{"type":47,"value":392}," with the token and user identifiers (email). Block bots\nand high-risk requests immediately.",{"type":42,"tag":67,"props":394,"children":395},{},[396,401,403,408,410,415,417,422],{"type":42,"tag":71,"props":397,"children":398},{},[399],{"type":47,"value":400},"Stage 2: Post-Authorization Enriched Assessment",{"type":47,"value":402},": Use a Payment Service\nProvider (PSP) like Stripe with ",{"type":42,"tag":71,"props":404,"children":405},{},[406],{"type":47,"value":407},"manual capture",{"type":47,"value":409},". After the user\nauthorizes the payment, use the webhook to retrieve real card data (last 4\ndigits, billing zip). Perform a ",{"type":42,"tag":71,"props":411,"children":412},{},[413],{"type":47,"value":414},"second",{"type":47,"value":416}," ",{"type":42,"tag":89,"props":418,"children":420},{"className":419},[],[421],{"type":47,"value":390},{"type":47,"value":423}," with this\nenriched data to catch \"stolen instrument\" fraud before capturing funds.",{"type":42,"tag":50,"props":425,"children":426},{},[427,432,434,440,442,447,449,455,457,462,464,469,471,476,478,483,485,490,492,498,500,506,508,513,515,520,522,527],{"type":42,"tag":71,"props":428,"children":429},{},[430],{"type":47,"value":431},"Codebase Survey (Database & Architecture)",{"type":47,"value":433},": You must store the\n",{"type":42,"tag":89,"props":435,"children":437},{"className":436},[],[438],{"type":47,"value":439},"assessmentName",{"type":47,"value":441}," or reCAPTCHA token to close the loop later. 1. ",{"type":42,"tag":71,"props":443,"children":444},{},[445],{"type":47,"value":446},"Architecture\nCheck",{"type":47,"value":448},": Is the payment processing in the same service as the frontend serving?\nIf separated (Microservices), ensure you identify how to pass the\n",{"type":42,"tag":89,"props":450,"children":452},{"className":451},[],[453],{"type":47,"value":454},"transactionId",{"type":47,"value":456}," across the boundary. 2. ",{"type":42,"tag":71,"props":458,"children":459},{},[460],{"type":47,"value":461},"Schema Check",{"type":47,"value":463},": Identify the\n",{"type":42,"tag":71,"props":465,"children":466},{},[467],{"type":47,"value":468},"Database Schema",{"type":47,"value":470}," and ",{"type":42,"tag":71,"props":472,"children":473},{},[474],{"type":47,"value":475},"ORM",{"type":47,"value":477}," (e.g., Prisma, Sequoia, TypeORM). *\n",{"type":42,"tag":71,"props":479,"children":480},{},[481],{"type":47,"value":482},"CRITICAL",{"type":47,"value":484},": ",{"type":42,"tag":89,"props":486,"children":488},{"className":487},[],[489],{"type":47,"value":439},{"type":47,"value":491}," can be long. Use ",{"type":42,"tag":89,"props":493,"children":495},{"className":494},[],[496],{"type":47,"value":497},"VARCHAR(255)",{"type":47,"value":499}," or ",{"type":42,"tag":89,"props":501,"children":503},{"className":502},[],[504],{"type":47,"value":505},"TEXT",{"type":47,"value":507},".\nConverting it to a standard UUID column (36 chars) will cause truncation and\nfailures. 3. ",{"type":42,"tag":71,"props":509,"children":510},{},[511],{"type":47,"value":512},"Mapping Strategy",{"type":47,"value":514},": Determine where to store the ",{"type":42,"tag":89,"props":516,"children":518},{"className":517},[],[519],{"type":47,"value":454},{"type":47,"value":521},"\n\u003C-> ",{"type":42,"tag":89,"props":523,"children":525},{"className":524},[],[526],{"type":47,"value":439},{"type":47,"value":528}," mapping.",{"type":42,"tag":530,"props":531,"children":532},"blockquote",{},[533,558],{"type":42,"tag":50,"props":534,"children":535},{},[536,541,543,548,550,556],{"type":42,"tag":71,"props":537,"children":538},{},[539],{"type":47,"value":540},"CRITICAL WARNING: Token Storage",{"type":47,"value":542}," Do ",{"type":42,"tag":71,"props":544,"children":545},{},[546],{"type":47,"value":547},"NOT",{"type":47,"value":549}," store the reCAPTCHA token in\nStripe's ",{"type":42,"tag":89,"props":551,"children":553},{"className":552},[],[554],{"type":47,"value":555},"metadata",{"type":47,"value":557}," field. The token is often larger than 2000 characters,\nwhich exceeds Stripe's 500-character limit for metadata values, causing the\nrequest to fail.",{"type":42,"tag":50,"props":559,"children":560},{},[561,566,568,573,575,580,582,587,589,594],{"type":42,"tag":71,"props":562,"children":563},{},[564],{"type":47,"value":565},"Solution",{"type":47,"value":567},": 1. Generate a unique ",{"type":42,"tag":89,"props":569,"children":571},{"className":570},[],[572],{"type":47,"value":454},{"type":47,"value":574}," on your server. 2. Store\nthe token in a server-side store (e.g., Redis, Database, or in-memory map)\nusing the ",{"type":42,"tag":89,"props":576,"children":578},{"className":577},[],[579],{"type":47,"value":454},{"type":47,"value":581}," as the key. 3. Pass only the ",{"type":42,"tag":89,"props":583,"children":585},{"className":584},[],[586],{"type":47,"value":454},{"type":47,"value":588}," in the\nStripe metadata. 4. In your webhook, retrieve the token using the\n",{"type":42,"tag":89,"props":590,"children":592},{"className":591},[],[593],{"type":47,"value":454},{"type":47,"value":595}," from the metadata.",{"type":42,"tag":50,"props":597,"children":598},{},[599,604,606,612,614,620],{"type":42,"tag":71,"props":600,"children":601},{},[602],{"type":47,"value":603},"Reference",{"type":47,"value":605},": See ",{"type":42,"tag":304,"props":607,"children":609},{"href":608},"references\u002Frecaptcha-api.md",[610],{"type":47,"value":611},"recaptcha-api.md",{"type":47,"value":613}," for\nrequest\u002Fresponse schemas and the ",{"type":42,"tag":89,"props":615,"children":617},{"className":616},[],[618],{"type":47,"value":619},"expectedAction",{"type":47,"value":621}," requirement.",{"type":42,"tag":50,"props":623,"children":624},{},[625,629,631,637],{"type":42,"tag":71,"props":626,"children":627},{},[628],{"type":47,"value":319},{"type":47,"value":630},": Read ",{"type":42,"tag":89,"props":632,"children":634},{"className":633},[],[635],{"type":47,"value":636},"assets\u002Frecaptcha-integration.js",{"type":47,"value":638}," and generate an equivalent\nNode.js integration within the user's backend codebase.",{"type":42,"tag":530,"props":640,"children":641},{},[642],{"type":42,"tag":50,"props":643,"children":644},{},[645,650,652,658,660,666],{"type":42,"tag":71,"props":646,"children":647},{},[648],{"type":47,"value":649},"Note",{"type":47,"value":651},": The template uses placeholders (e.g., ",{"type":42,"tag":89,"props":653,"children":655},{"className":654},[],[656],{"type":47,"value":657},"'YOUR_PROJECT_ID'",{"type":47,"value":659},"). You must\nmanually wire these to the user's environment variables (e.g.,\n",{"type":42,"tag":89,"props":661,"children":663},{"className":662},[],[664],{"type":47,"value":665},"process.env.CLOUD_PROJECT_ID",{"type":47,"value":667},").",{"type":42,"tag":50,"props":669,"children":670},{},[671,676,678,684,686,691,692,697],{"type":42,"tag":71,"props":672,"children":673},{},[674],{"type":47,"value":675},"Wiring",{"type":47,"value":677},": 1. Import the generated ",{"type":42,"tag":89,"props":679,"children":681},{"className":680},[],[682],{"type":47,"value":683},"recaptcha-integration.js",{"type":47,"value":685}," in your payment\nprocessing route. 2. Call ",{"type":42,"tag":89,"props":687,"children":689},{"className":688},[],[690],{"type":47,"value":390},{"type":47,"value":416},{"type":42,"tag":71,"props":693,"children":694},{},[695],{"type":47,"value":696},"before",{"type":47,"value":698}," authorizing the charge\nwith your PSP.",{"type":42,"tag":50,"props":700,"children":701},{},[702,707,709,714],{"type":42,"tag":71,"props":703,"children":704},{},[705],{"type":47,"value":706},"Best Practice",{"type":47,"value":708},": Adopt a ",{"type":42,"tag":71,"props":710,"children":711},{},[712],{"type":47,"value":713},"Fail Open",{"type":47,"value":715}," strategy. If the reCAPTCHA API fails or\nreturns an error (other than a fraudulent verdict), allow the transaction to\nproceed to avoid blocking legitimate users during outages. (The generated code\nincludes a try\u002Fcatch block for this purpose).",{"type":42,"tag":225,"props":717,"children":719},{"id":718},"_3-automate-ground-truth-feedback-loop",[720],{"type":47,"value":721},"3. Automate Ground Truth & Feedback Loop",{"type":42,"tag":50,"props":723,"children":724},{},[725],{"type":47,"value":726},"The reCAPTCHA model improves when you provide feedback:",{"type":42,"tag":63,"props":728,"children":729},{},[730,748],{"type":42,"tag":67,"props":731,"children":732},{},[733,738,740,746],{"type":42,"tag":71,"props":734,"children":735},{},[736],{"type":47,"value":737},"Annotate",{"type":47,"value":739},": When a transaction is confirmed as legitimate or fraudulent\n(e.g., via a chargeback), call ",{"type":42,"tag":89,"props":741,"children":743},{"className":742},[],[744],{"type":47,"value":745},"annotateAssessment",{"type":47,"value":747},".",{"type":42,"tag":67,"props":749,"children":750},{},[751,756,758,764],{"type":42,"tag":71,"props":752,"children":753},{},[754],{"type":47,"value":755},"Webhooks",{"type":47,"value":757},": Map PSP events (like Stripe's ",{"type":42,"tag":89,"props":759,"children":761},{"className":760},[],[762],{"type":47,"value":763},"charge.dispute.created",{"type":47,"value":765},") to the\noriginal reCAPTCHA assessment name.",{"type":42,"tag":50,"props":767,"children":768},{},[769,773,774,780],{"type":42,"tag":71,"props":770,"children":771},{},[772],{"type":47,"value":603},{"type":47,"value":605},{"type":42,"tag":304,"props":775,"children":777},{"href":776},"references\u002Fpsp-webhooks.md",[778],{"type":47,"value":779},"psp-webhooks.md",{"type":47,"value":781}," for\nPSP-specific webhook handling.",{"type":42,"tag":50,"props":783,"children":784},{},[785,789,791,796,797,803,805,810,812,818,820,826],{"type":42,"tag":71,"props":786,"children":787},{},[788],{"type":47,"value":319},{"type":47,"value":790},": Determine if the user is using ",{"type":42,"tag":89,"props":792,"children":794},{"className":793},[],[795],{"type":47,"value":25},{"type":47,"value":499},{"type":42,"tag":89,"props":798,"children":800},{"className":799},[],[801],{"type":47,"value":802},"adyen",{"type":47,"value":804}," by reading\n",{"type":42,"tag":89,"props":806,"children":808},{"className":807},[],[809],{"type":47,"value":251},{"type":47,"value":811},". Read the corresponding template (",{"type":42,"tag":89,"props":813,"children":815},{"className":814},[],[816],{"type":47,"value":817},"assets\u002Fwebhook-stripe.js",{"type":47,"value":819}," or\n",{"type":42,"tag":89,"props":821,"children":823},{"className":822},[],[824],{"type":47,"value":825},"assets\u002Fwebhook-adyen.js",{"type":47,"value":827},") and inject the endpoint into their backend.",{"type":42,"tag":530,"props":829,"children":830},{},[831],{"type":42,"tag":50,"props":832,"children":833},{},[834,838,840,845],{"type":42,"tag":71,"props":835,"children":836},{},[837],{"type":47,"value":649},{"type":47,"value":839},": If neither are detected directly in ",{"type":42,"tag":89,"props":841,"children":843},{"className":842},[],[844],{"type":47,"value":251},{"type":47,"value":846}," (e.g., wrapped\nvia another library), look for imports or environment variables containing\n\"Stripe\", \"Adyen\", or \"Payment\" to identify the integration point manually\nbefore proceeding.",{"type":42,"tag":225,"props":848,"children":850},{"id":849},"_4-verify-integration-health-end-to-end-test",[851],{"type":47,"value":852},"4. Verify Integration Health & End-to-End Test",{"type":42,"tag":50,"props":854,"children":855},{},[856,861,863,867,869,875,877,883],{"type":42,"tag":71,"props":857,"children":858},{},[859],{"type":47,"value":860},"Step 1: Metric Check",{"type":47,"value":862}," To confirm that your keys are active and receiving\ntraffic, query the reCAPTCHA Enterprise API for metrics. ",{"type":42,"tag":71,"props":864,"children":865},{},[866],{"type":47,"value":319},{"type":47,"value":868},": Read\n",{"type":42,"tag":89,"props":870,"children":872},{"className":871},[],[873],{"type":47,"value":874},"assets\u002Fcheck-status.js",{"type":47,"value":876},". Create this script temporarily in their workspace and\nexecute it via ",{"type":42,"tag":89,"props":878,"children":880},{"className":879},[],[881],{"type":47,"value":882},"node",{"type":47,"value":884}," (ensuring environment variables are populated). Review the\noutputs and delete the script.",{"type":42,"tag":50,"props":886,"children":887},{},[888,893,895,899,900,906,908,914,916,921,923,928],{"type":42,"tag":71,"props":889,"children":890},{},[891],{"type":47,"value":892},"Step 2: Logic Verification (Unit Test)",{"type":47,"value":894}," Verify your integration logic handles\ngood, bad, and invalid tokens correctly without needing real traffic.\n",{"type":42,"tag":71,"props":896,"children":897},{},[898],{"type":47,"value":319},{"type":47,"value":630},{"type":42,"tag":89,"props":901,"children":903},{"className":902},[],[904],{"type":47,"value":905},"assets\u002Fverify-logic.js",{"type":47,"value":907},". Create a temporary verification\nscript with the contents in the user's workspace, modifying the\n",{"type":42,"tag":89,"props":909,"children":911},{"className":910},[],[912],{"type":47,"value":913},"require('.\u002Frecaptcha-integration')",{"type":47,"value":915}," line to match wherever you injected the\nintegration module in the previous step. Execute it via ",{"type":42,"tag":89,"props":917,"children":919},{"className":918},[],[920],{"type":47,"value":882},{"type":47,"value":922},", then delete it.\nThis checks the ",{"type":42,"tag":89,"props":924,"children":926},{"className":925},[],[927],{"type":47,"value":390},{"type":47,"value":929}," function against various scenarios (high\nscore, low score, wrong action).",{"type":42,"tag":50,"props":931,"children":932},{},[933,938,940,945,947,952,954,959,961,966,968,973],{"type":42,"tag":71,"props":934,"children":935},{},[936],{"type":47,"value":937},"Step 3: End-to-End Transaction Test (Mandatory)",{"type":47,"value":939}," Do not consider the task\ncomplete until you have verified the full flow: 1. ",{"type":42,"tag":71,"props":941,"children":942},{},[943],{"type":47,"value":944},"Frontend",{"type":47,"value":946},": Load the page,\ncheck browser console for reCAPTCHA token generation. 2. ",{"type":42,"tag":71,"props":948,"children":949},{},[950],{"type":47,"value":951},"Backend",{"type":47,"value":953},": Process a\ntest transaction (e.g., using Stripe Test Mode card numbers). 3. ",{"type":42,"tag":71,"props":955,"children":956},{},[957],{"type":47,"value":958},"Logs",{"type":47,"value":960},": Check\nserver logs to confirm ",{"type":42,"tag":89,"props":962,"children":964},{"className":963},[],[965],{"type":47,"value":390},{"type":47,"value":967}," was called and returned a verdict. 4.\n",{"type":42,"tag":71,"props":969,"children":970},{},[971],{"type":47,"value":972},"Webhook (Optional)",{"type":47,"value":974},": Trigger a test dispute in the PSP dashboard and verify\nyour webhook receives it.",{"type":42,"tag":56,"props":976,"children":978},{"id":977},"resources",[979],{"type":47,"value":980},"Resources",{"type":42,"tag":982,"props":983,"children":984},"ul",{},[985,998,1011,1025,1046,1060,1080],{"type":42,"tag":67,"props":986,"children":987},{},[988,993,994],{"type":42,"tag":71,"props":989,"children":990},{},[991],{"type":47,"value":992},"API Documentation",{"type":47,"value":484},{"type":42,"tag":304,"props":995,"children":996},{"href":608},[997],{"type":47,"value":611},{"type":42,"tag":67,"props":999,"children":1000},{},[1001,1006,1007],{"type":42,"tag":71,"props":1002,"children":1003},{},[1004],{"type":47,"value":1005},"PSP Webhooks Guide",{"type":47,"value":484},{"type":42,"tag":304,"props":1008,"children":1009},{"href":776},[1010],{"type":47,"value":779},{"type":42,"tag":67,"props":1012,"children":1013},{},[1014,1019,1020],{"type":42,"tag":71,"props":1015,"children":1016},{},[1017],{"type":47,"value":1018},"Integration Asset",{"type":47,"value":484},{"type":42,"tag":89,"props":1021,"children":1023},{"className":1022},[],[1024],{"type":47,"value":636},{"type":42,"tag":67,"props":1026,"children":1027},{},[1028,1033,1034,1039,1041],{"type":42,"tag":71,"props":1029,"children":1030},{},[1031],{"type":47,"value":1032},"Frontend Assets",{"type":47,"value":484},{"type":42,"tag":89,"props":1035,"children":1037},{"className":1036},[],[1038],{"type":47,"value":327},{"type":47,"value":1040},",\n",{"type":42,"tag":89,"props":1042,"children":1044},{"className":1043},[],[1045],{"type":47,"value":335},{"type":42,"tag":67,"props":1047,"children":1048},{},[1049,1054,1055],{"type":42,"tag":71,"props":1050,"children":1051},{},[1052],{"type":47,"value":1053},"Verification Asset",{"type":47,"value":484},{"type":42,"tag":89,"props":1056,"children":1058},{"className":1057},[],[1059],{"type":47,"value":905},{"type":42,"tag":67,"props":1061,"children":1062},{},[1063,1068,1069,1074,1075],{"type":42,"tag":71,"props":1064,"children":1065},{},[1066],{"type":47,"value":1067},"Webhook Assets",{"type":47,"value":484},{"type":42,"tag":89,"props":1070,"children":1072},{"className":1071},[],[1073],{"type":47,"value":817},{"type":47,"value":168},{"type":42,"tag":89,"props":1076,"children":1078},{"className":1077},[],[1079],{"type":47,"value":825},{"type":42,"tag":67,"props":1081,"children":1082},{},[1083,1088,1089],{"type":42,"tag":71,"props":1084,"children":1085},{},[1086],{"type":47,"value":1087},"Status Check Asset",{"type":47,"value":484},{"type":42,"tag":89,"props":1090,"children":1092},{"className":1091},[],[1093],{"type":47,"value":874},{"items":1095,"total":1280},[1096,1114,1130,1152,1166,1177,1191,1206,1223,1236,1252,1262],{"slug":1097,"name":1097,"fn":1098,"description":1099,"org":1100,"tags":1101,"stars":1111,"repoUrl":1112,"updatedAt":1113},"kb-search","search and extract local knowledge base documents","Allows listing, searching and extracting information from local knowledge base documents for information about tables\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1102,1105,1108],{"name":1103,"slug":1104,"type":16},"Documentation","documentation",{"name":1106,"slug":1107,"type":16},"Knowledge Base","knowledge-base",{"name":1109,"slug":1110,"type":16},"Search","search",6749,"https:\u002F\u002Fgithub.com\u002FGoogleCloudPlatform\u002Fknowledge-catalog","2026-07-12T07:38:52.157375",{"slug":1115,"name":1116,"fn":1117,"description":1118,"org":1119,"tags":1120,"stars":1111,"repoUrl":1112,"updatedAt":1129},"knowledgecatalogdiscoveryagent","knowledge_catalog_discovery_agent","search and rank Knowledge Catalog data entries","Analyzes user queries, extracts relevant predicates, and utilizes Knowledge Catalog Search to find and rank the most relevant data entries. Engages with the user throughout the process.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1121,1124,1125,1128],{"name":1122,"slug":1123,"type":16},"Data Analysis","data-analysis",{"name":9,"slug":8,"type":16},{"name":1126,"slug":1127,"type":16},"Knowledge Management","knowledge-management",{"name":1109,"slug":1110,"type":16},"2026-07-12T07:38:22.196851",{"slug":1131,"name":1131,"fn":1132,"description":1133,"org":1134,"tags":1135,"stars":1149,"repoUrl":1150,"updatedAt":1151},"contributing","contribute to Cloud Foundation Fabric","End-to-end workflow for contributing to Cloud Foundation Fabric: triaging GitHub issues, proactive feature development, validating with tests and Policy Troubleshooter, and submitting sanitized Pull Requests. Use when addressing a Fabric GitHub issue, developing a module or FAST stage change, or preparing a branch for a pull request.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1136,1139,1142,1145,1146],{"name":1137,"slug":1138,"type":16},"Automation","automation",{"name":1140,"slug":1141,"type":16},"Engineering","engineering",{"name":1143,"slug":1144,"type":16},"GitHub","github",{"name":9,"slug":8,"type":16},{"name":1147,"slug":1148,"type":16},"Pull Requests","pull-requests",2062,"https:\u002F\u002Fgithub.com\u002FGoogleCloudPlatform\u002Fcloud-foundation-fabric","2026-07-31T06:23:36.935005",{"slug":1153,"name":1153,"fn":1154,"description":1155,"org":1156,"tags":1157,"stars":1149,"repoUrl":1150,"updatedAt":1165},"fabric-builder","generate Terraform code for Google Cloud","Generates idiomatic Cloud Foundation Fabric (CFF) Terraform code using CFF modules. Use when users ask to create GCP resources, use Fabric modules, or generate Terraform code for Google Cloud.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1158,1159,1162],{"name":9,"slug":8,"type":16},{"name":1160,"slug":1161,"type":16},"Infrastructure as Code","infrastructure-as-code",{"name":1163,"slug":1164,"type":16},"Terraform","terraform","2026-07-12T07:38:23.514555",{"slug":1167,"name":1167,"fn":1168,"description":1169,"org":1170,"tags":1171,"stars":1149,"repoUrl":1150,"updatedAt":1176},"fast-0-org-setup-prereqs","prepare prerequisites for FAST 0-org-setup","Guides the user step-by-step through the prerequisites for the FAST 0-org-setup stage, supporting both Standard GCP and Google Cloud Dedicated (GCD) environments. Use when a user asks to prepare or run prerequisites for 0-org-setup or bootstrap the FAST landing zone.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1172,1173],{"name":9,"slug":8,"type":16},{"name":1174,"slug":1175,"type":16},"Operations","operations","2026-07-12T07:38:28.127148",{"slug":1178,"name":1178,"fn":1179,"description":1180,"org":1181,"tags":1182,"stars":1188,"repoUrl":1189,"updatedAt":1190},"agent-aware-cli","design agent-aware command-line interfaces","Guide for designing and implementing command-line interfaces (CLIs) that are equally usable by human developers and automated coding agents. Use when the user wants to build a CLI, apply CLI best practices, or use Go with Cobra and Viper.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1183,1186,1187],{"name":1184,"slug":1185,"type":16},"CLI","cli",{"name":1140,"slug":1141,"type":16},{"name":9,"slug":8,"type":16},1150,"https:\u002F\u002Fgithub.com\u002FGoogleCloudPlatform\u002Fvertex-ai-creative-studio","2026-07-12T07:39:08.41406",{"slug":1192,"name":1192,"fn":1193,"description":1194,"org":1195,"tags":1196,"stars":1188,"repoUrl":1189,"updatedAt":1205},"build-mcp-genmedia","build and configure GenAI MCP servers","Builds the mcp-genmedia Go MCP servers (nanobanana, veo, lyria, gemini-multimodal, chirp3-hd, avtool) from source and wires them into settings.json. Use this skill whenever the MCP tools are missing or broken — typically at the start of a new session, after a container restart, or when \u002Ftmp has been wiped. The prebuilt binaries in \u002Fworkspace\u002F.local\u002Fbin\u002F have no exec bit and live on a noexec mount; this skill compiles fresh executables into \u002Ftmp\u002Fbin\u002F where execution is allowed.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1197,1198,1199,1202],{"name":21,"slug":22,"type":16},{"name":9,"slug":8,"type":16},{"name":1200,"slug":1201,"type":16},"LLM","llm",{"name":1203,"slug":1204,"type":16},"MCP","mcp","2026-07-12T07:39:10.911302",{"slug":1207,"name":1207,"fn":1208,"description":1209,"org":1210,"tags":1211,"stars":1188,"repoUrl":1189,"updatedAt":1222},"genmedia-audio-engineer","synthesize and mix audio content","Expert in audio synthesis, music generation, and mixing. Use when creating podcasts, background scores, or multi-track audio layering using mcp-chirp3-go, mcp-lyria-go, mcp-gemini-go, mcp-nanobanana-go, and mcp-avtool-go.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1212,1215,1218,1219],{"name":1213,"slug":1214,"type":16},"Audio","audio",{"name":1216,"slug":1217,"type":16},"Creative","creative",{"name":9,"slug":8,"type":16},{"name":1220,"slug":1221,"type":16},"Vertex AI","vertex-ai","2026-07-12T07:39:16.623879",{"slug":1224,"name":1224,"fn":1225,"description":1226,"org":1227,"tags":1228,"stars":1188,"repoUrl":1189,"updatedAt":1235},"genmedia-image-artist","generate and edit AI images","Expert in AI image generation and editing. Use when the user needs high-quality textures, character-consistent visuals, or image-to-image editing using mcp-nanobanana-go.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1229,1230,1231,1234],{"name":1216,"slug":1217,"type":16},{"name":9,"slug":8,"type":16},{"name":1232,"slug":1233,"type":16},"Image Generation","image-generation",{"name":1220,"slug":1221,"type":16},"2026-07-12T07:39:15.372822",{"slug":1237,"name":1237,"fn":1238,"description":1239,"org":1240,"tags":1241,"stars":1188,"repoUrl":1189,"updatedAt":1251},"genmedia-producer","produce multi-step media content","Expert media production assistant. Use when requested to help with storyboarding, podcast creation, audio assembly, or complex multi-step media workflows using the GenMedia MCP servers (Veo, Lyria, Gemini TTS, NanoBanana).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1242,1243,1244,1245,1248],{"name":1213,"slug":1214,"type":16},{"name":1216,"slug":1217,"type":16},{"name":9,"slug":8,"type":16},{"name":1246,"slug":1247,"type":16},"Media","media",{"name":1249,"slug":1250,"type":16},"Video","video","2026-07-12T07:39:09.672849",{"slug":1253,"name":1253,"fn":1254,"description":1255,"org":1256,"tags":1257,"stars":1188,"repoUrl":1189,"updatedAt":1261},"genmedia-video-editor","edit and compose video content","Expert in video composition, editing, and format conversion. Use when the user wants to generate high-quality video, overlay images on video, concatenate clips, create GIFs, or sync audio to video using mcp-avtool-go and mcp-veo-go.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1258,1259,1260],{"name":1216,"slug":1217,"type":16},{"name":9,"slug":8,"type":16},{"name":1249,"slug":1250,"type":16},"2026-07-12T07:39:13.749081",{"slug":1263,"name":1263,"fn":1264,"description":1265,"org":1266,"tags":1267,"stars":1188,"repoUrl":1189,"updatedAt":1279},"genmedia-voice-director","generate expressive text-to-speech with Gemini","Expert in casting, directing, and generating expressive text-to-speech using Gemini TTS. Use this when the user needs virtual voice actor personas, expressive speech generation, or multiple variations of a voiceover (like \"take 3 on the bounce\").",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1268,1269,1270,1273,1276],{"name":1213,"slug":1214,"type":16},{"name":1216,"slug":1217,"type":16},{"name":1271,"slug":1272,"type":16},"Gemini","gemini",{"name":1274,"slug":1275,"type":16},"Speech","speech",{"name":1277,"slug":1278,"type":16},"Text-to-Speech","text-to-speech","2026-07-12T07:39:17.86673",80,{"items":1282,"total":1290},[1283],{"slug":4,"name":4,"fn":5,"description":6,"org":1284,"tags":1285,"stars":26,"repoUrl":27,"updatedAt":28},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1286,1287,1288,1289],{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},{"name":24,"slug":25,"type":16},1]