← WingspanCONTENT HISTORY

Update to Wingspan

Snapshot Sep 30, 2026 · 23:10 UTC · version 1.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Add contractors to Wingspan, assign them to an existing engagement and send their invites. Use for \"add these contractors\", \"onboard these people\", \"invite [name] to Wingspan\", \"create contractor records\", \"set up these five contractors\", \"invite this roster\", \"add them to the [engagement] engagement\". Writes to the company's Wingspan account, so it always previews first.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 367
    }
  ],
  "name": "onboarding-contractors",
  "skill_md_contents": "---\nname: onboarding-contractors\ndescription: Add contractors to Wingspan, assign them to an existing engagement and send their invites. Use for \"add these contractors\", \"onboard these people\", \"invite [name] to Wingspan\", \"create contractor records\", \"set up these five contractors\", \"invite this roster\", \"add them to the [engagement] engagement\". Writes to the company's Wingspan account, so it always previews first.\n---\n\n# Onboarding contractors\n\nThe shared rules for every call — ids, paging, previewing a write, what the\ntools cannot do — are in the `using-wingspan-tools` skill. Apply them here.\n\nA **contractor** is a person or business the company pays; Wingspan also calls\nthis a *payee*. An **engagement** is a named working arrangement a contractor is\nassigned to. An **invite** is the email that lets the contractor claim their own\nWingspan account.\n\n`create_contractors` does three things in one call: it creates each contractor\nrecord, assigns each one to an existing engagement, and emails the invite to\neveryone who has not come on board yet. **It writes to the company's account.**\n\n## Always preview first\n\n1. Call `create_contractors` with the rows and no `mode`. It defaults to\n   `mode: \"preview\"`, which writes nothing: it looks up the engagement, checks\n   every email address, and reports exactly what applying would do — including\n   which rows already exist.\n2. Show that preview to the user in full: how many would be created, how many\n   would be skipped, which rows have problems, which engagement each one would\n   be assigned to, and how many invite emails would be sent and to how many\n   people.\n3. Wait for the user to say yes. Do not treat an earlier \"add these people\" as\n   consent to write; the preview is the thing being consented to.\n4. Call again with `mode: \"apply\"`, a `requestId` you have not used before,\n   the matching preview's `confirmationToken` unchanged,\n   and the **same rows and the same `ref` values** you previewed.\n\n## Arguments\n\n| Argument | What it does |\n| --- | --- |\n| `contractors` | The rows. At least one, at most 50 per call. |\n| `engagement` | An existing engagement, by name or id, to assign every row to. A row's own `engagements` overrides it. |\n| `sendInvites` | Email the invite to everyone not yet on board. Defaults to true. |\n| `mode` | `preview` (the default, writes nothing) or `apply`. |\n| `confirmationToken` | Required with `apply`; copy it verbatim from the matching preview. If it expires or arguments change, preview again. |\n| `requestId` | Required with `apply`. An id of your own, up to 64 printable characters with no spaces. |\n| `accountId` | Write into one child account of an organization instead of the signed-in account. Only when the user names one; `who_am_i` lists them. |\n\nEach row in `contractors`:\n\n| Field | What it does |\n| --- | --- |\n| `email` | **Required.** The invite goes here, and it identifies the contractor. |\n| `ref` | Your label for this row, echoed in the result. Up to 48 printable characters, no spaces and no colon. Defaults to `row-1`, `row-2` and so on. |\n| `name` | Full name. Split into first and last name at the first space, exactly as the Wingspan app does. |\n| `company` | Business name, if they invoice as a company. |\n| `externalId` | Your own id for this contractor, for reconciliation. |\n| `phone` | Contact phone number. |\n| `engagements` | Engagements for this row specifically, by name or id. Overrides the top-level `engagement`. |\n\nThere are no other fields. Do not invent one — custom fields and group\nmembership are app work.\n\n## What `requestId` and `ref` are for\n\nEvery write carries a key built from your `requestId` and the row's `ref`. If an\napply half-succeeds and you call again with the *same* `requestId` and the same\nrefs, you get back the result of the original writes; nothing new is created.\nThat is the only safe way to retry. Change the `requestId` only when\nstarting a genuinely new attempt, and never renumber refs between the preview\nand the apply — refs, not row order, are what the keys are built from.\n\nResults come back by `ref`. Email addresses and names are deliberately absent\nfrom the result, including from error messages, so keep your own mapping from\nref to person if the user needs one.\n\n## What each row can come back as\n\n- **created** — the contractor record was created, and the invite was sent\n  unless `sendInvites` was false.\n- **skipped** — the contractor already existed. Nothing was duplicated. If\n  they existed but had never come on board, the invite still went out to them:\n  that is what makes a retry of a half-finished batch safe.\n- **failed** — that row alone failed, with a reason and often the field at\n  fault. One bad row never stops the others.\n\nA row can also report engagement problems separately from the contractor\nitself: the record was created but an assignment did not stick.\n\n## The invite, and what happens next\n\nThe invite creates a pending claim record and emails a one-time link to the\naddress on the row. Wingspan decides which person that address belongs to; a\ncaller never supplies one.\n\nFrom there:\n\n- **Pending** — waiting for the recipient.\n- **Linked** — they accepted, and the contractor record is now bound to the\n  Wingspan account they chose. This is permanent.\n- **Rejected** — they declined. Inviting them again creates a fresh, separate\n  claim, and that is done in the Wingspan app.\n\n`search_contractors` reports this as `onboarding`, with `Pending`, `Active` and\n`Inactive`. The `finding-contractors` skill covers reading it.\n\n## Engagements\n\nAssign contractors to an **existing** engagement. This tool never creates one:\nif the user names an engagement the company does not have, the preview says so,\nand creating it is app work.\n\nA contractor created with no engagement is a real record, but it cannot be paid\nuntil an engagement is assigned. Say that when a user asks for bare records.\n\n## Batches\n\nFifty rows is the hard limit for one call; over that, the tool refuses and\nnames the limit rather than quietly dropping rows. Batches of roughly 25 are\neasier for a person to read in a preview. Each batch is its own attempt and\nneeds its own `requestId`.\n\nThis is a synchronous call, not a bulk importer. A roster of several hundred\npeople belongs in the Wingspan app's import screen.\n\n## Finish these in the Wingspan app\n\n- Creating or editing engagements, worksites, groups, custom fields and rate\n  cards.\n- Setting a contractor's custom-field values, adding them to a group, or\n  setting their rate.\n- Re-sending, retargeting or cancelling an invite, and inviting again after a\n  rejection.\n- Attaching requirements, and approving or rejecting what a contractor\n  submits.\n- Everything the contractor does themselves: accepting the invite, signing up,\n  signing documents, uploading certificates, verifying identity, adding a payout\n  method.\n- Sharing tax information, which is usually the contractor's step; a company\n  that records and verifies a contractor's taxpayer details itself also does\n  that in the app.\n"
}

SHA-256 of public snapshot: 2551d54ccb5a7840ef7e2b14e1bb508c229ae613838a00146fdfd2607d500d1e