Signup to CRM
ivy.agent.signup-to-crm · v1.0.0
ivyx
Takes a new-signup event, has a model name the customer segment and write one line for the sales channel, creates the contact in the CRM and posts the line to Slack.
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.
- 01Model turnRead the signup
From this signup, say which segment the customer belongs to (individual, startup, smb or enterprise, judged from the email domain, company and plan) and write one line announcing it to the sales channel, naming the person, the company and the plan.
- takes
contextfrom the agent's input,payload- returns
segment,announcement
- 02Ivy NodeCreate the CRM contactivy.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,crm_urljson.emailfrom the agent's input,payload.emailjson.namefrom the agent's input,payload.namejson.companyfrom the agent's input,payload.companyjson.planfrom the agent's input,payload.planjson.segmentfrom step 1,output.segmentjson.notefrom step 1,output.announcement- set
methodPOST- secret
tokenthe stored secret crm-api-key- returns
contact_id,crm_status
- 03Ivy NodeTell the sales channelivy.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 1,output.announcement- 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
crm-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: email, name, company and plan of the new account. |
| crm_urlrequired | string | The CRM's contacts endpoint; a POST creates a contact. The stand-in's address is used in the cases. |
Outputs
| Field | Type | Description |
|---|---|---|
| segment | string | individual, startup, smb or enterprise. |
| announcement | string | The line posted to Slack and kept on the contact. |
| contact_id | string | The id the CRM gave the contact. |
| crm_status | integer | The CRM's HTTP status. |
| slack_status | integer | Slack's HTTP status. |
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, a model core, the CRM's API key stored as the secret crm-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
- team-plan
A company signup on the team plan becomes a CRM contact and a Slack line.
- given
payload{"email":"ada@acme.io","name":"Ada Lovelace","company":"Acme Analytics","plan":"team"}crm_urlhttp://127.0.0.1:18910/crm/contacts- expects
segmentmatches ^(individual|startup|smb|enterprise)$announcementmatches Acmecontact_idmatches ^C-crm_statusequals 201slack_statusequals 200
- free-plan
A personal address on the free plan is a contact too, with its own segment.
- given
payload{"email":"mehmet.k@gmail.com","name":"Mehmet Kaya","company":"","plan":"free"}crm_urlhttp://127.0.0.1:18910/crm/contacts- expects
segmentmatches ^(individual|startup|smb|enterprise)$announcementmatches Mehmetcrm_statusequals 201slack_statusequals 200