0% found this document useful (0 votes)
16 views18 pages

Intro The Problem

The document outlines the development of an AI-based LinkedIn message management system called Request Router, which utilizes UniPile, Slack, and Notion to streamline message handling. It provides a demo of the system in action, emphasizing the importance of human oversight in AI-generated responses. Additionally, the document details the setup process for integrating various components, including webhooks, API credentials, and database configurations.

Uploaded by

dev1tanvir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views18 pages

Intro The Problem

The document outlines the development of an AI-based LinkedIn message management system called Request Router, which utilizes UniPile, Slack, and Notion to streamline message handling. It provides a demo of the system in action, emphasizing the importance of human oversight in AI-generated responses. Additionally, the document details the setup process for integrating various components, including webhooks, API credentials, and database configurations.

Uploaded by

dev1tanvir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 18

Intro: The Problem

0:00
[Music]
0:03
so Max and I cooked up a crazy idea what
0:05
if AI can answer your LinkedIn messages
0:07
for you this started as a jam session
0:09
with Max the original flowmer where we
0:11
basically vibecoded our way through a
0:13
working MVP if you want to see how it
0:15
came together Max made a
0:16
behind-the-scenes video worth checking
0:17
out we were both overloaded with
0:19
LinkedIn messages and internal requests
0:21
and we thought man there's got to be a
0:22
better way to handle this so here's what
0:24
we built a LinkedIn request router that
0:25
uses UniPile to handle messages Slack
0:27
for approvals and Notion is the brains
0:29
behind the scenes we're actually using
0:30
this ourselves this isn't just a demo
0:32
let me show you how to set it up let's
Demo: AI Inbox in Action
0:34
start by seeing a demo of this in action
0:35
the way this works is we utilize Slack
0:38
as our interface for human in the loop
0:40
to do this we've created an app called
0:42
Request Router request router acts as a
0:44
messaging cue for you to process your
0:46
incoming LinkedIn messages now because
0:49
we don't fully trust AI and because
0:51
there are some instances where the AI
0:52
just cannot answer with the context that
0:54
we have we want to make sure that these
0:56
messages go through us first and we're
0:58
able to edit them before we send out the
1:00
AI responses so to do that I'm going to
1:02
go ahead and trigger our web hook here
1:04
on the Unipile side and I'm going to
1:06
trigger a sample message from LinkedIn
1:08
so we'll give it just a few moments for
1:10
it to run and then we should see it
1:12
moving smoothly through this process
1:14
here and there we go so now we've
1:15
triggered the workflow to run and as you
1:17
can see it's running through the
1:18
workflow
1:20
and there we go now if we make our way
1:21
back to request router we can see we've
1:23
received a message it's very well
1:25
formatted using block kit and we have a
1:27
few useful links here we can link
1:28
directly to the person who messaged us
1:30
LinkedIn account or we can link directly
1:32
to the LinkedIn message itself and
1:34
respond via the website LinkedIn but
1:37
what's most useful here is that the
1:39
message has already been preformatted
1:41
and preset up all I have to do is come
1:42
in here and make some changes if I want
1:44
to and hit approve and it will send that
1:46
new updated message out to this user via
1:49
LinkedIn message now this message here
1:51
of course we're is a sample message so
1:53
we're not going to utilize this right
1:54
now but as a cue what we can do here is
1:57
if we don't intend to message this
1:59
person back we can just hit archive or
2:00
we can hit approve to send the message
2:02
for this one I'm going to go ahead and
2:04
archive it for now now let's see what
2:06
happened on the back end so here what
2:08
has happened is we have received the
How It Works (Slack + Notion + Unipile)
2:10
message from LinkedIn through unipile
2:12
which is a third-party service that acts
2:14
as a relay for the LinkedIn API it is a
2:16
paid service however it is well worth
2:18
the cost as it makes working with
2:20
LinkedIn's API very easy to do so the
2:22
message comes in via UniPile we check to
2:24
make sure that we were the one that sent
2:26
or received this message then once we
2:28
check as we can see here it's someone
2:29
other than ourselves that sent this
2:31
message so we're going to go ahead and
2:32
route it here if it had been us
2:34
responding to the person that message
2:35
would have gone down this path because
2:37
we don't want it to take action on our
2:38
messages only incoming messages so the
2:41
message comes in we do some checking on
2:42
LinkedIn to find more details of the
2:45
user to get context of that user in
2:48
LinkedIn things like followers and
2:50
connections and even where they're from
2:51
additionally we will then check our
2:54
notion database this notion database
2:56
acts as a directory this directory
2:58
allows us to route messages hence where
3:00
the name request router came from to the
3:02
right department cuz many times the
3:04
problem is we don't know who needs to
3:06
get a particular message or even if we
3:07
do getting the URL or email address of
3:10
the person that needs to be contacted
3:12
can be difficult or timeconuming at the
3:14
very least so here what we've done is
3:16
we've created a standardized database
3:17
that we're going to look at here in a
3:19
moment to feed the AI with context to
3:21
generate the message appropriately this
3:23
also has a little bit of memory so that
3:25
it keeps track of the separate
3:26
conversations and gives it more context
3:29
when it comes to responding in real time
3:31
next up we will then send one of three
3:33
different messages as we saw here
3:35
there's actually two different types of
3:37
user within LinkedIn so you can get a
3:39
message from an individual user or you
3:41
can get a message from an organization
3:43
so here what we're doing is we're
3:44
checking to see if we find the user if
3:45
we can't then we search the organization
3:48
endpoint and if we can't we have a
3:49
fallback error message and this error
3:52
still generates a Slack automatic
3:53
message but it doesn't have the
3:55
contextual details for the user or the
Setting Up the Workflow
3:58
organization let's go ahead and walk
3:59
through setting this up i've done my
4:01
best to color code these to make it easy
4:03
to deploy so to do that we have the red
4:06
items here which are web hooks that need
4:07
to be updated one here on UniPile one
4:10
here in Slack and then the yellow for
4:12
logic or credential updates that need to
4:14
be made to make sure that this works
4:15
correctly everything else should be able
4:16
to be left as is so let's go ahead and
4:18
start by updating the UniPile web hook
4:21
portion to make this easier I've
4:22
included a link directly to the UniPile
4:25
dashboard to where we need to go so what
4:27
we're going to do here is we're going to
4:28
set up a new web hook so I'm going to
4:29
call this something along the lines of
4:30
NAN web hook i'm going to set it to only
4:33
trigger on messages and on any new
4:35
messages that's what's going to trigger
4:37
the web hook now this is important if
4:38
you manage a business in LinkedIn you
4:40
will not only receive messages sent to
4:42
you but also to your organization any
4:45
organizations that you manage or are
4:46
owner of they're going to trigger this
4:48
workflow as well and when you respond as
4:50
that organization it will trigger it as
4:52
well so we're going to need to update
4:53
the logic to take this into
4:54
consideration so here's where we put our
4:56
callback URL that's pretty
4:58
straightforward we're going to go into
4:59
the web hook we're going to copy the
5:00
production URL and we're going to paste
5:02
it right here now I'm not going to do it
5:03
in this case cuz I don't need more than
5:05
one here so as you can see mine's
5:07
already set up this is what yours should
5:08
look like and you'll be ready to go the
5:10
next portion of setup is the logic so
5:13
this right here is as I was mentioning
5:15
is your LinkedIn user ID now I don't
5:18
believe this is LinkedIn's actual user
5:19
ID this is Unipile's version of your
5:22
LinkedIn ID so the best way to do this
5:24
is to send a message to someone on
5:26
LinkedIn while this is active maybe turn
5:28
off the Slack portions or all the other
5:31
portions here at the end by hitting the
5:32
little power buttons here when the
5:34
message comes in that you know that you
5:35
sent this will fill in with your user ID
5:38
so just copy this directly into this
5:41
portion same goes for if you send or
5:44
receive a message from your organization
5:45
the organization that you manage go
5:47
ahead and update it here if you don't
5:48
manage an organization in LinkedIn go
5:50
ahead and delete this and you'll be in
5:52
good shape from there we're going to
5:53
want to update the credentials inside of
5:56
your Unipile HTTP request so again I've
6:00
tried to link it to make it a little bit
6:01
easier to the Unipile site what we're
6:03
going to do here is we're going to
6:04
generate a token we're going to give it
6:05
messaging and account scopes i'm also
6:07
giving it web hook scope i don't believe
6:09
it needs it but it's best to have it
6:11
just in case we'll call this NAN credits
6:14
and we'll go ahead and generate and make
6:16
sure that expiration date is set up
6:18
correctly now I'm going to delete this
6:19
here in a moment but I did want to
6:20
generate it so that you realize that
6:22
there are two things that need to be
6:23
updated the first is the URL you're
6:25
going to copy this URL here you're going
6:27
to go into here and make sure that this
6:29
portion right here reflects that same
6:32
URL for UniPile and then the second
6:35
portion is the API key so we're going to
6:36
go ahead and go into the Unipile account
6:38
here we're going to copy that API key
6:40
easier to just copy it here into this
6:42
value now you will want to use the
6:44
X-API- key in all caps exactly as we see
6:48
here and don't forget to give it a name
6:49
so here I'm going to leave my old one in
6:51
place i'm going to come back here and
6:53
hit done and I'm going to go ahead and
6:54
delete this one right now once that is
6:57
updated you will need to make sure that
6:59
you do that for all three of these so
7:01
this one as well as this one these three
7:03
all have the Uniile login and they will
7:06
need to be updated next up we're going
7:07
to make our way into Notion now the
7:09
Notion portion already has plenty of
7:11
documentation and I don't have the
7:13
ability to generate API credentials on
7:15
my Notion account here what you're going
7:16
to want to do is follow the
7:18
documentation internally by clicking
7:20
docs and following the instructions but
7:22
more importantly change this out for
7:24
whatever service you use you don't have
7:25
to use Notion you can use something as
7:27
simple as Google Sheets rather if you do
7:29
change this make sure that you change as
7:31
well the outputs here so you may get
7:33
under the schema you really want to get
7:35
a name description as well as an action
7:38
make sure to click and drag these here
7:39
to map them correctly into this single
7:41
object and then from there the rest will
7:43
be updated automatically on the AI agent
7:46
side next we're going to go ahead and
7:47
update our model so if you're going to
7:49
use Open AI's chat GPT it's as easy as
7:52
opening this up and updating your API
7:54
keys here again this is very well
7:56
documented i'm not going to dive into
7:57
the documentation for this portion but
7:59
if you are unsure on how to set up
8:01
credentials for this go ahead and hit
8:02
docs and you'll be good to go it'll walk
8:04
you through it the Slack portion can be
8:06
a little bit more work but I've tried to
8:07
make it as easy as possible what we're
8:09
going to want to do is make your way to
8:11
the Slack API portion under
8:13
api.slack.com/apps
8:16
and it should look something like this
8:17
and what you're going to want to do is
8:18
create a new app now I have included the
8:21
app manifest here to make it easier
8:23
you're going to click here select your
8:24
organization and make your way to the
8:26
template page that's provided in the
8:28
link and head down to the Slack setup
8:30
portion and copy this app manifest in
8:33
order to copy and paste all of the
8:35
scopes required for this app now I did
8:38
not put in a web hook URL so you're
8:40
going to want to replace this with your
8:42
web hook URL we're going to go here and
8:44
go into production URL and replace it
8:46
with your Slack URL this once you've
8:49
pasted it in and created your
8:51
organization or your Slack app you're
8:53
going to go into request into the app
8:54
itself and you're going to go into
8:56
interactivity and shortcuts and just
8:58
make sure that web hook URL is set here
9:00
correctly you may have to update it and
9:02
hit save and it should then start
9:04
working at this point both sections are
9:07
then going to be active make sure that
9:08
you of course update your credentials
9:10
here as well they should update
9:11
automatically once you create the
9:13
credentials here but if not double check
9:15
it and ensure those are up to date now
9:17
that we've set up both portions of the
9:19
workflow ready to start working let's go
9:21
ahead and dive through each portion this
9:23
portion of the workflow receives the
9:25
message and isolates some variables in
9:28
order to make life a little easier we've
9:30
already talked a little bit on how to
9:31
update this portion not going to dive
9:33
too deeply into it and the message comes
9:35
in and is then checked to see if we can
9:38
find more details on the user that
9:40
information can be found by opening this
9:42
up and as you can see we have the data
9:44
on the right with the information of the
9:46
user if it's not found it will then try
9:48
the organization to see if it can find
AI Agent & Directory Logic
9:50
it once we get that information we're
9:51
going to get our directory this is where
9:53
a big portion of the power of this
9:55
automation lives ai is wonderful but
9:58
without guard rails AI can quickly start
10:00
hallucinating responses that we may not
10:02
want to that end we've created a little
10:04
database internally for our team you can
10:06
think of this database as almost a
10:08
standardized procedures database that
10:10
allows us to route the answers to the
10:13
correct department for example if
10:15
somebody wants to become an NADN
10:16
ambassador they need to visit a specific
10:18
web page that web page is now preloaded
10:20
so if the message comes in saying "Hey
10:22
how do I become an NAND ambassador?"
10:24
Typically I'd have to find the owner get
10:26
the information from them get the URL
10:28
and then send it to the person via
10:30
LinkedIn in this case that information
10:31
is already included in the database so
10:33
it will generate a response that
10:35
includes that URL that makes life a lot
10:37
easier things like as well how can I
10:39
become an expert here as you can see we
10:41
have the NAND experts page this allows
10:43
us to quickly route the message to the
10:46
right person not only that but we see
10:47
who the owner is we're able to
10:49
standardize our internal processes and
10:51
use that standardized database not just
10:54
for manual use for someone like me that
10:56
might be new to be able to figure out
10:58
who to send requests to but also for our
11:00
AI to automatically generate responses
11:03
this is really powerful if you create a
11:04
subworkflow of the AI portion of this
11:07
and use that subworkflow not just for
11:08
LinkedIn but also for maybe your email
11:10
inbox to instead of generate the
11:13
responses and send them via email but to
11:15
generate responses and set them up as a
11:16
draft email attached to that thread
11:18
there are many uses for this and it
11:20
doesn't have to be notion it can also be
11:22
something as simple as Google sheets the
11:24
other thing that we can do is
11:25
conditional responses this is really
11:27
powerful because one of the things we're
11:29
getting here via LinkedIn is how many
11:30
followers and connections a particular
11:32
person has or organization has when they
11:34
message you for example on my end what
11:36
I've done is I've created a conditional
11:38
message that if somebody messages me and
11:40
they have over 5,000 followers on
11:42
LinkedIn I immediately will give them my
11:44
booking link this is great because I can
11:47
see that this person is an influencer
11:48
this person is wellconed and maybe they
11:51
can help our organization internally in
11:54
terms of our outreach now if they're
11:56
under 5,000 we can give them a warm
11:59
polite decline so thanking them for
12:01
their interest let them know that I'm
12:03
currently heads down or unable to meet
12:05
thanks so much for this kind message
12:06
really appreciate it at this moment I'm
12:07
heads down not taking on new meetings
12:09
letting them know hey I'm sorry I'm a
12:11
little busy right now these kinds of
12:12
messages tend to flood my inbox and so
12:14
this has been a wonderful way to be able
12:16
to quickly decide whether or not I
12:19
should reach out to someone or not now
12:21
that you have a better understanding of
12:22
the directory database let's head back
12:24
into request router and move on to the
12:26
next step which is the AI agent this is
12:28
where the AI magic happens there are two
12:31
inputs here we have our user input which
12:33
is the context of the message here we
12:35
have the name of the sender the message
12:37
themselves that was sent and my name in
12:39
this particular case and here I might
12:41
replace this with Angel and you don't
12:42
have to give it this context but it
12:44
helps especially if you're utilizing
12:46
this workflow across several different
12:48
users and then here we have a little bit
12:49
of a prompt to found the LinkedIn
12:50
profile will be below pay close
12:52
attention to the number of followers and
12:53
connections this is important for that
12:56
conditional responses that we mentioned
12:58
earlier and then the most important part
13:00
is here the actual system prompt you can
13:02
think of this as the AI's personality so
13:04
here we're telling it what it is smart
13:06
professional assistant designed to help
13:08
generate smart personalized responses in
13:10
LinkedIn we give it an idea of what it's
13:12
going to be provided with and then our
13:13
objective the first objective is to look
13:15
inside of our directory database which
13:18
is included below to see if there's any
13:20
potential responses to their answers in
13:23
that database and then if nothing is
13:24
found generate a thoughtful response
13:26
from its own training this makes it
13:29
faster to respond because this at least
13:30
takes care of the pleasantries within
13:32
the message response cycle at the very
13:34
least all I have to do is go into Slack
13:36
and edit just the content itself but the
13:38
beginning and end is usually well
13:40
thought out and ready to go we also give
13:42
it a nice tone so friendly confident and
13:44
professional lightly personalized
13:46
doesn't sound like a sales pitch and
13:48
keep the replies concise and natural we
13:50
want to make sure to acknowledge the
13:51
sender's message add a relevant or
13:53
helpful comment and keep the tone warm
13:55
and open-ended only the output of the
13:58
message should be sent to the user and
13:59
here we have the actual directory
14:01
database we give it the context needed
14:03
to respond correctly and then the format
14:05
we expect it to respond in we also have
14:08
that format set in the output parser
14:10
right here in order to double check to
14:12
make sure that the output is correct
14:14
once that is done because we are setting
14:16
a response type and that is set a little
14:18
further earlier on here on the type so
14:21
here we're either a user type or we're
14:23
an organization type or if not either of
14:26
those then none here it routes through
14:28
one of these two and if it can't find
14:31
them then it sends this type of message
14:33
as you can see here we sent this kind a
14:35
user message and we've mapped in all of
14:38
the relevant block kit needed to ensure
14:40
that the message looks nice and is
14:42
contextual and we've also included the
14:44
button block kit here that embeds the
14:48
uniile message ids and chat ids in order
14:51
to store this inside of Slack almost as
14:54
a database item when we hit the button
14:56
it sends this data back in the bottom
14:59
part of this workflow to quickly route
15:01
the message as needed let's take a look
Slack Button Actions + Advanced Routing
15:02
at that portion when we hit one of the
15:04
buttons it sends it down to this web
15:06
hook this is used to verify that the web
15:08
hook is still active in case Slack sends
15:11
a challenge message normally this will
15:13
not be used other than whenever you
15:14
first put in your web hook URL in the
15:16
Slack app and then here we check for
15:18
users because we want to create the
15:20
least amount of apps possible what we
15:22
can do is we can use this as an
15:24
organization here what we're doing is
15:26
we're checking to make sure that my
15:27
Slack user ID is set if I'm the one that
15:30
presses the button my Slack user ID is
15:33
included in the payload user ID and it
15:35
routes it through my response type but
15:37
if for example my colleague Max presses
15:40
the button on his but he's using the
15:42
same Slack app it gets sent to the same
15:43
workflow what I can do is send that
15:45
payload to his workflow in N8N and have
15:48
him take care of the logic on his end to
15:51
customize what happens when the button
15:52
is pressed here as you can see if the
15:54
message is mine I'm going to isolate the
15:56
message and payload here we're going to
15:58
check to see if we approved it or not
15:59
and then here since we have stored the
16:02
message and chat ids we're going to go
16:04
ahead and send it to this channel ID the
16:06
message and here is the message itself
16:09
that we're sending this as the response
16:11
and then from there we're going to go
16:12
ahead and delete the message from Slack
16:14
in order to keep our queue nice and
16:16
clean and keep that human in the loop
16:18
process active that is the whole process
16:20
now this can be adapted in many
16:22
different ways you can adapt this for
16:24
this portion right here to be its own
16:25
subworkflow that then can be used both
16:27
for LinkedIn or for emails whenever an
16:30
email inbox message is sent into a
16:32
shared organization email you can use
16:35
the same subworkflow to ensure that only
16:38
one place needs to be updated across
16:40
multiple workflows and you have the same
16:43
consistent output across all of them and
Wrap-Up & Template Info
16:45
that's request router simple human in
16:46
the loop and built using tools you
16:48
probably already have if this sparked
16:49
any ideas or you want to build your own
16:50
flavor of it hit me up via LinkedIn i'd
16:52
love to see what you come up with i'm
16:53
including the template file in the link
16:55
below and again don't miss the
16:56
behind-the-scenes video Max made of the
16:58
original session catch you on the next
17:00
one

You might also like