# Origamy playbook spec v1. Reference: /playbooks/spec-format/
spec_version: 1
id: government.application-status-updates
title: Application status updates
sector: government
source:
  kind: synthesized
  notes: >-
    No local government, agency or licensing office has built this with us yet. Written from the
    lending loan-application follow-up (an application form, a staff form where officers record a
    status, one message per status through a trigger filter, an upload form and a reminder after
    some days) and the base call-task pattern for a supervisor. The wording is plain and
    official: it states the status and points to the official notice, and never gives reasons
    or mentions penalties.
derived_from: lending.loan-application-follow-up
vocabulary:
  person: applicant
  people: applicants
  group: case officers
summary: >-
  Keeps applicants informed from the day they apply to the day they collect. Each application
  gets an acknowledgement with its reference number and how long it usually takes. When your staff
  record a status (documents needed, approved, not approved or ready for collection) the applicant
  gets the right message, and anyone asked for documents gets an upload link and a reminder.
  Applications that wait too long without an update appear on a supervisor's task list every day.
  After a decision, applicants are asked how it went, and supervisors get a monthly summary.
when_to_use:
  - You run a local government office, a licensing or permits desk, an agency or an appointments desk, and applicants keep calling to ask where their application is.
  - Staff already give each application a reference number, on a receipt or in a case register.
  - You want applicants told the same day a status changes, and a supervisor warned when a case has gone quiet.

requires:
  data_in:
    - how: public_form
      what: "The Application form, the Upload Documents form and the Service Feedback form this playbook creates. Put the Application link on your website and in your office, or let staff fill it in with the applicant at the counter."
    - how: staff_form
      what: "A staff-only Status Update form your officers fill in each time a status changes, matched to the applicant by phone number and reference."
    - how: sheet_sync
      what: "Optional: a case register synced as People (phone, reference number, service type, stage, last update date). The daily check for stalled cases works from it. The messages for each status are sent only when staff use the Status Update form."
  channels:
    - channel: sms
      for: Every message to applicants
      needs: An SMS provider, or Origamy managed SMS after business verification (KYC). Use your agency's registered sender name where the country allows it.
    - channel: email
      for: The acknowledgement, if the applicant gave an email address
      needs: A verified sending domain for {{ params.email_from }}.
  events:
    - onboarding.submitted
  traits:
    - reference_number
    - application_stage
    - status_updated_at
    - service_type
    - satisfaction_score
    - stuck_review
    - document_review

parameters:
  - key: org_name
    ask: true
    question: What should messages call your office or agency?
    label: Office name
    type: string
    example: Northwind City Licensing Office
  - key: services
    ask: true
    question: What services can people apply for? (one per line)
    help: The Application form shows these as choices, and the monthly report counts applications for each one.
    label: Services
    type: list
    default: [Business permit, Trade licence, Certificate]
  - key: officers_team
    ask: true
    question: Which team reviews uploaded documents? (your case officers, one person is fine)
    label: Case officers
    type: team_name
    default: Case officers
  - key: supervisor_team
    ask: true
    question: Which team hears about applications that have gone quiet, and gets the monthly report? (a supervisor)
    label: Supervisors
    type: team_name
    default: Supervisors
  - key: expected_days
    ask: true
    question: How many working days does an application usually take?
    label: Usual working days
    type: days
    default: 10
  - key: collection_point
    ask: true
    question: Where do people collect a finished application, and when? (a few words)
    label: Collection point
    type: text
    example: the front desk, Monday to Friday, 8am to 4pm
  - key: info_url
    label: Link to your official page or notice about decisions and next steps (leave empty to skip it)
    type: url
    default: ""
  - key: office_phone
    label: Number applicants can call with questions
    type: string
    default: "{{ workspace.phone }}"
  - key: docs_wait_days
    label: Days to wait for documents before the reminder
    type: days
    default: 5
  - key: sla_days
    label: Days without an update before a supervisor is asked to look
    type: days
    default: 10
  - key: feedback_delay
    label: Feedback request after a decision or collection notice
    type: duration
    default: 2d
  - key: low_score
    label: A feedback score at or below this (out of 5) gives a supervisor a task
    type: number
    default: 2
  - key: call_due_hours
    label: Hours a task has to be handled
    type: hours
    default: 24
  - key: send_time
    label: Daily time for the check on stalled applications
    type: time
    default: "08:00"
  - key: report_cron
    label: Monthly report (first day of the month)
    type: cron
    default: "0 8 1 * *"
  - key: timezone
    label: Time zone for the daily check and the report
    type: timezone
    default: "{{ workspace.timezone }}"
  - key: default_country
    label: Default phone country on the forms
    type: country_code
    default: "{{ workspace.country }}"
  - key: email_from
    label: Sender address
    type: email
    default: "{{ workspace.default_sender }}"
  - key: greeting_fallback
    label: Greeting when a first name is missing
    type: string
    default: applicant

timings:
  - A new application gets an SMS and an email straight away.
  - A status recorded on the Status Update form sends the matching SMS straight away.
  - "Documents needed: the upload link goes straight away, and a reminder {{ params.docs_wait_days }} days later if the applicant hasn't uploaded anything."
  - Documents uploaded through the Upload Documents form get an SMS straight away and a review task for {{ params.officers_team }}, due in {{ params.call_due_hours }} hours.
  - "Every day at {{ params.send_time }} ({{ params.timezone }}), applications with no update for {{ params.sla_days }} days give {{ params.supervisor_team }} a task, due in {{ params.call_due_hours }} hours. A case is flagged at most once a week."
  - "Approved or ready for collection: a feedback request {{ params.feedback_delay }} later. A low score gives {{ params.supervisor_team }} a task."
  - "Monthly report to {{ params.supervisor_team }}: cron {{ params.report_cron }} in {{ params.timezone }}."

customer_must:
  - Add your case officers to the {{ params.officers_team }} team and supervisors to {{ params.supervisor_team }} (Settings → Collaborators → Teams). A task or report sent to an empty team reaches nobody.
  - Issue a reference number for every application from your own register or receipt book. Origamy does not create reference numbers. Applicants type theirs on the forms, and staff type the same one on the Status Update form.
  - Have staff fill in the Status Update form every time a status changes, using the applicant's phone number and reference. It is the only thing that sends the status messages and resets the waiting clock.
  - Limit who can open submitted forms. Uploaded documents may hold ID and other personal data. Give access only to the staff who process applications, and keep them only as long as your records rules allow.
  - Tell applicants on the form and at your counter that documents go only through the upload form, and that you will never ask for a PIN, password, payment or code by SMS or call. No message in this playbook asks for one.
  - Check the wording with your communications office. Messages state the status and point to the official notice. They never give reasons for a decision, mention penalties or carry any political or campaign content.
  - Review and publish the four forms, connect an SMS provider or finish business verification, switch the follow-ups and the report on and test with your own phone and a fake application.

objects:
  - ref: team_officers
    kind: team
    about: Reviews uploaded documents.
    body: { name: "{{ params.officers_team }}" }
  - ref: team_supervisors
    kind: team
    about: Hears about applications that have gone quiet and low feedback, and gets the monthly report.
    body: { name: "{{ params.supervisor_team }}" }

  - ref: form_apply
    kind: form
    about: The application form. A hidden field sets the stage to received.
    body:
      name: Application
      slug: application
      description: "Apply to {{ params.org_name }}. We will never ask for your PIN, password or any payment by message."
      draft_state:
        version: 1
        meta: { layout: classic, submit_label: Submit application, success_message: "Thank you. We have received your application and will message you with updates." }
        pages:
          - id: p1
            title: Your application
            description: Use the same phone number every time you contact us.
            fields:
              - { id: f_first, key: first_name, type: short_text, label: First name, required: true, maps_to: { mode: custom, key: first_name, trait: true } }
              - { id: f_last, key: last_name, type: short_text, label: Surname, required: true, maps_to: { mode: custom, key: last_name, trait: true } }
              - { id: f_phone, key: phone, type: phone, label: Phone number, required: true, maps_to: { mode: mapped, slot: profile.phone }, config: { country_picker: true, default_country: "{{ params.default_country }}", verify: "off" } }
              - { id: f_email, key: email, type: email, label: Email address, required: false, maps_to: { mode: mapped, slot: profile.email } }
              - id: f_service
                key: service_type
                type: single_select
                label: What are you applying for?
                required: true
                maps_to: { mode: custom, key: service_type, trait: true }
                options:
                  $each: params.services
                  $value: { value: "{{ item }}", label: "{{ item }}" }
              - { id: f_ref, key: reference_number, type: short_text, label: Your reference number, help: "Printed on your receipt or application slip. If you don't have one yet, ask the office.", required: true, maps_to: { mode: custom, key: reference_number, trait: true } }
              - { id: f_consent, key: consent_to_process, type: boolean, label: I agree that my details may be used to process this application and to send me updates, required: true, maps_to: { mode: custom, key: consent_to_process } }
              - { id: f_stage, key: stage, type: hidden, label: "", required: false, default: received, maps_to: { mode: custom, key: application_stage, trait: true } }
      verification_settings: { required: false }
  - ref: form_status
    kind: form
    about: Staff-only form where officers record a status. Matched to the applicant by phone.
    body:
      name: Status Update
      slug: status-update
      description: Staff only. One entry each time an application's status changes.
      draft_state:
        version: 1
        meta: { layout: classic, submit_label: Save status, success_message: Saved. The applicant will be told by SMS. }
        pages:
          - id: p1
            title: Status update
            description: Use the phone number and reference from the application.
            fields:
              - { id: f_phone, key: phone, type: phone, label: Applicant's phone number, required: true, maps_to: { mode: mapped, slot: profile.phone }, config: { country_picker: true, default_country: "{{ params.default_country }}", verify: "off" } }
              - { id: f_ref, key: reference_number, type: short_text, label: Reference number, required: true, maps_to: { mode: custom, key: reference_number, trait: true } }
              - id: f_status
                key: application_status
                type: multiple_choice
                label: New status
                required: true
                maps_to: { mode: custom, key: application_status, trait: true }
                options:
                  - { value: documents_needed, label: Documents needed }
                  - { value: approved, label: Approved }
                  - { value: rejected, label: Not approved }
                  - { value: ready_for_collection, label: Ready for collection }
              - { id: f_by, key: updated_by, type: short_text, label: Your name, required: true, maps_to: { mode: custom, key: updated_by } }
              - { id: f_note, key: internal_note, type: long_text, label: Internal note (never sent to the applicant), required: false, maps_to: { mode: custom, key: internal_note } }
      verification_settings: { required: false }
  - ref: form_docs
    kind: form
    about: A short form for applicants to upload documents. A hidden field marks the stage as documents received.
    body:
      name: Upload Documents
      slug: upload-documents
      description: "Send {{ params.org_name }} the documents we asked for. We will never ask for your PIN, password or any payment by message."
      draft_state:
        version: 1
        meta: { layout: classic, submit_label: Send documents, success_message: "Thank you. Our team will review your documents." }
        pages:
          - id: p1
            title: Upload your documents
            description: Use the same phone number and reference number as your application.
            fields:
              - { id: f_phone, key: phone, type: phone, label: Phone number you applied with, required: true, maps_to: { mode: mapped, slot: profile.phone }, config: { country_picker: true, default_country: "{{ params.default_country }}", verify: "off" } }
              - { id: f_ref, key: reference_number, type: short_text, label: Your reference number, required: true, maps_to: { mode: custom, key: reference_number, trait: true } }
              - { id: f_doc1, key: document_one, type: file, label: Document, required: true, maps_to: { mode: custom, key: document_one }, validation: { mime_types: [image/jpeg, image/png, application/pdf], max_size_mb: 10 } }
              - { id: f_doc2, key: document_two, type: file, label: Another document (if asked), required: false, maps_to: { mode: custom, key: document_two }, validation: { mime_types: [image/jpeg, image/png, application/pdf], max_size_mb: 10 } }
              - { id: f_stage, key: stage, type: hidden, label: "", required: false, default: documents_received, maps_to: { mode: custom, key: application_stage, trait: true } }
      verification_settings: { required: false }
  - ref: form_feedback
    kind: form
    about: A two-question service feedback form sent after a decision.
    body:
      name: Service Feedback
      slug: service-feedback
      description: "How was your experience with {{ params.org_name }}?"
      draft_state:
        version: 1
        meta: { layout: classic, submit_label: Send, success_message: "Thank you for telling us." }
        pages:
          - id: p1
            title: How was your experience?
            description: It takes less than a minute.
            fields:
              - { id: f_phone, key: phone, type: phone, label: Phone number you applied with, required: true, maps_to: { mode: mapped, slot: profile.phone }, config: { country_picker: true, default_country: "{{ params.default_country }}", verify: "off" } }
              - { id: f_rating, key: rating, type: rating, label: "How would you rate the service you received?", required: true, maps_to: { mode: custom, key: satisfaction_score, trait: true }, validation: { min: 1, max: 5 } }
              - { id: f_comment, key: comment, type: long_text, label: What could we do better?, required: false, maps_to: { mode: custom, key: comment } }
      verification_settings: { required: false }

  - ref: seg_pending
    kind: segment
    about: Applications received or with documents received, and not yet decided.
    body:
      name: Applications in progress
      description: Stage is received or documents_received.
      segment_type: dynamic
      status: active
      definition:
        operator: or
        conditions:
          - { type: trait, trait_key: application_stage, cond_operator: eq, value: received }
          - { type: trait, trait_key: application_stage, cond_operator: eq, value: documents_received }
  - ref: seg_stuck
    kind: segment
    about: Applications in progress whose last update is older than the service level.
    body:
      name: Applications with no update
      description: "Stage is received or documents_received, and the last update was more than {{ params.sla_days }} days ago."
      segment_type: dynamic
      status: active
      definition:
        operator: and
        conditions:
          - operator: or
            conditions:
              - { type: trait, trait_key: application_stage, cond_operator: eq, value: received }
              - { type: trait, trait_key: application_stage, cond_operator: eq, value: documents_received }
          - { type: trait, trait_key: status_updated_at, cond_operator: older_than, value: "{{ params.sla_days }}d" }
  - ref: seg_docs_needed
    kind: segment
    about: Applicants who were asked for documents and haven't sent them.
    body:
      name: Waiting for documents
      description: Stage is documents_needed.
      segment_type: dynamic
      status: active
      definition:
        operator: and
        conditions:
          - { type: trait, trait_key: application_stage, cond_operator: eq, value: documents_needed }

  - ref: tmpl_ack_sms
    kind: template
    about: SMS that acknowledges an application, with its reference and the usual time.
    body:
      name: Application received (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: thank you, {{ traits.first_name | default: \"{{ params.greeting_fallback }}\" }}. We have received your application, reference {{ properties.reference_number }}. It usually takes {{ params.expected_days }} working days, and we will message you when the status changes. Questions? Call {{ params.office_phone }}. Reply STOP to opt out."
  - ref: tmpl_ack_email
    kind: template
    about: Email that acknowledges an application, with its reference and the usual time.
    body:
      name: Application received (email)
      channel: email
      category: Applications
      style: html
      status: active
      subject: "We have received your application, reference {{ properties.reference_number }}"
      metadata: { email: { from: "{{ params.email_from }}", preview_text: "Here is what happens next." } }
      variables: {}
      body: >-
        <p>Dear {{ traits.first_name | default: "{{ params.greeting_fallback }}" }},</p>
        <p>{{ params.org_name }} has received your application. Your reference number is
        <strong>{{ properties.reference_number }}</strong>. Please keep it, and quote it whenever you contact us.</p>
        <p>Applications usually take {{ params.expected_days }} working days. We will send you a message
        whenever the status changes.</p>
        {% if "{{ params.info_url }}" != "" %}<p>More information: <a href="{{ params.info_url }}">{{ params.info_url }}</a></p>{% endif %}
        <p>If you have a question, call {{ params.office_phone }}.</p>
        <p>Yours sincerely,<br>{{ params.org_name }}</p>
        <p style="font-size:12px;color:#6b6b80"><a href="{{ unsubscribe_url }}">Unsubscribe</a></p>
  - ref: tmpl_docs_sms
    kind: template
    about: SMS with the secure upload link when documents are needed.
    body:
      name: Documents needed (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: update on application {{ properties.reference_number }}. We need some documents to continue. Please upload the documents listed in your notice here: {{ ref.form_docs.url }} Questions? Call {{ params.office_phone }}. We will never ask for a PIN, password or payment by message. Reply STOP to opt out."
  - ref: tmpl_docs_reminder_sms
    kind: template
    about: Reminder SMS when the documents haven't arrived.
    body:
      name: Documents reminder (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: a reminder about application {{ traits.reference_number }}. We are still waiting for your documents. You can upload them here: {{ ref.form_docs.url }} Questions? Call {{ params.office_phone }}. Reply STOP to opt out."
  - ref: tmpl_docs_received_sms
    kind: template
    about: Acknowledgement when documents are uploaded.
    body:
      name: Documents received (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: thank you. We have received the documents for application {{ properties.reference_number }} and our team will review them. Reply STOP to opt out."
  - ref: tmpl_approved_sms
    kind: template
    about: SMS when an application is approved.
    body:
      name: Application approved (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: update on application {{ properties.reference_number }}. Your application has been approved.{% if \"{{ params.info_url }}\" != \"\" %} Next steps: {{ params.info_url }}{% endif %} Questions? Call {{ params.office_phone }}. Reply STOP to opt out."
  - ref: tmpl_ready_sms
    kind: template
    about: SMS when an application is ready for collection.
    body:
      name: Ready for collection (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: update on application {{ properties.reference_number }}. It is ready for collection at {{ params.collection_point }}. Please bring your reference number and a valid ID. Questions? Call {{ params.office_phone }}. Reply STOP to opt out."
  - ref: tmpl_rejected_sms
    kind: template
    about: SMS when an application is not approved. No reasons, a pointer to the official notice.
    body:
      name: Application not approved (SMS)
      channel: sms
      category: Applications
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: update on application {{ properties.reference_number }}. A decision has been made and your application was not approved.{% if \"{{ params.info_url }}\" != \"\" %} Details and what you can do next: {{ params.info_url }}{% endif %} You can also call {{ params.office_phone }} to talk it through. Reply STOP to opt out."
  - ref: tmpl_feedback_sms
    kind: template
    about: SMS that asks for feedback after a decision.
    body:
      name: How was it (SMS)
      channel: sms
      category: Feedback
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: how was your experience with application {{ traits.reference_number }}? Please answer two quick questions: {{ ref.form_feedback.url }} Reply STOP to opt out."

  - ref: q_received_by_service
    kind: saved_question
    about: Applications received for each service (counts only), for the monthly report.
    body:
      name: "Report: applications by service"
      data_plane_id: default
      viz_type: bar
      viz_settings: {}
      visibility: workspace
      query_ast:
        table: events
        filters:
          operator: and
          conditions:
            - { field: event_name, op: eq, value: onboarding.submitted }
            - { field: properties.form_id, op: eq, value: "{{ ref.form_apply.id }}" }
        aggregations: [{ fn: count, alias: applications }]
        breakouts: [{ field: properties.service_type }]
  - ref: q_received_total
    kind: saved_question
    about: How many applications were received, for the monthly report.
    body:
      name: "Report: applications received"
      data_plane_id: default
      viz_type: number
      viz_settings: {}
      visibility: workspace
      query_ast:
        table: events
        filters:
          operator: and
          conditions:
            - { field: event_name, op: eq, value: onboarding.submitted }
            - { field: properties.form_id, op: eq, value: "{{ ref.form_apply.id }}" }
        aggregations: [{ fn: count, alias: applications }]
  - ref: q_status_updates
    kind: saved_question
    about: Status updates recorded by staff, by status (counts only), for the monthly report.
    body:
      name: "Report: status updates by status"
      data_plane_id: default
      viz_type: bar
      viz_settings: {}
      visibility: workspace
      query_ast:
        table: events
        filters:
          operator: and
          conditions:
            - { field: event_name, op: eq, value: onboarding.submitted }
            - { field: properties.form_id, op: eq, value: "{{ ref.form_status.id }}" }
        aggregations: [{ fn: count, alias: updates }]
        breakouts: [{ field: properties.application_status }]

  - ref: report_monthly
    kind: report
    about: Each month, applications received, status updates and applications waiting too long, to the supervisors. Counts only.
    body:
      name: "Monthly: applications"
      description: Applications received, decisions and status updates recorded, and how many applications are in progress or have gone without an update. Counts only, no names or reference numbers.
      schedule_cron: "{{ params.report_cron }}"
      timezone: "{{ params.timezone }}"
      enabled: false
      spec:
        period: previous_month
        compare: previous_period
        week_start: monday
        sections:
          - { id: received, kind: saved_question, title: Applications received, viz: number, params: { question_id: "{{ ref.q_received_total.id }}" } }
          - { id: by_service, kind: saved_question, title: Applications by service, viz: bar, params: { question_id: "{{ ref.q_received_by_service.id }}" } }
          - { id: updates, kind: saved_question, title: Status updates recorded, viz: bar, params: { question_id: "{{ ref.q_status_updates.id }}" } }
          - id: ages
            kind: segment_sizes
            title: In progress, with no update, and waiting for documents
            params: { segment_ids: ["{{ ref.seg_pending.id }}", "{{ ref.seg_stuck.id }}", "{{ ref.seg_docs_needed.id }}"] }
          - { id: tasks, kind: tasks_summary, title: Review and follow-up tasks, params: {} }
      recipients: [{ type: team, id: "{{ ref.team_supervisors.id }}" }]
      channel_policy: { mode: email_only }

  - ref: wf_ack
    kind: workflow
    about: An acknowledgement by SMS and email with the reference and usual time. Starts the waiting clock.
    body:
      name: "Application 1: received"
      description: When the Application form is submitted, the date is saved and the applicant gets an SMS and an email.
      enabled: false
      trigger_type: event
      trigger_config: { event_name: onboarding.submitted, form_id: "{{ ref.form_apply.id }}" }
      steps:
        - { id: s1, type: action, config: { action_type: set_trait, traits: { status_updated_at: "{{ now | date: \"%Y-%m-%d\" }}" } } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_ack_sms.id }}" } } } }
        - { id: s3, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: email, template_id: "{{ ref.tmpl_ack_email.id }}" } } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_docs_needed
    kind: workflow
    about: 'Staff record "documents needed": the applicant gets the upload link, and a reminder if nothing arrives.'
    body:
      name: "Application 2: documents needed"
      description: The applicant gets the upload link; if they haven't uploaded anything some days later, a reminder.
      enabled: false
      trigger_type: event
      trigger_config:
        event_name: onboarding.submitted
        form_id: "{{ ref.form_status.id }}"
        property_filters: [{ property: application_status, cond_operator: eq, value: documents_needed }]
        properties: { $origamy_property_filters: true }
      steps:
        - { id: s1, type: action, config: { action_type: set_trait, traits: { application_stage: documents_needed, status_updated_at: "{{ now | date: \"%Y-%m-%d\" }}" } } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_docs_sms.id }}" } } } }
        - { id: s3, type: delay, config: { duration: "{{ params.docs_wait_days }}d" } }
        - { id: s4, type: filter, config: { condition: { type: trait, trait_key: application_stage, cond_operator: eq, value: documents_needed } } }
        - { id: s5, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_docs_reminder_sms.id }}" } } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_approved
    kind: workflow
    about: 'Staff record "approved": the applicant gets the message, and a feedback request later.'
    body:
      name: "Application 3: approved"
      description: When an application is approved, the stage is saved, the applicant gets an SMS, and some days later a feedback request.
      enabled: false
      trigger_type: event
      trigger_config:
        event_name: onboarding.submitted
        form_id: "{{ ref.form_status.id }}"
        property_filters: [{ property: application_status, cond_operator: eq, value: approved }]
        properties: { $origamy_property_filters: true }
      steps:
        - { id: s1, type: action, config: { action_type: set_trait, traits: { application_stage: approved, status_updated_at: "{{ now | date: \"%Y-%m-%d\" }}" } } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_approved_sms.id }}" } } } }
        - { id: s3, type: delay, config: { duration: "{{ params.feedback_delay }}" } }
        - { id: s4, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_feedback_sms.id }}" } } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_ready
    kind: workflow
    about: 'Staff record "ready for collection": the applicant gets the collection details, and a feedback request later.'
    body:
      name: "Application 4: ready for collection"
      description: When an application is ready for collection, the stage is saved, the applicant gets an SMS with the collection details, and some days later a feedback request.
      enabled: false
      trigger_type: event
      trigger_config:
        event_name: onboarding.submitted
        form_id: "{{ ref.form_status.id }}"
        property_filters: [{ property: application_status, cond_operator: eq, value: ready_for_collection }]
        properties: { $origamy_property_filters: true }
      steps:
        - { id: s1, type: action, config: { action_type: set_trait, traits: { application_stage: ready_for_collection, status_updated_at: "{{ now | date: \"%Y-%m-%d\" }}" } } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_ready_sms.id }}" } } } }
        - { id: s3, type: delay, config: { duration: "{{ params.feedback_delay }}" } }
        - { id: s4, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_feedback_sms.id }}" } } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_rejected
    kind: workflow
    about: 'Staff record "not approved": the applicant gets a plain message that points to the official notice.'
    body:
      name: "Application 5: not approved"
      description: When an application is not approved, the stage is saved and the applicant gets a plain SMS that points to the official notice.
      enabled: false
      trigger_type: event
      trigger_config:
        event_name: onboarding.submitted
        form_id: "{{ ref.form_status.id }}"
        property_filters: [{ property: application_status, cond_operator: eq, value: rejected }]
        properties: { $origamy_property_filters: true }
      steps:
        - { id: s1, type: action, config: { action_type: set_trait, traits: { application_stage: rejected, status_updated_at: "{{ now | date: \"%Y-%m-%d\" }}" } } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_rejected_sms.id }}" } } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_docs_received
    kind: workflow
    about: Uploaded documents get an acknowledgement and a review task for a case officer.
    body:
      name: "Application 6: documents received"
      description: SMS acknowledgement and a review task when the Upload Documents form is submitted. The waiting clock restarts.
      enabled: false
      trigger_type: event
      trigger_config: { event_name: onboarding.submitted, form_id: "{{ ref.form_docs.id }}" }
      steps:
        - { id: s1, type: action, config: { action_type: set_trait, traits: { status_updated_at: "{{ now | date: \"%Y-%m-%d\" }}" } } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_docs_received_sms.id }}" } } } }
        - id: s3
          type: human_task
          config:
            human_task:
              title: "Review documents: {{ traits.reference_number | default: \"reference not given\" }}"
              instructions: |-
                {{ traits.first_name }} {{ traits.last_name }} ({{ traits.phone }}) uploaded documents for application {{ traits.reference_number }}.

                Review them against what was asked. If everything is there, carry on with the application and record the next status on the Status Update form. If something is missing, record Documents needed again. Choose an outcome and add a short note.
              assignee_refs: [{ type: team, id: "{{ ref.team_officers.id }}" }]
              strategy: round_robin
              completion_policy: first_response_wins
              outcome_options:
                - { id: complete, label: Everything is there, intent: positive }
                - { id: still_missing, label: Something is still missing, intent: neutral }
              due_hours: "{{ params.call_due_hours }}"
              wait: true
              wait_timeout_hours: 168
              notify: immediate
        - { id: s4, type: action, config: { action_type: set_trait, traits: { document_review: "{{ properties.task_outcome | default: \"unknown\" }}" } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_stuck
    kind: workflow
    about: 'Daily run over "applications with no update": a task for a supervisor to look at the case.'
    body:
      name: "Application 7: no update"
      description: Every day, applications that have gone without an update for too long give a supervisor a task. The outcome is saved.
      enabled: false
      trigger_type: schedule
      trigger_config: { segment_id: "{{ ref.seg_stuck.id }}", rrule: FREQ=DAILY, starts_at: "{{ workspace.tomorrow }}T{{ params.send_time }}", timezone: "{{ params.timezone }}" }
      steps:
        - id: s1
          type: human_task
          config:
            human_task:
              title: "No update: {{ traits.reference_number | default: \"reference not given\" }}, {{ traits.service_type | default: \"service not given\" }}"
              instructions: |-
                The application for {{ traits.first_name }} {{ traits.last_name }} ({{ traits.phone }}), reference {{ traits.reference_number }}, has had no status update for longer than the target time.

                Find out where it is stuck and get it moving. If the applicant needs to be told something, record a status on the Status Update form. Choose an outcome and add a short note.
              assignee_refs: [{ type: team, id: "{{ ref.team_supervisors.id }}" }]
              strategy: round_robin
              completion_policy: first_response_wins
              outcome_options:
                - { id: in_progress, label: Being processed, intent: positive }
                - { id: decided, label: Decision now recorded, intent: positive }
                - { id: waiting_applicant, label: Waiting for the applicant, intent: neutral }
                - { id: reassigned, label: Passed to another officer, intent: neutral }
              due_hours: "{{ params.call_due_hours }}"
              wait: true
              wait_timeout_hours: 168
              notify: immediate
        - { id: s2, type: action, config: { action_type: set_trait, traits: { stuck_review: "{{ properties.task_outcome | default: \"unknown\" }}" } } }
      re_entry_policy: cooldown
      re_entry_cooldown_hours: 168
      goal: {}
      exit_conditions: []
  - ref: wf_low_score
    kind: workflow
    about: A low feedback score gives a supervisor a task.
    body:
      name: "Application 8: low feedback"
      description: When a feedback score is at or below the line, a task for a supervisor. The outcome is saved.
      enabled: false
      trigger_type: event
      trigger_config:
        event_name: onboarding.submitted
        form_id: "{{ ref.form_feedback.id }}"
        property_filters: [{ property: rating, cond_operator: lte, value: "{{ params.low_score }}" }]
        properties: { $origamy_property_filters: true }
      steps:
        - id: s1
          type: human_task
          config:
            human_task:
              title: "Low feedback: {{ traits.reference_number | default: \"reference not given\" }}"
              instructions: |-
                {{ traits.first_name }} {{ traits.last_name }} ({{ traits.phone }}) rated the service {{ properties.rating }} out of 5.
                What they said: {{ properties.comment | default: "nothing written" }}.

                Read the comment, check the case and, if it helps, call them to put things right. Choose an outcome and add a short note.
              assignee_refs: [{ type: team, id: "{{ ref.team_supervisors.id }}" }]
              strategy: round_robin
              completion_policy: first_response_wins
              outcome_options:
                - { id: resolved, label: Resolved, intent: positive }
                - { id: noted, label: Noted for service improvement, intent: neutral }
                - { id: not_reached, label: Could not reach, intent: negative }
              due_hours: "{{ params.call_due_hours }}"
              wait: true
              wait_timeout_hours: 168
              notify: immediate
        - { id: s2, type: action, config: { action_type: set_trait, traits: { feedback_follow_up: "{{ properties.task_outcome | default: \"unknown\" }}" } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []

eval:
  name: 115_government_application_status_updates
  mode: task
  vertical: ""
  prompt: >-
    We're a licensing office. Make an application form with name, phone, email, service type and
    reference number, and text the applicant an acknowledgement with their reference and that it
    takes about 10 working days. Our staff will record a status on a staff form (documents needed,
    approved, not approved, ready for collection) and the applicant should get the right SMS; for
    documents needed include a link to upload them and remind them after 5 days. Every day, give
    a supervisor a task for any application with no update in 10 days. Two days after approved
    or ready for collection, ask for feedback. Send supervisors a monthly report with counts
    only. Keep the tone plain and official, with no penalties mentioned.
  expect_artifacts: [form, segment, workflow, message_template, team, report]
  forbid_terms: [penalty, prosecution, fined, campaign, vote]
