Support Message Router
ivy.agent.support-message-router · v1.0.0
ivyx
Takes an inbound support message, has Jev choose the team, opens a ticket through your API and posts the ticket to Slack with its team.
Steps
In the order the agent's file lists them, each with where its inputs come from and the values the file fixes. A branch or a loop is a step too.
- 01Ivy NodeChoose the teamivy.node.jev-choice
Asks TypeSafe Jev which of the given options fits a text or JSON state and returns the chosen option with its confidence and the probability of every option.
- takes
statefrom the agent's input,payload- set
instructionsChoose the team for this support message: billing, technical, account, or other.options["billing","technical","account","other"]- secret
jev_api_keythe stored secret jev-api-key- returns
team
- 02Ivy NodeOpen the ticketivy.node.http-request
Sends one HTTP request to a URL and returns the status, headers and body, parsed as JSON when the response is JSON.
- takes
urlfrom the agent's input,tickets_urljson.fromfrom the agent's input,payload.fromjson.subjectfrom the agent's input,payload.subjectjson.messagefrom the agent's input,payload.messagejson.teamfrom step 1,choice- set
methodPOST- secret
tokenthe stored secret saas-api-key- returns
ticket_id
- 03Ivy NodeWrite the Slack lineivy.node.template-render
Fills {{ name }} placeholders in a text template from a mapping, and reports which names were missing.
- takes
values.teamfrom step 1,choicevalues.ticketfrom step 2,json.idvalues.subjectfrom the agent's input,payload.subjectvalues.fromfrom the agent's input,payload.from- set
template[{{ team }}] {{ ticket }}: {{ subject }} (from {{ from }})on_missingempty- returns
line
- 04Ivy NodePost the ticketivy.node.http-request
Sends one HTTP request to a URL and returns the status, headers and body, parsed as JSON when the response is JSON.
- takes
json.textfrom step 3,text- set
methodPOST- secret
urlthe stored secret slack-webhook-url- returns
slack_status
Nodes it brings
Adding this agent in IVYX Studio adds these nodes with it. A node your workspace already has is kept as it is, even at another version.
What it touches
Collected from what each of its nodes declares, plus the model call when a step is a model turn. A declaration is the author's statement, and it is what policy rules select on.
What it needs
- A stored secret named
jev-api-key. The agent's file carries the name, never the value. - A stored secret named
saas-api-key. The agent's file carries the name, never the value. - A stored secret named
slack-webhook-url. The agent's file carries the name, never the value.
Inputs
| Field | Type | Description |
|---|---|---|
| payloadrequired | object | The event your service posted: from, subject and message of the inbound support message. |
| tickets_urlrequired | string | Your API's tickets endpoint; a POST with from, subject, message and team opens a ticket. The stand-in's address is used in the cases. |
Outputs
| Field | Type | Description |
|---|---|---|
| team | string | billing, technical, account or other. |
| ticket_id | string | The id your API gave the ticket. |
| slack_status | integer | Slack's HTTP status. |
| line | string | The line posted to Slack. |
Tests
2 of 2 test cases passed on Oct 7, 2026, in the publisher's own environment, before this version was published. The registry keeps that record; it does not run the cases again.
Requires: python:3.9, the stored secret jev-api-key, your own API's key stored as the secret saas-api-key, a Slack incoming webhook URL stored as the secret slack-webhook-url, for the cases, the stand-in API on 127.0.0.1:18910 (api-standin.py), which the secrets crm-1, gh-1, saas-1 and the stand-in's /slack/hook address satisfy
- double-charge
A double charge goes to billing, gets a ticket and a Slack line naming the team.
- given
payload{"from":"ada@acme.io","subject":"Charged twice","message":"My card was charged twice for October. Please refund one o...tickets_urlhttp://127.0.0.1:18910/tickets- expects
teamequals billingticket_idmatches ^T-slack_statusequals 200linematches ^\[billing\] T-
- cannot-log-in
A login loop goes to technical or account.
- given
payload{"from":"ops@globex.example","subject":"Cannot log in","message":"After the password reset the login page just reload...tickets_urlhttp://127.0.0.1:18910/tickets- expects
teammatches ^(technical|account)$ticket_idmatches ^T-slack_statusequals 200