Reference

Example apps

On this page

This page walks through four of the app definitions that ship with Conclude. The YAML below is rendered directly from the product’s bundled files, so it cannot drift from what you install. Read it with the YAML reference and the attributes reference; the annotations say only what each block does in that app.

Three of the four (support, incident, approval) are in the installable catalog. contact-form is bundled but not listed there; see its section for how to use it.

Support

The smallest useful ticketing app: a subject, a description and a resolution.

name: support
label: Support
icon: support
description: Support ticketing system

settings:
  subject: ticket
  alert: ${__channel} ${initiator}

roles:
  owner: ${__blank}
  members: ${__channel} ${initiator}

attributes:
  - name: title
    type: string
    label: Subject
    placeholder: What is the inquiry about?
    mandatory: true
  - name: body
    type: text
    label: Description
    placeholder: Please provide details here
  - name: conclusion
    type: text
    label: Resolution
    placeholder: What is the resolution?

Download support.yaml · bundled template support

  • settings.subject: ticket names the activity in default UI text, so buttons and messages say “ticket”
  • settings.alert: ${__channel} ${initiator} notifies the install channel and the ticket’s creator on every event. ${__channel} is an install-time macro, replaced with the concrete channel at install
  • roles.owner: ${__blank} opts out of the default owner (the installer), so a new ticket starts unowned. roles.members makes everyone in the install channel plus the creator a participant
  • The three attributes are all reserved names: title is required on every app; body is the long description; conclusion is filled in when the ticket is closed. The app only relabels them (Subject, Description, Resolution) and adds placeholders

Incident

Adds a status list, a severity scale and a field that stays hidden until the incident is closed.

name: incident
label: Incident
description: Incident management
icon: incident

settings:
  subject: incident

roles:
  owner: ${__blank}

attributes:
  - name: title
    type: string
    label: Incident
    placeholder: Please enter a headline for the incident
    mandatory: true
  - name: root_cause
    type: text
    label: Root cause
    placeholder: What was the root cause of the incident?
    postmortem: true
  - name: conclusion
    type: text
    label: Resolution
    placeholder: What was the resolution?
  - name: status
    type: select
    label: Status
    defaultValue: open
    visible: edit,conclude
    options:
      - name: open
        label: Open
      - name: in_progress
        label: In progress
      - name: on_hold
        label: Snoozed
      - name: closed
        label: Resolved
      - name: duplicate
        label: Duplicate
      - name: rejected
        label: Rejected
  - name: severity
    type: select
    label: Severity
    defaultValue: none
    visible: always
    options:
      - name: critical
        label: "🔥 Critical"
      - name: high
        label: ❌️ High
      - name: medium
        label: "❗ Medium"
      - name: low
        label: "⚠️ Low"
      - name: unknown
        label: "🤔 Unknown"
      - name: none
        label: "👌 None"
  - name: body
    type: text
    label: Incident details
    placeholder: More information here
  - name: notes
    type: text
    label: Internal notes
    visible: edit

Download incident.yaml · bundled template incident

  • roles.owner: ${__blank} again starts each incident unowned. No alert is set, so it takes the default: the install channel
  • root_cause has postmortem: true: the field appears only on the conclude form and on closed incidents, which keeps root-cause analysis out of the create and edit forms
  • status is a select on the reserved status attribute with defaultValue: open and visible: edit,conclude, so it is not shown on the create form. All six option names are built-in statuses; the app only relabels them (for example on_hold becomes “Snoozed”, closed becomes “Resolved”). Because the names are built in, no state: binding is needed: closed, duplicate and rejected map to the closed state by default
  • severity is a select with defaultValue: none and visible: always. The option labels carry emoji; the option names are plain identifiers
  • notes has visible: edit, so internal notes can only be added after creation

Approval

Shows a superusers role and an option that closes the request when chosen.

name: approval
label: Approval
icon: approval
description: Request for approval

settings:
  subject: request
  alert: ${__channel} ${initiator}

roles:
  superusers: ${__installer}
  owner: ${__blank}
  members: ${__channel} ${initiator}

attributes:
  - name: title
    type: string
    label: Request
    placeholder: What is your request?
    mandatory: true
  - name: body
    type: text
    label: Description
    placeholder: More details here
  - name: status
    editors: ${superusers}
    type: select
    label: Decision
    hint: Setting this will close the approval
    visible: edit,conclude
    important: true
    options:
      - name: approved
        label: Approved
        state: closed
      - name: rejected
        label: Declined
  - name: conclusion
    type: text
    label: See decision
    visible: never

Download approval.yaml · bundled template approval

  • roles.superusers: ${__installer} gives the elevated role to whoever installs the app. Any other user or channel can be substituted after install
  • status has editors: ${superusers}, so only superusers can set the decision. important: true highlights it in the activity banner and list, and hint: explains the effect on the form
  • The approved option sets state: closed, so selecting it concludes the request. rejected needs no state: because it is a built-in status that already maps to closed (see custom statuses). Either decision closes the approval, as the hint says
  • conclusion is declared with visible: never, which removes the resolution field from every form; the decision itself is the outcome

Contact form

Turns inbound web form posts into activities through a web connector.

name: contact-form
label: Contact form
icon: generic
description: Handle external contact requests

settings:
  subject: request
  alert: ${__channel}
  rateLimit: 6/min

roles:
  owner: ${initiator}
  members: ${__channel}

webConnector:
  id: <auto-generated>
  attribute_map:
    - internal: title
      defaultValue: Message from ${name} ${email}
    - external: message
      internal: body
      defaultValue: <no message>

attributes:
  - name: title
    type: string
    label: Incoming
    mandatory: true
  - name: name
    type: string
    label: Name
  - name: email
    type: string
    label: Email
  - name: body
    type: text
    label: Message
  - name: conclusion
    type: text
    label: Resolution
    placeholder: 'Optional: Internal action to resolve or follow up this request'

texts:
  launchButton: Create Request
  createCaption: Create Request
  editCaption: Update Request
  concludeCaption: Close Request
  createIntro: submitted a form request
  editIntro: updated the form request
  concludeIntro: closed the form request

Download contact-form.yaml · bundled template contact-form

  • settings.rateLimit: 6/min throttles inbound connector traffic; the reference default is 10/min (see settings)
  • roles.owner: ${initiator} makes the creator the owner, and roles.members: ${__channel} adds the install channel as participants
  • webConnector.id: <auto-generated> is a placeholder; it fails validation, so the product replaces it with a generated connector ID when the app is saved. The ID becomes part of the POST /v1/form/<cid> URL (see endpoints)
  • The attribute map is meant to fill body from the form field message, falling back to <no message>, and to build title from a default value only, using the submitted name and email fields as macros. Entries use the keys external, internal, defaultValue and description. When a mapped field is submitted empty or missing, or an entry has no external at all, its defaultValue is used
  • texts overrides the launch button, form captions and chat intros so the UI says “request” rather than a generic subject