►
From YouTube: Support Ops - Managing agents via zendesk-agents
Description
Jason Colyer, Support Operations Manager, takes us through managing Zendesk Support agents via the zendesk-agents repo
A
A
So
the
readme
is
kind
of
basic.
It
tells
you
how
to
add
a
new
group.
It
shows
you
the
file
tree
and
tells
you
how
to
update
things
manually
when
needed,
but
figure
the
best
way
to
kind
of
get
started
with.
This
is
just
start
with
the
gem
file
right,
so
the
gym
file.
It
has
the
gems
for
faraday,
middleware,
json,
oj
and
yaml
faraday
middleware
for
making
connections
making
requests
oj
because
it
parses
things
really
nicely.
A
So
beyond
that
the
scripts
themselves,
we
have
the
group
and
agent
sync
so
group,
sync,
it's
just
going
to
call
zendesk
agents
groups
gather
run
and
then
it's
going
to
do
the
same
for
compare
same
for
sync,
you'll
notice.
Agents
does
kind
of
the
same
thing.
It's
going
to
call
zendesk
agents,
users
gather
run,
compare
run,
sync
run.
A
So
beyond
that
yeah,
let's
just
kind
of
get
started
into
the
actual
code
itself,
so
it
all
starts
with
this
zendesk
agent's
file.
A
This
itself
requires
bundler
and
has
bundler
run
to
install
those
gems
and
they
require
everything.
Well,
sorry,
it
requires
bundler
and
what
bundler
has
in
the
gym
file
so
that
it
requires
all
the
gems
it's
kind
of
a
simple
step
to
save.
We
have
four
of
them
we're
requiring
here,
so
it
wasn't
as
useful,
but
I
mean
when
you
have
100
gyms.
A
This
is
pretty
useful
and
beyond
that
we're
requiring
the
zendesk
agent's
client
file
so
go
ahead
and
go
into
the
folder
here
and,
let's
start
with
the
client
file
seems
a
good
place
to
start
right.
So
we
declared
you
know:
we've
got
our
module,
we've
got
our
class
for
clients
and
then
we're
requiring
the
groups
and
the
users
which
we'll
go
over
in
a
bit.
A
A
We're
also
defining
the
gl
client
function.
This
is
going
to
set
a
global
variable
gl
clients,
if
you're
not
familiar
with
the
double
pipe
equal.
It's
a
fancy
way
in
ruby
to
say
set
it
to
this.
Unless
it
already
has
a
value,
it's
really
useful.
This
means
in
the
future.
We
can
call
geoclamp
15
times,
and
it's
not
going
to
make
new
connections
it's
going
to
use
the
one
that's
already
been
established.
A
We
also
define
this
support
team
yaml
function.
This
has
the
url
for
the
actual
file
itself
that
we
want
to
read.
We
want
to
read
it
in
the
raw
from
the
master
branch
and
we're
going
to
call
the
gl
client
function.
We're
going
to
make
you
know,
do
a
public
send
on
it
using
a
get
http
method
and
using
that
url
we're
going
to
then
take
the
response
body
and
parse
it
using
gamma.
A
A
We've
got
the
request
retry,
where
that's,
where
we're
passing
our
retry
options
into
the
fair
adapter
is
the
default
faraday
adapter
in
the
headers,
we're
setting
the
content
type
to
application
json,
it's
something
that
the
desktop
api
requires
and
then
we're
making
we're
having
faraday
do
a
basic
authentication
of
a
zendesk
username,
slash
token
and
then
the
token.
Once
again,
these
are
cicd
variables.
A
It's
then
going
to
basically
make
a
public
send
on
that
zendesk
function,
using
the
http
method,
url
and
parameters,
and
then
it's
going
to
use
oj
to
load
the
but
response
body
to
us,
and
then
here
we
set
all
our
groups
that
we
work
with
in
zendesk
a
net
future
iteration
could
have
this
removed
and
instead
have
us
dynamically
generate
this.
For
now
we
hard
coded
it
because
there's
not
that
many
of
them.
A
So,
let's
start
with
the
groups,
because
that's
kind
of
where
we're
gonna
do
first,
normally
in
ci
cd,
we
wanna
obviously
set
up
our
groups
first
before
we
start
messing
with
users
groups,
this
file
is
just
gonna
require.
You
know
the
groups
compare
gather
and
sync
functions,
so
we'll
go
into
the
groups
folder
and,
let's
start
with
gather,
because
we
gotta
gather
information
first
right,
so
we've
got
our
modules
and
desk
agents,
we've
got
our
class
groups
and
then
we've
got
our
class
gather.
This
is
our
new
one.
A
We
have
the
run.
Exclamation
point
function.
This
is
basically
just
a
function
to
kind
of
gather
everything
we're
doing
in
one
nice
function
so
that
you
saw
those
spin
files.
We're
literally
just
calling
run
run
run
run
it's
a
lot
easier
than
having
15
different
things
we
have
to
do,
but
the
run
function
is
essentially
going
to
output
that
it
is
gathering
this
data
from
the
support
team
ammo.
And
it's
going
to
do
that
using
the
team
function
and
then
it'll
say
it's
done.
A
Now
our
team
function,
we've
got
the
global
team,
variable
double
pipe
people
and
map
team.
The
map
team
function
is
getting
that
support
team,
yaml
data
from
the
client
function,
and
then
it's
determining
memberships.
Based
on
the
data
from
the
supporting
email
file
for
the
memberships.
We
set,
the
team
groups
variable
to
an
empty
hash,
and
then
we
just
go
over
our
support.
A
Tml
data
we
iterate
over
it
for
each
user
and
we
want
to
go
through
each
user's
groups,
so
there's
in
desk
main
groups
and
then
using
that
we're
basically
going
to
get
the
id
value
from
the
name
that
is
in
the
support
team.
Animal
file.
That'll
give
us
our
group
id
in
our
empty
hash,
we're
going
to
set
team
we're
going
to
set
the
key
value
for
this
id
to
an
empty
array.
A
If
it
doesn't
exist,
that's
that
unless
it
actually
has
value
and
then
we're
going
to
set
the
we're
going
to
basically
push
the
user's
zendesk
user
id
to
this
new
array
that
we've
built
to
this
array.
For
that
you
know
key
value
and
after
all,
that's
done
we're
going
to
return
the
team
groups,
that's
essentially
what
the
at
team
is
going
to
have
stored
in
it.
Now
for
the
groups,
we
set
the
global
variable
groups
and
we
call
map
groups.
A
Here
we
set
an
empty
hash
for
memberships
and
for
every
group
in
the
in
the
client.
You
know
that
client
file
we
defined
we're
going
to
do
an
iteration
now
we're
not
actually
using
the
name.
We
just
need
the
ids,
so
what
I
did
is
underscore
name.
This
is
a
nice
way
to
say
yes,
it
has
a
key
value,
but
we're
not
using
it,
but
we
have
to
define
it
right
so
that
we
can
edit
we
get
the
variable
set
correctly.
A
The
membership
we're
going
to
determine,
based
on
making
a
zendesk
client
a
zendesk
request,
using
a
get
get
http
parameter
to
that
groups.
Ids
membership
they're
going
to
take
the
memberships
id
and
set
it
to
you
know,
set
it
to
the
memberships
that
we
got
from
our
request
and
then
we're
going
to
return
the
memberships
now,
after
all,
that's
said
and
done,
you'll
notice,
it's
mapping
this
to
a
zendesk
object.
That's
just
in
this
format.
That's
the
exact
format.
Zendesk
wants
when
manipulating
the
api
through
updates,
deletes,
etc.
A
A
A
A
That
is
my
user
id,
and
I
am
the
owner
of
zendesk
and
if
you
make
an
api
request
to
update
an
owner,
you
get
an
error,
because
no
level
of
permission
allows
you
to
do
that,
not
even
the
owner's
api
permission
I
basically
have
to
log
in
with
my
username
and
my
password.
That's
the
only
way
I
can
edit
my
stuff.
So
we
skip
that
in
most
of
our
functions
and
stuff.
Just
because
we
don't
want
that
error.
A
It's
just
going
to
complicate
things
now
deletes
is
getting
the
membership's
id
unless
that
user
exists
and
our
support
team
enables
you
know
data.
So,
if,
like
it
comes
across,
it's
like
oh
support,
a
mia
group-
and
it
looks
at
you
know
bob
and
bob's,
not
part
of
that
group
in
the
support
team.
It's
gonna
say:
okay,
I
need
to
delete
that
push
that
to
deletes
for
updates.
It's
gonna
do
this
kind
of
in
the
reverse.
Actually,
it's
going
to
look
through
the
supporting
yaml
information.
A
It's
going
to
find
the
zendesk
group
based
on
that
and
then
it's
going
to
say
if
they're,
not
in
the
zendesk
group,
I
need
to
add
them
to
it
because
they're
in
the
support
team
yeah,
this
is
using
an
update
object
which
will
use
the
user
id
and
the
group
id
in
this
case
our
user
is,
you
know
their
id
number,
it's
their
zendesk
id.
It's
then
going
to
make
the
updates
and
deletes
json
artifacts.
A
A
We
call
it
an
update
because
it's
updating
as
far
as
we're
concerned,
but
as
far
as
like
the
back
end
of
zendesk,
it
is
creating
a
group
membership
object,
so
our
updates
are
coming
from
our
updates
file.
Our
deletes
are
coming
from
our
deletes
json
file,
we're
having
json
parse
those
for
creates
we're
going
to
slice
our
updates
into
100
there's
a
max
for
the
update.
Many
create
many
delete
mini.
That
is
a
hundred,
that's
the
most.
You
can
do
in
one
bulk,
so
to
prevent
issues.
A
What
we
actually
do
is
slice
it
into
a
hundred.
Now,
in
theory,
we
shouldn't
be
needing
to
update
more
than
100
people's
groups,
but
just
in
case
we're
going
to
make
a
post
request
to
zendesk
using
the
group.
Memberships
create
mini
and
we're
going
to
pass
it.
The
memberships
for
the
group
memberships
and
we're
going
to
make
sure
that
what
it's
sending
for
the
parameter
is
in
json
format,
because
that's
how
zendesk
wants
it
deletes
is
similar,
but
instead
we're
post
we're
doing
a
delete,
http
method
request.
A
Two
group
memberships
create
many
and
we're
doing
our
ids.
For,
like
that,
that's
that's!
Basically,
all
you
do
we're
just
joining
the
id
membership
numbers,
their
user
ids.
So
that's
the
group
functions.
Let's
look
at
the
users,
so
for
users,
it's
very
similar
to
groups
we're
you
know
making
sure
to
require
relative.
The
compare
gathers
take
so,
let's
look
at
gather
first,
since
you
know
we
have
to
gather
data
first,
this
one
actually
does
a
little
more
than
the
group.
A
So
you
know,
we've
got
our
module,
our
class
and
our
you
know
other
class
and
we've
got
the
run,
which
will
let
us
know
it's
parsing.
It's
gathering
data
from
support
team
ammo
and
it
will
via
team,
tell
us
when
it's
done.
Gather
data
from
zendesk
via
agent's
function.
Tell
us
when
it's
done
and
then
make
artifacts
so
that
parts
pretty
pretty
similar
to
the
groups.
A
So
our
team
function
it's
going
to
map
the
team
and
to
do
that.
It's
going
to
get
the
supports
enamel
data
and
it's
going
to
map
them
into
team
to
agent
object,
and
the
reason
for
that
is.
We
want
them
in
a
format
that
zendesk
would
also
recognize
so
they're
easy
to
compare
it's
a
one-to-one
comparison
instead
of
trying
to
say:
oh
well,
zendesk
does
it
in
this
format,
but
we
have
it
in
this
format.
A
So
the
format
we
do
is
their
id
is
their
zendesk
main
id.
Their
name
is
their
their
name,
their
organization
id.
That's
always
that
one
that's
git
lab.
It's
always
that
one
for
tags
we
run
the
determine
agent
tags
for
signature,
determine
signature
default
group,
different,
determined
default
group
and
then
their
user
fields.
Their
username
is
their
gitlab
username
and
their
user
id
is
their
gitlab
id
so
for
determine
agent
tags.
A
Basically,
we
start
with
an
empty
array
and
if
their
title
has
operations
in
it,
they
get
the
operations
tag,
but
as
manager
they
get
the
manager
tag.
If
it
has
director,
they
get
the
director
the
manager
tag,
and
then
it's
going
to
do.
The
reports
too
and
reports2
is
looking
at
their
manager
and
then
formatting
it
into
a
way
that
becomes
a
tag
and
we're
going
to
do
a
sort
on
those
and
a
unique.
A
We
want
a
unique
because,
like
a
good
example
is,
I
could
be
director
of
support
management
or
some
weird
title
that
doesn't
exist
and
that
would
actually
catch
manager
twice,
but
we
don't
want
to
tell
it
add
the
manager
tag
twice
it
can't.
So
we
want
to
just
sort
it
to
make
that
easier.
On
zendesk
for
the
signature,
we're
going
to
start
with
an
array
that
just
has
a
new
line
on
it
and
we're
basically
just
going
to
add
line
by
line
their
signature.
A
So
first,
if
they
have
a
salutation
defined
in
their
support
team.
Animal
entry,
it'll
pick
a
random
salutation,
because
if
they
have
one
it'll
get
that
one
every
time
if
they
have
20
it'll
pick
one
random
one.
Every
time
it's
going
to
get
their
name
and
their
title,
it's
going
to
get
the
you
know
the
get
lab
support,
link
and
then
the
feedback
form,
which
is
a
string
containing
a
link
to
our
feedback
form.
A
It's
then
going
to
join
that
array
by
new
lines.
So
what
we'll
end
up?
Having
is
blank
line?
Blank
line
name
new
line?
You
know
title
new
line,
link
new
line,
et
cetera
for
different,
determining
the
default
group.
Here,
we're
basically
going
to
get
the
groups
from
the
client
of
the
client
file
and
if
the
agent's
group
is
support,
ops,
we're
gonna
set
the
default
group
to
support
ops.
If
their
title
is
operations,
we're
gonna
set
their
default
group
to
managers.
A
The
agent
object
that
it's
actually
using
for
the
zendesk
side
of
things
just
looks
like
this,
and
that's
because
it's
already
pretty
much
in
the
right
format.
We
just
wanted
to
make
sure
we
sorted
the
tags,
so
they're
one-to-one
comparison
and
then
it's
gonna,
you
know,
make
the
artifacts
just
in
case
gather
agents.
I
don't
remember
if
I
quite
went
over
this,
but
basically
you
know:
we've
got
our
agent,
we're
gonna,
get
our
agents,
the
ids,
we're
mapping
ids
from
the
team.
A
A
So
the
next
thing
we
would
do
is
compare
now
for
compare
it's
going
to.
Let
us
know
it's
comparing
data,
it's
going
to
compare
the
data
and
it's
going
to
say
it's
done
and
make
the
artifact.
So
we
have
our
empty
updates.
We
don't
need
to
delete
because
we're
not
deleting
agents.
That's
just
the
thing
we
do
not
do
we
do
that
manually
because
a
lot
of
risk
so
we're
going
to
parse
our
support,
teammammal.json
and
our
agents,
our
zendesk.json
and
then
we're
just
going
to
compare
it
again.
A
A
So
our
last
part
of
that
is
the
sync
and
the
sync
for
agents
is
actually
pretty
easy.
We
don't
have
to
do,
deletes
but
looks
a
lot
like
groups,
we're
syncing
this
many
we're
syncing
them
and
then
we're
done
and
again
it's
going
to
read
the
updates.json
slice
it
into
100
and
do
put
requests
to
users
update
many
using
that
data.
A
So
that's
really
all
there
is
to
the
scripting
itself.
A
This
all
works
via
ci
cd.
It
runs
once
a
day
on
a
schedule
at
midnight.
Utc
time
you
can
see,
we
got
the
images,
ruby,
3.0.1,
that's
the
one
we've
tested
and
is
working
stages.
We've
got
groups
and
agents,
we've
got
our
cache
path,
our
before
script,
print
out
the
ruby
version.
It's
a
debug
thing.
I
always
do
install
bundler
and
then
run
bundle
that
will
use
the
gem
file
to
install
the
other
gyms.
We
need
the
sync
groups.
Job
is
part
of
the
group
stage.
A
A
So
that's
pretty
much
all
there
really
is
to
that.
This
has
information
about.
If
you
needed
to
update
people
manually
in
zendesk,
we
should
avoid
doing
that
as
much
as
possible,
because
this
can
use
a
good
chunk
of
api
requests.