← 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": "Find, filter and inspect the contractors a company pays through Wingspan, including who still has onboarding paperwork outstanding. Use for \"who do we pay\", \"list our contractors\", \"find [name]\", \"who has not signed up yet\", \"who is missing their W-9\", \"who is blocked by the certificate of insurance\", \"which contractors are blocked from being paid\", \"can we pay [name]\", \"what is [name]'s status\", \"who is on this engagement\".",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 359
    },
    {
      "relative_path": "references/requirement-types.md",
      "size_in_bytes": 5047
    }
  ],
  "name": "finding-contractors",
  "skill_md_contents": "---\nname: finding-contractors\ndescription: Find, filter and inspect the contractors a company pays through Wingspan, including who still has onboarding paperwork outstanding. Use for \"who do we pay\", \"list our contractors\", \"find [name]\", \"who has not signed up yet\", \"who is missing their W-9\", \"who is blocked by the certificate of insurance\", \"which contractors are blocked from being paid\", \"can we pay [name]\", \"what is [name]'s status\", \"who is on this engagement\".\n---\n\n# Finding 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\nis assigned to. A **requirement** is something a contractor must satisfy before\nthey can be paid, such as a tax form or an insurance certificate.\n\nTwo tools cover this: `search_contractors` lists and filters, and\n`get_contractor` reads one contractor in full. Every row a search returns\ncarries a `contractorId`, and that is the id `get_contractor` takes.\n\n## Listing and searching\n\n`search_contractors` with no arguments lists active contractors, newest first,\n25 to a page.\n\n| Argument | What it does |\n| --- | --- |\n| `query` | Free-text search over name, email, company and your own external id. At least two characters. Results come back by relevance. |\n| `status` | Which screen tab to read: `active`, `notSignedUp`, `incomplete`, `complete`, `archived`. |\n| `onboarding` | Where the working relationship stands: `Pending`, `Active`, `Inactive`. |\n| `eligibility` | `blocked` or `clear`, as reported by the search API. Missing eligibility is neither; use the verification workflow below before concluding nobody is blocked. |\n| `engagement` | Only contractors assigned to this engagement, by name or id. |\n| `batch` | Only contractors loaded by one bulk import in the Wingspan app, by that import's batch id. |\n| `requirement` | Only contractors whose copy of this requirement is in `requirementState`. |\n| `requirementState` | Which state that requirement is in. Defaults to `incomplete`. |\n| `sortBy` | `createdAt` or `updatedAt`. One field per call. |\n| `sortDirection` | `asc` or `desc`. Defaults to `desc`. Refused without `sortBy`. |\n| `limit` | Rows per page, 1 to 100. Defaults to 25. |\n| `pageToken` | Continue a previous page. Pass the previous result's `pagination.nextPageArgs` back unchanged. |\n| `accountId` | Read one child account of an organization instead of the signed-in account. Only when the user names one; `who_am_i` lists them. |\n\nUse the current tool schema for supported filters. Do not invent filters or assume this table is exhaustive.\n\n## Two separate questions, two separate arguments\n\n`status` is the tab strip from the Wingspan app, and it mixes the working\nrelationship with paperwork: `incomplete` and `complete` are a summary of\nrequirements, while `notSignedUp` and `archived` are about the relationship.\n\n`onboarding` is the relationship on its own, and every row reports it whatever\nyou filtered on.\n\nThe two combine, so `status: \"notSignedUp\"` with `onboarding: \"Pending\"` means\n\"invited, has not signed up\". One pair is refused rather than answered:\n`onboarding: \"Inactive\"` together with `status: \"active\"`, because `active`\nexcludes archived contractors and `Inactive` requires them. `status` defaults\nto `active`, so leaving it out is the same pair — send `onboarding: \"Inactive\"`\nwith `status: \"archived\"`.\n\nOne more thing worth passing on: `onboarding: \"Inactive\"` matches archived\ncontractors, but a contractor who only rejected their invite is not matched.\nThe underlying search cannot express \"archived or rejected\" in one query, and\nthe result's `note` says so.\n\n**One kind of contractor no filter finds:** someone archived before any\nengagement was assigned to them. Every `status` tab except `active` needs a\npaperwork or engagement summary they never got, and `active` excludes anyone\narchived — so no combination of `status` and `onboarding` returns them. Read one\nwith `get_contractor` if you have their `contractorId`; its headline reads\nArchived. Every row that does come back carries its own `archived` field,\nwhatever you filtered on.\n\n## Who is blocked from being paid\n\nUse `search_contractors` with `eligibility: \"blocked\"` as a candidate search,\nnot proof that every other contractor is eligible. Preserve the user's account\nand roster scope. Do not add an `onboarding: \"Active\"` filter: a contractor\nstill onboarding can have a non-eligible engagement.\n\nIf the blocked search is empty, fails, or conflicts with the user's observation,\nread the roster without the eligibility filter. Also verify individual records\nwhenever roster rows have `paymentEligibility: null`, empty `engagements`, or\nmissing requirement summaries. These values mean unknown in search, not clear.\nSearch has been observed returning no engagements while detail returns actual\nassignments; do not recommend assigning an engagement based only on search.\n\nCall `get_contractor` using each candidate or unknown row's `contractorId`.\nFor a small roster, inspect every returned row when checking a negative result.\nFor larger rosters, respect paging and the user's requested scope; explicitly\nstate how many records were checked and whether further pages or unknowns\nremain. Never turn a partial check or failed detail call into \"nobody is blocked\".\n\nFor payment eligibility, inspect `engagements[].paymentsEligibility` and the\nengagement status. Report `NotEligible` as ineligible for that engagement;\ninclude a `Created` engagement instead of discarding it for not being\n`Activated`. An eligible engagement does not cancel out another non-eligible\nengagement. Distinguish historical inactive assignments from current work.\nReport `Eligible` at the engagement level, not as a guarantee that funds can\nbe delivered. Missing or unrecognized eligibility remains unknown.\n\nExplain outstanding requirements using `requirementDetails`. Match a\nrequirement's `engagementIds` to the assignment's `payeeEngagementId`, not the\ntemplate `engagementId`. Report the returned statuses, such as\n`PendingCompletion`. Separate confirmed engagement ineligibility from the\noutstanding requirements: without placement-specific evidence, do not claim\neach outstanding requirement independently blocks payment.\n\nUse `alert` for the general onboarding headline, but do not let it override\nexplicit engagement eligibility. If it says invited or not signed up while\nthe Sign up requirement is completed, disclose that inconsistency rather\nthan choosing one as a proven explanation. When search and detail disagree,\nreport the detail's explicit engagement verdict and explain that the search\nmissed it. Indexing or mapping issues are hypotheses until independently\nconfirmed.\n\nOnly report no ineligible engagements found after checking the relevant scope;\ninclude any unresolved records and coverage limits. Do not use absence from\nthe blocked search as evidence that everyone can be paid.\n\n## Who still has a named requirement outstanding\n\nTwo calls, in this order.\n\n1. `search_requirements` lists the requirements the company has configured.\n   Each carries a `requirementDefinitionId`, the `blocking` value Wingspan\n   holds for it, its grace period and how often it expires. Pick the one the\n   user named. With no arguments it lists the ones still in use; it also takes\n   `type` (one kind of requirement), `includeInactive` (show retired ones too),\n   `limit`, `pageToken` and `accountId`, and nothing else.\n2. `search_contractors` with `requirement` set to that id; its exact name also\n   works, matched case-insensitively and in full, so a partial name will not\n   resolve. Set `requirementState` to the state you want.\n\n| `requirementState` | Means |\n| --- | --- |\n| `incomplete` | Outstanding — the contractor has not finished it. This is the default. |\n| `pendingReview` | The contractor submitted something and the company has not reviewed it. |\n| `complete` | Satisfied, whether the contractor or the company finished it. |\n| `expiring` | Satisfied, but the expiry date is approaching. |\n| `expired` | It lapsed and has to be renewed. |\n\nA requirement the company rejected, or one whose underlying record was revoked\nor failed, is reopened rather than failed — it reads as outstanding again, with\na reason recorded. There is no failed state. Say \"reopened after review\" rather\nthan \"never started\" when reporting one.\n\n`requirementState` on its own is refused: it needs `requirement`.\n\nTwo things to say out loud when reporting the answer:\n\n- **Not every outstanding requirement blocks a payment.** `blocking` on a\n  definition is what Wingspan reports for that definition. A contractor's own\n  copy can be blocking or not depending on where it was attached.\n  `get_contractor` treats every incomplete requirement as blocking and does\n  not read that setting; which placement merely tracks a requirement is visible\n  only in the Wingspan app.\n- **`gracePeriodDays` is a delay on the definition**, not a verdict about a\n  person: it is the days from when a requirement is attached to a contractor\n  before an outstanding copy starts holding up a payment. Inside that window an\n  unfinished requirement does not block.\n\nWhen interpreting requirement kinds or filtering by `type`, read\n[references/requirement-types.md](references/requirement-types.md).\n\n## When to read one contractor in full\n\nMove to `get_contractor` once the question is about one person: \"can we pay\nthem\", \"what is their status\", \"what is missing\". It returns what the\nContractors detail screen shows. For general onboarding status, lead with\n`alert`. For payment eligibility, use the engagement verification workflow\nabove. The headline can have one of these outcomes:\n\n| `alert` says | Means |\n| --- | --- |\n| Contractor invited | Invited, has not signed up yet. |\n| Tax information not shared | Signed up, but has not shared tax information with the company. |\n| Archived | Someone at the company archived them. |\n| Contractor is all set for now | Ready to be paid. |\n| Payments eligibility pending | Signed up with nothing outstanding, but at least one active assignment is not cleared for payment. |\n| Requirements expired | Something already satisfied has lapsed and needs renewing. |\n| Requirements expiring soon | Something already satisfied is about to lapse. |\n| Requirements incomplete | Something is outstanding. |\n\nOnly one applies, and the order above decides which. A contractor who is both\narchived and missing tax information reads \"Tax information not shared\",\nbecause that check comes first. This headline is not a substitute for the\nexplicit `paymentsEligibility` on each engagement.\n\n\"Tax information not shared\" does not always mean the contractor must act — a\npayer can supply and verify the details itself, in the Wingspan app.\n\n`alert` can also be empty, when none of the checks above fire. Report that as\n\"nothing flagged\" and fall back to the assignments and requirement list in the\nsame result rather than declaring the contractor payable.\n\n`get_contractor` also returns their tax information and its verification\nstatus, every engagement assignment with a count of outstanding requirements,\nthe full requirement list with expiry dates, whether they have a payout method\nset up (somewhere for the money to land), and your own id for them.\n\n## Two results to read carefully\n\n**Missing search summaries do not prove there are no assignments.**\nWhen search reports no engagements or paperwork summary, verify with\n`get_contractor` before explaining the cause or recommending changes. A genuine\nabsence of assignments is different from missing indexed data.\n\n**An assignment with no requirements shows \"None required\".** It also shows\nwhatever eligibility Wingspan reports. Do not infer from it. If such a\ncontractor cannot be paid, the fix is to attach one requirement in the Wingspan\napp and have it completed; nothing else re-evaluates eligibility.\n\n## A search that finds nobody\n\nIf a name search returns no rows and archived contractors were excluded, the\nresult reports how many archived contractors do match. Offer to look there\nbefore telling the user the person does not exist.\n\n## Finish these in the Wingspan app\n\n- Creating or editing engagements, groups, worksites, custom fields and rate\n  cards.\n- Writing a requirement definition, and attaching one to an engagement or a\n  group.\n- Approving, rejecting, resetting or renewing one contractor's requirement, and\n  extending an expiry date.\n- Archiving or restoring a contractor.\n- Everything the contractor does themselves: signing up, signing, uploading a\n  document, verifying identity, adding a payout 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: 74a29db147005e736ecde88175692233bde45e18d74f02f531d8cdeb3d28ab8d