How to Route Inbound Client Requests to the Right Project Manager with AI
Build a Spojit workflow that watches a shared client inbox, uses AI to classify each request by type and urgency into structured JSON, then opens a Monday.com task and direct-messages the assigned project manager in Slack.
What This Integration Does
Professional-services teams (agencies, consultancies, fractional teams) usually share a single client inbox such as clients@youragency.com. Messages land there mixed together: scope changes, billing questions, urgent escalations, and routine status checks. Triaging them by hand is slow, and the right project manager often sees an urgent request hours late. This workflow reads every new message, lets an Agent-mode Connector node decide what kind of request it is and how urgent it is, then creates a tracked Monday.com task and pings the owning project manager directly in Slack so nothing slips.
The run model is poll-driven. An Email trigger checks a connected Gmail or Outlook mailbox on an interval and starts one run per new message. A Connector node in Agent mode classifies the message and returns clean JSON via a Response Schema. A Condition node branches on the classified request type to pick the right Monday.com board and project-manager handle, then two Connector nodes in Direct mode create the task and send the Slack DM. Each message produces exactly one Monday.com item and one Slack notification; because the Email trigger only fires on messages it has not seen, re-polling does not double-process the same email.
Prerequisites
- A Gmail (trigger) or Outlook (trigger) connection on the shared client inbox, added under Connections → Add connection. Read-only access is enough for this workflow.
- A Monday.com connection (API key) with access to the board(s) you route tasks into. Note the numeric
boardIdfor each board, and agroupIdif you want tasks placed in a specific group. - A Slack connection with permission to look up users by email and send messages.
- A small mapping you maintain yourself: which request type goes to which project manager, their Slack login email, and the target Monday.com board.
- Optional: a Front connection if your shared inbox is managed in Front and you want to enrich the sender with contact details.
Step 1: Start with an Email trigger on the shared inbox
Add a Trigger node and set its type to Email. Select your connected Gmail or Outlook mailbox, choose the folder (typically Inbox), and set a poll interval (1 to 60 minutes; the default of 2 is fine for a client inbox). Leave after-processing off unless you want Spojit to mark messages read, which needs a read-and-modify connection. Each new message produces an output you can reference downstream:
{
"from": "jane@clientco.com",
"to": "clients@youragency.com",
"subject": "URGENT: launch date moved up",
"textBody": "Hi team, our board moved the launch to Friday...",
"receivedAt": "2026-06-21T08:14:00Z",
"conversationId": "...",
"attachments": []
}
If you only forward client mail into Spojit rather than owning the mailbox, consider a Mailhook trigger instead, which gives you a unique ...@mailhook.spojit.com address and fires within seconds with no mailbox connection. See Webhook vs Mailhook: Which Trigger Should I Use? to choose.
Step 2: Classify the request with a Connector node in Agent mode
Add a Connector node and switch it to Agent mode. Agent mode lets the agent read the email and reason about it instead of you hand-coding rules. In the prompt, pass the subject and body and ask for a classification:
You are triaging an inbound client email for a professional-services team.
Subject: {{ trigger.subject }}
From: {{ trigger.from }}
Body:
{{ trigger.textBody }}
Classify this request. Return:
- requestType: one of "scope_change", "billing", "status_update", "escalation", "general"
- urgency: one of "low", "normal", "high"
- summary: one short sentence a project manager can scan
- suggestedDueInDays: integer, 1 for high urgency, 3 for normal, 7 for low
Because you need predictable fields, not prose, turn on the Response Schema so the agent must return JSON matching:
{
"type": "object",
"properties": {
"requestType": { "type": "string",
"enum": ["scope_change", "billing", "status_update", "escalation", "general"] },
"urgency": { "type": "string", "enum": ["low", "normal", "high"] },
"summary": { "type": "string" },
"suggestedDueInDays": { "type": "integer" }
},
"required": ["requestType", "urgency", "summary", "suggestedDueInDays"]
}
Set the node's output variable to classification. Downstream you reference {{ classification.requestType }}, {{ classification.urgency }}, and {{ classification.summary }}. For more on locking AI output to a schema, read How to Use Structured Output for Reliable AI Data Extraction.
Step 3: Branch on request type with a Condition node
Add a Condition node to route each request type to the correct project manager and Monday.com board. The cleanest pattern is one Condition per high-traffic type plus a catch-all. For example, set the first branch to check whether {{ classification.requestType }} equals escalation, and a second to check billing; anything else falls through to a general branch.
In each branch you set the two values the later steps need: the target boardId and the assigned manager's email. The simplest approach is to put a small Transform node at the top of each branch that emits, for example, { "boardId": "1234567890", "pmEmail": "alex@youragency.com" } into a variable called routing. That keeps your routing table in one visible place and lets the Direct-mode steps after the branches stay identical. For deeper branching guidance see Using Condition Nodes.
Step 4: Create the Monday.com task with a Connector node in Direct mode
Add a Connector node in Direct mode, choose the Monday.com connector, and select the create-item tool. Map its inputs from the variables built above:
boardId:{{ routing.boardId }}name: a readable title, e.g.[{{ classification.urgency }}] {{ classification.requestType }} - {{ trigger.from }}groupId(optional): the group you want new client requests to land incolumnValues: a JSON object keyed by your board's column IDs, for example status, the request summary, and the source email
{
"status": { "label": "New" },
"text_summary": "{{ classification.summary }}",
"email_source": { "email": "{{ trigger.from }}", "text": "{{ trigger.from }}" },
"date_due": { "date": "{{ classification.dueDate }}" }
}
Column IDs are specific to your board. Run the Monday.com get-board tool once in a scratch workflow to read the exact column IDs, then plug them into columnValues. Set this node's output variable to mondayItem so you can reference {{ mondayItem.id }} in the Slack message. A worked end-to-end example lives in How to Create Monday.com Tasks from Customer Support Emails.
Step 5: Resolve the project manager's Slack user
Add another Connector node in Direct mode on the Slack connector and select lookup-user-by-email. Map its email input to {{ routing.pmEmail }}. This returns the manager's Slack user object; set the output variable to pmUser so you can address the direct message to their user ID. Looking the user up at run time means you never hard-code Slack IDs, and the workflow keeps working if someone joins or changes their handle as long as their login email matches the one in your routing table.
Step 6: Send the project manager a Slack DM with a Connector node in Direct mode
Add a final Connector node in Direct mode on the Slack connector and select send-message. For a direct message, set the channel input to the manager's user ID returned in the previous step, and write a templated text that links straight back to the work:
channel:{{ pmUser.user.id }}text:
:incoming_envelope: New {{ classification.urgency }}-urgency client request
*Type:* {{ classification.requestType }}
*From:* {{ trigger.from }}
*Summary:* {{ classification.summary }}
*Monday task:* item {{ mondayItem.id }}
Original subject: {{ trigger.subject }}
That is the full path: an email arrives, the agent classifies it, the Condition routes it, Monday.com tracks it, and the right project manager is notified in Slack within one poll cycle. If you would rather notify a shared channel as well, add a parallel send-message call with channel set to a channel ID instead of a user ID, as shown in How to Set Up Multi-Channel Notifications (Email + Slack).
Tips
- Keep your routing table in one place. A single Transform node per Condition branch that emits
boardIdandpmEmailis far easier to maintain than editing field mappings inside every connector node. - Use the
summaryfield from Step 2 as the Monday.com task description and the Slack message body so managers get the same one-line context in both places. - Agent mode costs AI credits per run while the Monday.com and Slack Direct-mode calls do not. If volume is high, narrow the trigger with a From allowlist or Subject regex so only genuine client mail is classified.
- If your shared inbox lives in Front, add a Connector node on the Front connector with
get-contactorlist-contactsto attach the client's account name and tags to the Monday.com task.
Common Pitfalls
- Monday.com
columnValuesmust use your board's real column IDs, not the visible column titles. Mapping to a title silently drops the value. Runget-boardonce to read the IDs. - Slack
send-messagesends a direct message only whenchannelis a user ID. Passing an email or a display name fails. Always resolve the user first withlookup-user-by-email. - If
lookup-user-by-emailfinds no match (the manager signed up to Slack with a different address), the DM step will fail. Keep the emails in your routing table identical to each manager's Slack login email. - The Email trigger only sees mail in the folder you selected. If a rule moves client mail out of
Inboxbefore the next poll, those messages never trigger a run. - Reply timestamps follow the mailbox's timezone, and any due-date you compute from
suggestedDueInDaysshould be formatted to the date format your board column expects.
Testing
Validate on a tiny scope first. Set a From allowlist on the Email trigger to a single test address, send yourself a few sample emails covering each request type (one clear escalation, one billing question, one routine status check), and watch the run in the execution log. Confirm the Agent-mode node returns valid JSON against your Response Schema, that the Condition routes each type to the expected board and manager, and that one Monday.com item plus one Slack DM appear per message. Once the routing looks correct, widen or remove the allowlist to take the workflow live. If a run fails, ask Miraxa "Why did my last run fail?" to investigate it in context.