Actions
The ten automation actions — post a message, schedule a closure, link or unlink packages, assign, set a priority, notify Discord, call a webhook, ask the AI, ask for the package — and exactly when each one declines to run.
Actions are what a workflow actually does. They execute along the paths the conditions chose, in the order they are connected.
The ten actions
| Action | What it does | Plan |
|---|---|---|
| Post message | Posts a message in the ticket, optionally with choices the customer answers | All |
| Schedule closure | Closes the ticket automatically in 1 to 30 days | All |
| Set package | Links Tebex packages to the ticket | All |
| Unlink package | Removes package links from the ticket | All |
| Assign to a user | Assigns the ticket to a team member | Team |
| Set priority | Sets the ticket's priority | All |
| Discord notification | Sends an embed to a channel, or a DM to the people involved | All |
| Call a webhook | Sends a JSON POST to an endpoint you configure | All |
| Ask AI | Has the assistant answer the ticket right away | All |
| Ask for the package | Asks the customer which package the ticket is about | All |
Post message
Posts a plain-text message (up to 2,000 characters) in the ticket conversation. Choose how it appears:
| Presentation | Where it shows | Seen by |
|---|---|---|
| System (the default) | A centered event line | The customer and your team |
| Chat | A message from the team side | The customer and your team |
| Internal | A staff-only note | Your team |
For chat and internal messages, choose who the message is posted as: a custom author name and avatar (falling back to the workflow's name), or the person behind the action, the team member who triggered the workflow (who typed the command, who replied…), with their own name and avatar. Since the text is yours, not theirs, your team sees the workflow's name next to the member's (via Refund follow-up); customers don't. When nobody from your team triggered it (the AI, a customer, another workflow), the message is posted under the workflow's name, and the run history says so. Either way it still counts as a message posted by a workflow, so a condition on Team member never matches it. The message body and the custom name support {path} placeholders.
A chat message notifies like a reply from your team: the customer and the ticket's participants get the usual Discord DM, and team members who chose to be notified of replies from other staff members get theirs. A system line or an internal note sends no DM.
Prompts with choices
A chat message can also carry choices the customer answers, presented either as a row of buttons (up to 5) or as a dropdown (up to 10, with a placeholder you can customize). The presentation changes nothing else: each choice becomes an output on the right of the node either way, so you can connect different actions to each one.
When the message is posted the workflow pauses at that node. When the customer answers, the workflow resumes along that choice's output and runs the connected actions, which can read {choice.label}.
- A prompt can only be answered once — the first answer wins, and the prompt then stays in the conversation showing what was chosen.
- Only the customer can answer: your team sees the prompt read-only.
- A prompt on a closed ticket takes no answer.
- Each answer counts as one workflow run against your monthly quota, whatever the number of choices offered.
Translate for the customer
Team plan. Available on chat messages only — the ones actually addressed to the customer. It posts the message in the language they used to open the ticket, read from their first message. The choices and the dropdown placeholder are translated too; the author name is not, since it is a name. Internal notes are excluded because only your team reads them, and system lines because they are not a reply.
The language is resolved once per ticket and reused afterwards. If the first message says nothing about it — too short to tell, or no customer message yet — their portal language is used instead. With neither, the message is posted exactly as you wrote it, and so it is when your text is already in that language.
Nothing here can stop a workflow: if the translation cannot be produced for any reason, the original goes out and the run succeeds. Should a project move down to a plan that no longer includes translation, the workflows keep posting, in the language they were written in.
Schedule closure
Schedules the ticket to close automatically in 1 to 30 days. Reopening the ticket before the scheduled date cancels the closure.
Skipped when the ticket is already closed, or already has a scheduled closure.
Set package
Links one or more Tebex packages, chosen from the project's catalog, to the ticket — recorded with the standard packages updated system message. Two modes:
- Add to the linked packages (the default): whatever the customer already picked stays.
- Replace the linked packages: the ticket ends up linked to your selection alone.
Each newly linked package fires the Package selected trigger, just as a manual change does, so workflows reacting to it (an assignment, for instance) run too.
Skipped when every selected package is already linked.
Unlink package
Removes package links from the ticket. Leave its picker empty (the default) to remove them all, or name the ones to remove and the rest stay.
Unlike a manual unlink, it posts no system message: the customer never asked for it, so the conversation stays clean. It also cancels an automatic AI reply already counting down on the ticket, so the assistant never answers about the packages that were just removed.
Skipped when none of the targeted packages is linked.
Assign to a user
Team plan. Assigns the ticket, with a choice of who it goes to and a choice of assignment mode.
Assign to:
- A team member (the default): a fixed member, chosen from the project's members when the workflow is built.
- Whoever triggered this: the person who performed the action that fired the run — for example, whoever just replied on a New message trigger. Nobody is picked at build time; the executor resolves it from the event itself.
Assignment mode:
- Replace assignees (the default): replaces the current assignment, so the ticket ends up assigned to that person alone.
- Add to assignees: keeps whoever is already assigned and adds this person. Chain several Add actions, or run several workflows, to route a ticket to a whole group.
Both modes post the usual assignment system messages and notifications.
Fails when a fixed member has left the project. Skipped when the outcome would change nothing (already assigned to that person alone in Replace mode, already among the assignees in Add mode), or — for Whoever triggered this — when nobody performed the triggering action (the AI, another automation, an integration) or that person is not a team member (e.g. the customer).
Automatic assignment is included in the Team plan. On a lower plan the action appears in the palette with a lock and cannot be added to a workflow. Should a project move down to a plan that no longer includes it, the workflows holding it keep working: only that action is skipped, and it starts assigning again as soon as the plan covers it.
Set priority
Sets the ticket's priority — Low, Medium, High, or Urgent — recorded with the standard priority changed system message.
Skipped when the ticket already carries that priority.
Discord notification
Sends an embed either to a channel of the project's connected Discord server, or as a direct message to the people involved in the ticket. One node has one destination; use two nodes to do both.
The embed is composed with the same editor as the manual sender in Settings, Integrations, Discord — title, message, colour, button label and emoji, plus an author line, thumbnail, image and footer — with a live preview. Every text field supports {path} placeholders, and the preview shows them as you typed them, unresolved.
The author line does not land in the same place for both destinations, and the preview follows it. In a channel, the author name and avatar replace the bot as the sender of the message. In a direct message, the bot still sends it (your project's bot when it has one) and the author appears as a small line at the top of the embed.
To a channel
The default. Posted with a button linking to the ticket in the dashboard. Requires an active Discord integration, and the channel is picked from the server's text channels the bot can post in.
Fails when the send fails: integration removed, channel deleted, or bot missing permissions. The reason is in the run history.
As direct messages
Pick any combination of recipients, resolved when the workflow runs: the customer who opened the ticket, the invited customers who joined it through an invite link, the assigned team members, and any specific team members you name in the node.
Each recipient receives one DM, with a button pointing where they can actually open the ticket: the portal for a customer, the dashboard for a team member.
A recipient is skipped when they have no Discord account linked, when they turned Discord DMs off for this project, or when their Discord privacy settings refuse messages from the bot. Skipped recipients never fail the run: the node reports how many messages were delivered and how many were skipped, both readable by a later condition, and the run history states the reason. The run only fails if Discord itself could not be reached.
A DM node needs no Discord server connected, since a direct message involves none.
Call a webhook
Sends a JSON POST request to an HTTP(S) endpoint you configure. By default the request carries the run's data: trigger event, workflow identity, ticket fields, and the outputs of the nodes already executed.
You can instead write a custom request body: a JSON document of your own, supporting {path} placeholders, so the node can talk to a service expecting its own shape — a Discord or Slack webhook, an automation platform, your own API — without a relay in between. Placeholders are inserted as text and escaped, so a subject containing a quote or a line break cannot break the document. Keep each placeholder inside quotes ("{ticket.subject}"); a body that would not be valid JSON is refused when you save the workflow. Leave the field empty to keep the default payload.
With an optional signing secret, each request carries X-Joely-Timestamp and X-Joely-Signature headers — hex HMAC-SHA256 of "{timestamp}.{body}", computed over whichever body was actually sent — so your endpoint can authenticate the call.
| Rule | Behaviour |
|---|---|
| Private or internal addresses | Refused |
| Redirects | Not followed |
| Timeout | 5 seconds |
| Any response, error statuses included | A delivered call: the run succeeds, and webhook.ok / webhook.status are published to downstream conditions |
| Unreachable endpoint | The run fails |
Ask AI
Has the assistant answer the ticket, right then, instead of waiting for the usual delay after a customer message. Optionally give it an instruction (up to 1,000 characters, supporting {path} placeholders) to steer that one reply: "focus on the installation steps", "answer in two sentences", "explain what we still need from the customer". Leave it empty and you get exactly the reply the assistant would have written on its own.
The reply is written and delivered like any other AI answer: it uses your knowledge base, it counts as one AI response against your monthly quota, and by default it follows your approval setting: sent straight to the customer when approval is off, waiting in the ticket as a draft when it is on. The action's Staff approval option can override that for this workflow only: Always as a draft makes a staff member approve the reply before the customer sees it (like the /ai command), Always send directly sends it right away even when your project requires approval. A draft nobody approves is never sent, so pick Always as a draft only if someone on your team can approve AI replies. If a reply was already counting down on the ticket, this action replaces it, so the customer never receives two.
Skipped when the ticket is closed, when the AI is turned off for the project, when no AI provider is configured, while the assistant is still waiting for the customer to tell it which package the ticket is about, when an assistant draft is still awaiting approval (like the /ai command, it never stacks a second draft), or when the workflow was started by the assistant's own reply: that reply fires the On chat message trigger too, and this rule is what keeps an On chat message → Ask AI workflow from answering itself. A reply the assistant already sent does not block it: started by a command or a customer message, the action answers again, exactly like /ai. The rest of the workflow carries on.
Fails when your monthly AI response quota is exhausted, or the reply could not be produced.
A later condition can read how confident the assistant was, and whether it told the customer a human would take over — connect that to an Assign to a user action and a handoff routes itself.
Ask for the package
Asks the customer which Tebex package their ticket is about, as a dropdown they pick from and confirm. They can choose several packages at once, and their answer links those packages to the ticket exactly as a manual link would: system message, Package selected trigger, everything.
The node has two outputs, Package selected and None / other, so the workflow continues differently depending on the answer.
By default the dropdown offers your whole catalog; restrict it to a specific list when the question only makes sense for a few packages, or list packages under Excluded packages to never offer them (up to 50 options either way, so restrict the list on a large shop). Leave the offered list empty and fill the excluded one to ask about your whole shop except a few packages: packages you add to the shop later are offered automatically. A package cannot be both offered and excluded; the workflow cannot be enabled until you remove it from one of the two lists. The question also works on a ticket that already has packages, and the Linking mode (the same choice as on Set package) decides what the answer does to them:
- Add to the linked packages (default): the packages the customer picks are added to the ones already linked. Packages already linked are not offered, and since a ticket holds at most 10 packages, the customer can only pick as many as the ticket still has room for.
- Replace the linked packages: the ticket ends up linked to exactly what the customer picked, and the packages it no longer covers are unlinked. Packages already linked stay in the list, so the customer keeps one by picking it again. The change shows as a single Packages updated line in the conversation, and only the newly linked packages fire the Package selected trigger.
An Other / not listed answer never touches the linked packages, whatever the mode. Offer "Other / not listed" is on by default and gives the customer a way out — turning it off removes the None / other output, so disconnect any branch wired to it first. You can also customize the dropdown's placeholder text, and have the question itself asked in the customer's language (Team plan, same rule as Post message; package names are never translated).
The point of this action is that it only asks when it needs to. Skipped when the ticket is closed, when the ticket already has the maximum of 10 packages (in Add mode only), when the customer previously answered Other / not listed, when a question from that same node is still waiting for an answer, when the customer already picked a package in answer to that same node, or when there is no package left to offer. Don't ask again after "Other" is on by default; turn it off to keep asking on every run until a package is actually picked. Ask again after a package is picked is off by default, so each node asks at most once per ticket once a package was chosen; turn it on to ask again on later runs, each answer applied with the linking mode.
Like every other prompt, only the customer can answer (your team sees it read-only), the first answer wins, and each answer counts as one workflow run.
The question always shows up as a new reply on the ticket. It is also sent as a Discord DM, like a chat message from Post message (to the customer, the participants and the team members notified of staff replies). The DM shows the same question as the portal: without translation, each customer reads it in their own language, with a reminder to answer it on the portal, and team members read it in English; asked in the customer's language, the DM carries that translated question.
Skipped, failed, and the rest of the run
A skipped action is a normal outcome, not an error: the reason is recorded in the run detail, the run still succeeds, and the other branches keep going.
A failed action stops the workflow: the run is marked Failed with the reason shown in the run history, the rest of that run — including any branches not yet reached — is skipped, and other workflows still run.
Example
Ask what the ticket is about, then route it.Ticket creation → Ask for the package → on Package selected: Assign to a user (the maintainer of that package), then Post message as a system line:
Thanks, we routed your ticket to the right person.→ on None / other: Set priority to Low, then Post message asking for more detail.