Appearance
Driver onboarding
Onboarding a driver on their phone, decided by rules, an AI model and the onboarding team together: the flow takes the city, age, years licensed, the driver's own description of their insurance and photos of the license and insurance card, four rules decide, a model reads the insurance description before a driver is activated, and drivers who need a look go to the onboarding team. Every rule result, model answer and decision is on the run's record. Pack: examples/policies/driver-onboarding/.
A pattern for expressing a gig & on-demand work policy, not compliance guidance: the thresholds, lists, fields and questions are placeholders chosen to make the example run; a real policy comes from the business's own rules. Its model step calls one install, chatgpt (The chatgpt install).
The decision it automates
Whether to activate the driver, refer them to the onboarding team, or reject the application, when it is submitted. The rules decide; the model can only send a driver to the onboarding team, never activate or reject one.
Data expected
- The driver as a subject (kind
user) withidentityMatch, your identity check's result (for example an identity vendor's selfie and document check), written before the run starts. - The flow's answers under
submission:fullName,city,age,yearsLicensed,insuranceCoverage(the insurer and the coverage for driving for pay, in the driver's words; at most 2,000 characters) and optional photos of the license and the insurance card. - An install named
chatgptof the platform'schatgptapp, with your OpenAI API key.
Steps and rules
| Step | Type | Why |
|---|---|---|
collect | wait_for_collection | The driver-application flow; the photo fields take the phone's camera. |
rules | evaluate_rules | The driver-onboarding rule set under max_severity. |
route | branch | rules.outcome == reject goes straight to the decision, without the model; any other application to read. |
read | call_app | decide through chatgpt on insuranceCoverage: one question, answered under ai. |
gate | branch | rules.outcome == manual_review opens a case; ai.answers.covered.probability >= 0.8 activates a driver the rules approve; the rest open a case. |
review | create_case | driver_onboarding, 8-hour SLA. |
decide | emit_decision | From the rules, or the onboarding team's decision. |
The rule set driver-onboarding (useCase: onboarding) uses max_severity: a failed block rule rejects, a failed warn rule sends the run to review, and the weights add up to the score.
| Rule | Type | Severity, weight | Fails when |
|---|---|---|---|
gig_city_supported | comparison | block, 100 | city is not New York, Chicago or Los Angeles |
gig_minimum_age | comparison | block, 100 | age is under 21 |
gig_identity_match | comparison | block, 100 | subject.identityMatch is not true |
gig_license_experience | comparison | warn, 30 | yearsLicensed is under 2 |
The model step
read gives the model the driver's description of their insurance, insuranceCoverage, in a text the step writes (its stateTemplate), and nothing else, and asks one question:
| Question | Answer | Asks | Read by |
|---|---|---|---|
covered | yes or no, threshold 0.8 | Does the description say the insurance covers driving for pay, deliveries or passengers, such as a rideshare or delivery endorsement or commercial auto coverage? | gate: a driver the rules approve is activated only on a yes at 0.8 or more |
A probability under 0.8, a model that cannot tell included, sends the driver to the onboarding team, who check the insurance card: the model reads what the driver wrote, never the card (no document or image reaches a model), and does not say whether the coverage is valid (Routing on an answer). The question's threshold is the branch's, so ai.answers.covered.value says which way a clean application went. The answer is short and the case shows it, so the pack asks for no brief.
What the vendor sees
The driver's description of their insurance and the step's own text, through the install's connection: not the name, the identity result or the photos (Data protection). With the one-click install's configuration, the step reaches OpenAI's Responses API, with storing off. The driver writes the description: at worst, an answer the model was talked into activates a driver every rule passed, as the rules alone would (Prompt injection).
The chatgpt install
A pack never carries an install: its step calls one by name, so the pack declares it, "installs": { "chatgpt": "chatgpt" }, the platform's ChatGPT (OpenAI API). The import reports chatgpt missing (--publish publishes all the same), and the admin console's import result installs it in one click, with a preset configuration and a sample key in place of yours. Store your OpenAI API key on the install's page (Connect › Apps, the install chatgpt, Configuration › Keys, openaiApiKey) before the workflow runs.
Until you do, the run fails: OpenAI refuses the sample key, so every application the rules do not reject fails at read, with no case and no decision. A model call that fails once the key is in does the same: an outage that outlasts the retries, an exhausted quota or a refusal fails the run at read. The vendor's answer is on the call's invocation record, under the run's app calls; once the call can succeed, replay the run from read (Operate › Runs, Replay from step), and the driver is not asked again. Without any install named chatgpt, the run fails at read with unknown_install. To ask Claude or Gemini instead, install that app under a name of your own and name it in the step's app and in the pack's installs: every model app answers decide in the same shape (Installing a model app).
What a reviewer sees
A driver_onboarding case with the answers, the photos, each rule's result, the model's call under Vendor checks and its answer (ai) in the run context.
How to adapt it
Write the question for the coverage your markets require, and move the 0.8 in gate together with the question's threshold. Call your identity vendor in the workflow instead of trusting the subject's flag, through an http-api install: a request step when it answers at once (Adding a vendor step), or, when it takes the documents and answers later, a start step that sends them while the install's documents are on and waits for its webhook (Documents). Add your background-check provider the same way, a start step the provider's webhook completes, and have your scheduler start the workflow again before a license or an insurance policy expires.
Run it
bash
pnpm policy:import examples/policies/driver-onboarding --publishThe check runs two fixtures against the model stub (scripts/ai-stub.mjs), whose answers a cue word in the insurance description picks. expect.json is a 27-year-old in New York, licensed for one year, with a rideshare and delivery endorsement on their auto policy: the experience rule fails, so the driver goes to the onboarding team whatever the model says. Cued high, the stub answers covered yes at 0.95; a driver_onboarding case opens, the check approves it and the run completes with a manual approve. expect-activated.json is a 34-year-old in Chicago, licensed for 12 years, with commercial auto coverage for deliveries and passengers: every rule passes, the stub answers covered yes at 0.95, and the run completes with an automated approve, no case opened.