skills/airwallex-beneficiary-creation/SKILL.md
Use this skill when onboarding suppliers or vendors in Airwallex — extract bank details from invoices/documents, validate per-country requirements, and create beneficiaries. Not for money transfers.
npx skillsauth add chatandbuild/skills-repo Airwallex Beneficiary CreationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reads supplier invoices or documents, extracts bank details, validates them against country-specific schemas, and creates beneficiaries in Airwallex. This skill creates beneficiaries only — money movement (transfers) is not in scope and is not available through this connector.
This skill uses the Airwallex MCP tools (beneficiary list / schema / create / update / verify). It operates on live production data — there is no sandbox. Treat every write as a real production write.
This skill only covers Payouts-domain operations — listing, creating, updating, and verifying beneficiaries, plus beneficiary-schema lookup. If the task requires anything outside this domain, stop — this is the wrong skill. Redirect the user:
If the user's message mentions transferring, sending, wiring, or paying money (e.g., "set up and transfer", "send $15K to them", "pay this supplier now"):
This gate fires even if the transfer request is mixed with a valid beneficiary-creation request. Acknowledge what you CAN do, clearly state what you CANNOT, then continue with the part you can handle.
required flag is not always accurate — some fields marked optional are actually required by the API. When in doubt, include every field the country's banking rules list as required, even if the schema says optional, and ask the user rather than guessing.nickname — beneficiary calls take no request_id, so never invent one.verify on the candidate bank details before creating. Only create once both pass AND the user confirms.The create/update body takes its fields at the top level, with bank fields nested inside bank_details. Do NOT wrap the payload in a { "beneficiary": {…} } envelope. Verify exact field names against the beneficiary schema (the getSchema action) before sending:
{
"bank_details": {
"account_name": "...",
"account_number": "...",
"account_routing_type1": "sort_code",
"account_routing_value1": "123456",
"bank_country_code": "GB",
"account_currency": "GBP"
},
"entity_type": "COMPANY",
"company_name": "Acme Ltd",
"address": {
"city": "London", "country_code": "GB",
"postcode": "EC1A 1BB", "street_address": "123 Main St"
},
"transfer_methods": ["LOCAL"],
"nickname": "Acme supplier"
}
getSchema action with bank_country_code, account_currency (not currency), transfer_method, and entity_type. When the schema does not surface valid values for routing types, state formats, or fields like bank_account_category, ask the user — do not guess.transfer_method vs transfer_methods. Schema fetch and verify use the singular transfer_method. The create/update body uses the plural array ("transfer_methods": ["LOCAL"]). Mixing the two causes API rejection.transfer_methods is a top-level array. bank_country_code and account_currency live inside bank_details. The schema-fetch call takes singular transfer_method plus bank_country_code and account_currency as top-level parameters — do not confuse the two shapes.account_name inside bank_details is required for most countries even when the schema does not mark it required.swift_code, not routing — do NOT put a BIC in account_routing_type1 (LOCAL routing only). IBAN countries may still require both iban and swift_code on SWIFT.sort_code, aba, bsb, etc.) — use the schema, never hardcode.bank_account_category — required for US/USD/LOCAL (both COMPANY and PERSONAL) and some personal accounts (e.g., BR). Valid values: "Checking" / "Savings" (note the s). The schema may omit this field — always include it for US beneficiaries and ask the user for the value.account_routing_type1, account_routing_value1, and account_number as optional — they are actually required. IBAN alone is NOT enough. Include account_routing_type1 (bank_code), account_routing_value1 (clearing number, 4–5 digits), and account_number. Ask the user for these values.entity_type drives required name fields. COMPANY uses company_name; PERSONAL uses first_name + last_name, plus additional_info for tax IDs (personal_id_type and personal_id_number). The schema does not always surface the conditional additional_info requirement.name (PERSONAL) / company_name (COMPANY) — there is no first_name filter. Use the actual filter names exposed by the listing operation; do not invent filters from JSON body field names.pattern only when constructing the payload. Check the field's pattern regex first, then strip only characters that prevent a match. E.g., GB sort code pattern ^[0-9]{6}$ → strip hyphens from 20-32-06 to get 203206. If the pattern already allows the characters, preserve the original value. Always show the before→after transformation so the user can verify.address.state uses ISO 3166-2 codes with country prefix (e.g., CA-ON, AU-NSW, IN-KA). Do NOT use a bare abbreviation.066, 086) mean wrong length or invalid format — ask the user, never pad or truncate.verify ≠ create — verify only checks the candidate bank details, it does NOT create the beneficiary. There is no separate payload-validation operation on this connector, so your pre-flight is the schema cross-check plus verify; then confirm with the user and create.page_num (0-based) + page_size; increment until there are no more results.Step 1 — Get the document(s). Accept one or more supplier invoices, contracts, vendor lists, or bank-detail documents. Batch supported.
Step 2 — Extract supplier and bank details. Identify: supplier name, entity type, bank name, bank country, currency, account number/IBAN, routing code(s), address (all five components: street_address, city, state, postcode, country_code), contact info. Documents may be in any language — extract bank details regardless of language, keep company/entity names in their original language, and present the extracted summary in English for confirmation.
Step 2b — Verify user-supplied field names against the schema. If the user's request mentions routing types or bank-detail parameters you cannot confirm exist, do NOT echo them back as required fields. Proceed to the schema fetch (Step 5) first, then return with only the fields the schema actually requires — and call out any user-mentioned terms that don't correspond to real API fields.
Step 3 — Clarify intent before proceeding. Present the extracted summary and explicitly ask what the user wants:
Do NOT assume "create new" by default. If the request is ambiguous (e.g., "set up this supplier" could mean create or update), ask. If more than one possible supplier/payee exists in the attachment or context and the user's wording does not unambiguously identify which records to act on, present the candidate list and ask which specific record(s) they mean before any schema check or API call.
Step 4 — Confirm you are working on live production data. Confirm access via a low-cost read (e.g., list beneficiaries).
Step 5 — Fetch the country-specific schema. For EVERY unique country/currency/transfer-method/entity-type combo, run the getSchema action to get the required fields and patterns. When the schema is silent on valid enum values, routing formats, or extra field requirements, ask the user — do not fabricate.
Step 6 — Build a beneficiary table:
| # | Company/Name | Entity Type | Bank Country | Currency | Transfer Method | Key Bank Fields | State | Status | | --- | --- | --- | --- | --- | --- | --- | --- | --- |
Fill State with an ISO 3166-2 code or n/a. Mark incomplete rows with [?].
Step 7 — Check and confirm. Cross-check every row against the schema fetched in Step 5. Do NOT proceed until every row passes and the user confirms.
Step 8 — Completeness check. Before the first write, cross-check each planned payload against its schema: every required field present, every value matching the schema's pattern. List any gaps and resolve them with the user.
Step 9 — Match existing beneficiaries. Search by name/company_name. Paginate fully. If a match exists, the user decides: skip, update, or create new.
Step 10 — Pre-flight with verify (recommended). verify takes a candidate bank_details payload and needs no existing beneficiary record, so it catches country-specific bank-detail errors before you create anything. Process one at a time, sequentially — do NOT parallelize (a parallel failure cancels sibling calls). Show each result. If verify is unsupported for that country/transfer method, say so and rely on the Step 8 schema cross-check.
Step 11 — Confirm before writes. Re-state to the user that these are live production records. Wait for explicit approval before proceeding.
Step 12 — Create. HARD GATE: NEVER attempt create for a row with missing or schema-mismatched fields, or one whose verify came back INVALID. Fix it first (ask the user for corrected data) or skip that row entirely. Retrying create with the same bad payload wastes turns and will fail identically. Process one at a time, sequentially. Create only checked, unmatched rows. Wait for each creation to succeed before starting the next. Report each result immediately.
Step 13 — Summary & next steps. Show the final summary: created / skipped / failed. Then advise:
Bank account ownership verification confirms the account belongs to the named beneficiary. This is the same verify operation as Step 10 — run it as a pre-flight before creating, or here on its own. Not all countries or transfer methods support it.
Step 14 — Check verify eligibility. Confirm the verify action is available. If the verify call rejects with an unsupported-country or unsupported-method error, explain and suggest the Airwallex Dashboard as a fallback.
Step 15 — Submit verification. The verify action takes a candidate bank_details payload — NOT a beneficiary ID — so you can verify before the beneficiary record exists. Body shape: entity_type, transfer_method (singular), bank_details. No request_id. Show the verification status to the user. Possible responses include VERIFIED, INVALID, CANNOT_VERIFY, and EXTERNAL_SERVICE_UNAVAILABLE; if the call is rejected outright, suggest the Airwallex Dashboard.
| Situation | Action |
| --- | --- |
| Required field missing or ambiguous | STOP, list the gaps, ask the user |
| Document unreadable | Ask for the content another way |
| Extraction ambiguous | Mark [?], ask the user, do not guess |
| Bank country unclear | Ask the user — a wrong country cascades to wrong fields |
| Required bank field missing | Show which field is missing for which country schema |
| Schema fetch fails | Try the alternate transfer method (LOCAL → SWIFT) |
| verify returns INVALID, or create is rejected | Show the exact API error, ask the user to correct |
| 066 / 086 account errors | Ask the user to verify account format/length; never pad or truncate |
| Duplicate detected | Show details, let the user choose |
| Partial completion | Report what succeeded (with IDs) and what failed |
| Auth expired | The connector refreshes tokens automatically; if a tool keeps returning an auth error, the grant may have been revoked — ask the user to re-authorize the Airwallex connection |
Phase 1: Extract
get document(s) → extract bank details → clarify intent
→ confirm live data + access → fetch country schema
→ build table → schema cross-check → user confirms
Phase 2: Check & Create
completeness check → match existing → verify bank details (pre-flight)
→ confirm before writes → create → summary & next steps
Phase 3: Verify bank account (standalone / post-create)
check eligibility → submit verification → show status
Adapted from Airwallex's official AgentOS beneficiary-creation skill, licensed under the Apache License 2.0 (see LICENSE.txt). Modified for the ChatChat Airwallex connector: CLI-specific instructions and external URLs removed, supporting reference files inlined, workflow steps aligned to the operations this connector actually exposes, and unsupported operations redirected to the Airwallex Dashboard.
tools
Use only when the user explicitly asks to stage, commit, push, and open a GitHub pull request in one flow using the GitHub CLI (`gh`).
development
Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like "the xlsx in my downloads") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.
development
Use this skill when turning messy workout information into clear logs, comparing user-provided sessions, surfacing trends or likely PRs, and suggesting realistic next-session steps.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.