Skip to main content
How it works

Variables

Put a ticket's, person's, device's or your own fields' values into replies, macros, auto-responses, task templates and workflows with {{variables}}. Every variable, fallbacks, previews and what requesters never see.

A variable is a value written once and filled in for each record: Hi {{requester.first_name}}, ticket #{{ticket.number}} is with {{assignee.name}}. reads "Hi Ana, ticket #1042 is with Sam Lee." on one ticket and something else on the next. The same variables work everywhere you write text in schoolOS, including the fields your account added.

Screenshot coming soon
The variable picker in a ticket's reply box, searching for the requester's variables

Where you can use them#

| Where | Filled in | From | | --- | --- | --- | | A ticket's reply box (Work a ticket) | When you send it | The ticket, its requester, assignee, device and location, and you | | Macros | When an agent picks the macro, and anything left when they send | The ticket it's used on | | Auto-responses | When the email goes out | The new ticket | | Task templates | When the template is applied to a ticket | The ticket | | schoolAgent routes: an email route's subject and message | When a chat is sent down the route | The conversation, the person and what they answered | | Workflow steps with text: Notify in app, Notify a person or team (subject and message), Add an internal note, Create a task (its name) and Update a field (a text value) | When the step runs | The record the workflow runs on |

Who can use them#

Variables are for helpdesk agents and the admins who manage each place. Everyone else, including staff who aren't agents, students, guardians and anyone writing in the portal, the widget or a chat, doesn't see the picker, Insert variable or Preview, and {{ in what they write is never filled in: it's sent exactly as typed.

| Where | Who | | --- | --- | | A ticket's reply box | Helpdesk agents (Work as helpdesk staff, tickets.staff) | | Macros, auto-responses, task templates | Manage helpdesk settings (tickets_admin.manage) | | Workflows | Manage workflows (workflows.manage) | | schoolAgent routes | Manage the agent (intelligence.view) |

Set these in Admin › People › Roles.

Add a variable#

  • Type {{. A list opens under the cursor, grouped by where the value comes from: Ticket, Requester, Assignee, Asset and so on. Keep typing to search by name ("first name", "serial"), then press Enter or Tab, or select one. Escape closes the list.
  • Insert variable. The button beside the text (the { } icon in the reply box) opens the same list with a search box.

Every place above has the same picker, the same warnings and Preview.

A variable is its name in double braces, like {{ticket.subject}}. You can type one by hand too. Upper or lower case and spaces inside the braces don't matter for the older variables below; today's are lower case.

Values are formatted for reading: dates as "September 28, 2026", times in your account's time zone ("September 28, 2026 at 10:30 PM"), yes/no fields as Yes or No, a multi-select's choices joined with commas, and prices as dollars ("$1,234.50").

Fallbacks#

A variable with no value is left blank. Give it a fallback after a | to say something else instead:

  • Hi {{requester.first_name | "there"}}, reads "Hi Ana," or, for someone with no first name on file, "Hi there,".
  • Assigned to {{assignee.name | "our team"}} reads "Assigned to our team" on an unassigned ticket.

Quotes are optional: {{requester.first_name | there}} works too.

Your own fields#

The fields your account added are variables too, as soon as they exist: ticket fields, asset fields, people fields and location fields. They're listed under their record in the picker by the name you gave them, like Asset › Bus route.

  • Asset, people and location fields are named by the field's key: {{asset.custom.bus_route}}, {{requester.custom.employee_id}}, {{location.custom.principal}}.
  • Ticket fields have no key, so they're named by the field's id: {{ticket.custom.8f0c6f8e-…}}. Pick them from the list rather than typing them.

Because a variable names the field, not its label, renaming a field doesn't break anything already written. Deleting or archiving a field does: its variable is left blank from then on (or shows its fallback), and the editor warns that it isn't a variable anymore.

A person's own fields are there for the requester, an asset's owner and the assignee. The assignee's are staff-only (see below).

What requesters never see#

Replies, public macros and auto-responses are read by the requester, so the picker leaves out anything internal:

  • Ticket › Latest internal note, Ticket › SLA breached, Ticket › Ticket ID and Ticket › Link for staff. Use Ticket › Link for the requester in a reply: it opens the ticket in their My tickets. In a workflow email to The Requester, it's their own View your request link, which needs no password (secure tracking links).
  • Asset › Purchase price, Asset › Link for staff and Asset › Asset ID.
  • The assignee's own fields.

If one of these is typed into a reply anyway, it's filled in blank (or with its fallback), never with the value, and the editor says so before you send. Internal notes, internal macros, task templates and workflows can use everything.

Preview with a real record#

Under the text, Preview with… fills it in for a real record, without saving or sending anything. Enter a ticket number (or a task number like TSK-0012, an asset tag, or a part number or name for workflows on those), then select Preview. The preview shows exactly what that record's requester or recipient would read. In the reply box, Preview uses the ticket you're on.

You can only preview records you can open yourself. A ticket you can't see answers like one that doesn't exist.

The auto-response also shows a preview with a sample ticket as you type, using your account's name and the department's.

Every variable#

Ticket. ticket.number, ticket.subject, ticket.description, ticket.status, ticket.priority, ticket.kind (its type, like Issue; ticket.type still works and shows the same), ticket.topic, ticket.department, ticket.team, ticket.source, ticket.due_date, ticket.first_response_due, ticket.resolution_due, ticket.created_at, ticket.updated_at, ticket.closed_at, ticket.portal_url (link for the requester). Staff only: ticket.sla_breached, ticket.url (link for staff), ticket.id, ticket.latest_internal_note. Plus ticket.custom.<field id>.

Requester. requester.name, requester.first_name, requester.last_name, requester.email, requester.location (their school or building), requester.role (like Teacher). Plus requester.custom.<key>.

Assignee. The same as the requester, plus assignee.team. On a task, the task's assignee.

Asset. On a ticket, the device linked to it. asset.name, asset.tag, asset.serial, asset.model, asset.manufacturer, asset.type, asset.status, asset.location, asset.owner (who it's assigned to), asset.purchase_date, asset.warranty_expiration. Staff only: asset.purchase_price, asset.url, asset.id. Plus asset.custom.<key>.

Owner. In asset workflows, the person the asset is assigned to: the same variables as the requester.

Task. In task workflows. task.number (like TSK-0012), task.name, task.status, task.type, task.team, task.due_date, task.completed_at, task.created_at, task.url, task.id. A task created from a ticket also has that ticket's Ticket and Requester variables.

Part. In part workflows. part.name, part.number, part.category, part.manufacturer, part.status, part.unit_cost, part.purchase_date, part.warranty_expiration, part.url, part.id.

Location. The record's own school or building: location.name, plus location.custom.<key>.

Account. account.name, account.logo_url, account.support_email (the address people email for help), account.portal_url (schoolAgent, where people ask for help and see their tickets), account.timezone.

Date and time. In your account's time zone: now.date, now.time, now.datetime.

You. In the reply box, macros and task templates, whoever is sending: actor.name, actor.first_name, actor.last_name, actor.email, actor.location.

Workflow. In workflows: workflow.name.

Routes#

A schoolAgent route's email has no ticket yet, so it has its own variables:

  • Requester. The person chatting: requester.name, requester.first_name, requester.last_name, requester.email.
  • Conversation. conversation.subject (a one-line summary), conversation.summary, conversation.question (the last thing they asked), conversation.transcript, conversation.url (the conversation in schoolOS, when there's a link) and conversation.agent_name.
  • Answers. What they gave when the chat asked for their details: answers.name, answers.email, answers.phone. Each of the route's Must know before sending questions is answers.<key>, like answers.bus_number, blank if they didn't know. answers.all lists every answer, one per line.
  • Account and Date and time, as everywhere.

Preview on a route fills them in with a sample conversation.

Which of these each place offers depends on its record: an asset workflow has Asset, Owner, Location, Account, Date and time and Workflow, but no ticket. The picker only lists what's there.

Older variables#

Text written before variables worked everywhere keeps working. These still fill in:

| Written as | Fills in as | | --- | --- | | {{requester_name}}, {{ticket_number}}, {{ticket_subject}}, {{agent_name}} (macros) | {{requester.name}}, {{ticket.number}}, {{ticket.subject}}, {{assignee.name}} | | {{District_Name}}, {{Department_Name}}, {{Ticket_ID}}, {{Requester_First_Name}}, {{Ticket_Subject}} (auto-responses, any case) | {{account.name}}, {{ticket.department}}, {{ticket.number}}, {{requester.first_name}}, {{ticket.subject}} | | {{subject_summary}}, {{conversation_summary}}, {{conversation_transcript}}, {{conversation_url}}, {{user_name}}, {{user_email}}, {{user_phone}} (routes) | {{conversation.subject}}, {{conversation.summary}}, {{conversation.transcript}}, {{conversation.url}}, {{requester.name}}, {{requester.email}}, {{answers.phone}} | | {{ticket.requester.name}}, {{ticket.assignee.email}}, {{ticket.team.name}}, {{ticket.location.name}}, {{asset.asset_tag}}, {{asset.serial_number}}, {{asset.assignee.name}}, {{part.part_number}} (workflows) | {{requester.name}}, {{assignee.email}}, {{ticket.team}}, {{location.name}}, {{asset.tag}}, {{asset.serial}}, {{owner.name}}, {{part.number}} |

A workflow step written with a bare column name, like {{subject}}, also still fills in from the record.

Which should I choose?#

| Choice | Choose it when | | --- | --- | | A variable with a fallback | The value might be missing and a blank would read oddly: a greeting, "assigned to …". | | A variable without one | A blank is fine, or the sentence reads well either way: a device's serial number in an internal note. | | Link for the requester (ticket.portal_url) | Anything the requester reads: replies, public macros, auto-responses. | | Link for staff (ticket.url) | Internal notes, workflow messages to your team. Requesters can't open it. | | One of your own fields | A value only your district tracks, like a bus route or an employee ID. Name it from the picker so a later rename can't break it. |

For example, a district's IT team words its password-reset macro as Hi {{requester.first_name | "there"}}, I've reset the password for {{requester.email}}. Sign in at {{account.portal_url}} and reply here if it doesn't work. – {{actor.first_name}}. Every agent who uses it sends a personal reply signed with their own name.

A facilities team's workflow on new HVAC work orders notifies the on-call tech in the app: {{ticket.priority}}: {{ticket.subject}} at {{location.name}} ({{location.custom.principal}}'s building). Due {{ticket.due_date}}.

Was this article helpful?

Updated October 29, 2026