← All ivy-agents
IVYXSTUDIO · IVY AGENT
S

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.

  1. 01
    Choose the team
    ivy.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
    state from the agent's input, payload
    set
    instructions Choose the team for this support message: billing, technical, account, or other.
    options ["billing","technical","account","other"]
    secret
    jev_api_key the stored secret jev-api-key
    returns
    team
    Ivy Node
  2. 02
    Open the ticket
    ivy.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
    url from the agent's input, tickets_url
    json.from from the agent's input, payload.from
    json.subject from the agent's input, payload.subject
    json.message from the agent's input, payload.message
    json.team from step 1, choice
    set
    method POST
    secret
    token the stored secret saas-api-key
    returns
    ticket_id
    Ivy Node
  3. 03
    Write the Slack line
    ivy.node.template-render

    Fills {{ name }} placeholders in a text template from a mapping, and reports which names were missing.

    takes
    values.team from step 1, choice
    values.ticket from step 2, json.id
    values.subject from the agent's input, payload.subject
    values.from from the agent's input, payload.from
    set
    template [{{ team }}] {{ ticket }}: {{ subject }} (from {{ from }})
    on_missing empty
    returns
    line
    Ivy Node
  4. 04
    Post the ticket
    ivy.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.text from step 3, text
    set
    method POST
    secret
    url the stored secret slack-webhook-url
    returns
    slack_status
    Ivy Node

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.

Network

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

FieldTypeDescription
payloadrequiredobjectThe event your service posted: from, subject and message of the inbound support message.
tickets_urlrequiredstringYour 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

FieldTypeDescription
teamstringbilling, technical, account or other.
ticket_idstringThe id your API gave the ticket.
slack_statusintegerSlack's HTTP status.
linestringThe 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_url http://127.0.0.1:18910/tickets
    expects
    team equals billing
    ticket_id matches ^T-
    slack_status equals 200
    line matches ^\[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_url http://127.0.0.1:18910/tickets
    expects
    team matches ^(technical|account)$
    ticket_id matches ^T-
    slack_status equals 200