Slide 1

Slide 1 text

Building Your Own R2 Unit

Slide 2

Slide 2 text

serial # R2-D2

Slide 3

Slide 3 text

#emoji-bot

Slide 4

Slide 4 text

#emoji-bot

Slide 5

Slide 5 text

But I was going to go into Tosche Station to pick up some power converters… " #emoji-bot

Slide 6

Slide 6 text

a long time ago…

Slide 7

Slide 7 text

a long time ago… 1950

Slide 8

Slide 8 text

a long time ago… 1965 1950

Slide 9

Slide 9 text

a long time ago… 1965 1950

Slide 10

Slide 10 text

a long time ago…

Slide 11

Slide 11 text

a long time ago… 1995

Slide 12

Slide 12 text

a long time ago… 1995

Slide 13

Slide 13 text

a long time ago… 1995 1997

Slide 14

Slide 14 text

a long time ago… 1995 1997

Slide 15

Slide 15 text

a long time ago…

Slide 16

Slide 16 text

a long time ago… 2000

Slide 17

Slide 17 text

a long time ago… 2000 2007

Slide 18

Slide 18 text

a long time ago… 2000 2007

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

2016

Slide 21

Slide 21 text

caring module #D5e7r6

Slide 22

Slide 22 text

3Apps

Slide 23

Slide 23 text

familiar 1.

Slide 24

Slide 24 text

familiar 1. 2. < barriers

Slide 25

Slide 25 text

UBER

Slide 26

Slide 26 text

UBER

Slide 27

Slide 27 text

UBER

Slide 28

Slide 28 text

UBER

Slide 29

Slide 29 text

UBER

Slide 30

Slide 30 text

Bewhere users the are

Slide 31

Slide 31 text

‘86

Slide 32

Slide 32 text

‘86

Slide 33

Slide 33 text

‘86 ‘96

Slide 34

Slide 34 text

‘86 ‘96 ‘06

Slide 35

Slide 35 text

‘16 ‘86 ‘96 ‘06

Slide 36

Slide 36 text

80 $ M slack fund

Slide 37

Slide 37 text

80 $ M slack fund

Slide 38

Slide 38 text

speaking module #S40926

Slide 39

Slide 39 text

UI the design

Slide 40

Slide 40 text

Can you schedule a meeting for tomorrow with Jim and Tim? Which Jim do you want me to schedule a meeting with? 1. Jim F. 2. Jim P. Sure. It looks like the afternoon is best. Do you want me to schedule this for then? Meeting invite went out for 2PM tomorrow to everyone. I will follow up to confirm everyone is booked. Ok. There is no more free time tomorrow. Do you want me to try for Wednesday? Multiple contacts "Yes" "No"

Slide 41

Slide 41 text

Design Challenges

Slide 42

Slide 42 text

Discoverability

Slide 43

Slide 43 text

Discoverability Are you ready to have that meeting? You can reply with "yes" or "no". "yes"

Slide 44

Slide 44 text

Discoverability

Slide 45

Slide 45 text

Discoverability Meeting scheduled! Did you know you can reschedule by just saying "reschedule meeting with Dave"?

Slide 46

Slide 46 text

Validation

Slide 47

Slide 47 text

Validation Andy wants to meet with you today at 2PM. Are you available? "blerg"

Slide 48

Slide 48 text

Validation "blerg"

Slide 49

Slide 49 text

Validation I'm sorry, "blerg" is not an answer. You can say "yes" or "no". Are you available to meet with Andy today at 2PM? "blerg"

Slide 50

Slide 50 text

Selection

Slide 51

Slide 51 text

Selection Where do you want to meet tonight with MacKenzie? 1. Coffee Shop 2. Restaurant for dinner 3. Local bar "1"

Slide 52

Slide 52 text

Selection "1"

Slide 53

Slide 53 text

Selection Ok. Which coffee shop? 1. Starbucks on Central 2. Cup 'o Joe Downtown "1"

Slide 54

Slide 54 text

Feedback

Slide 55

Slide 55 text

Feedback No one in your meeting is available on Friday. Would you like me to ask them anyway? R2 is typing …

Slide 56

Slide 56 text

Best Practices

Slide 57

Slide 57 text

Gender Neutral

Slide 58

Slide 58 text

Gender Neutral "are you a boy or a girl?" Neither. Those X-Wing pods are skinny. I would not fit with any extra parts.

Slide 59

Slide 59 text

Beer Test

Slide 60

Slide 60 text

Beer Test Just keep me away from those Jawas and we'll be cool. "you are my best friend"

Slide 61

Slide 61 text

Different Responses

Slide 62

Slide 62 text

Different Responses "how come you had rocket feet early on but then you didn't after episode 3?" They were using potatoes for special effects in the first 3. How would they pull off rocket feet?

Slide 63

Slide 63 text

Different Responses "Yeah, but how do you explain Jabba the Hutt in the special edition?"

Slide 64

Slide 64 text

Different Responses "Yeah, but how do you explain Jabba the Hutt in the special edition?" They were using potatoes for special effects in the first 3. How would they pull off rocket feet?

Slide 65

Slide 65 text

Use Their Surroundings

Slide 66

Slide 66 text

Use Their Surroundings "Dagobah did not look like a pleasant place!" It's 70 degrees in February where you're at. Global warming is affecting all systems.

Slide 67

Slide 67 text

Fallback

Slide 68

Slide 68 text

Fallback "Can you blerg?" I'm sorry, that oil bath got into some of my circuits. What were you saying?

Slide 69

Slide 69 text

power module #63wrqy

Slide 70

Slide 70 text

power module #63wrqy

Slide 71

Slide 71 text

speaking module #S40926

Slide 72

Slide 72 text

speaking module #S40926

Slide 73

Slide 73 text

listen module #aaYg5

Slide 74

Slide 74 text

listen module #aaYg5

Slide 75

Slide 75 text

process module #9862sw

Slide 76

Slide 76 text

process module #9862sw

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

Slack App Directory

Slide 80

Slide 80 text

Slack App Directory

Slide 81

Slide 81 text

Add to Slack

Slide 82

Slide 82 text

Add to Slack

Slide 83

Slide 83 text

Authorize app

Slide 84

Slide 84 text

Authorize app

Slide 85

Slide 85 text

Authorize app

Slide 86

Slide 86 text

new bot user

Slide 87

Slide 87 text

new bot user

Slide 88

Slide 88 text

chat!

Slide 89

Slide 89 text

power module #63wrqy

Slide 90

Slide 90 text

Create Slack App http://api.slack.com/applications/new

Slide 91

Slide 91 text

Create Slack App http://api.slack.com/applications/new

Slide 92

Slide 92 text

ngrok ngrok http -subdomain=my-slack-bot 5000

Slide 93

Slide 93 text

Create Slack App http://api.slack.com/applications/new

Slide 94

Slide 94 text

Web Component

Slide 95

Slide 95 text

Web Component

Slide 96

Slide 96 text

Web Component Add to Slack

Slide 97

Slide 97 text

OAuth # Gemfile #… gem "omniauth-slack" #…

Slide 98

Slide 98 text

OAuth #config/initializers/omniauth.rb Rails.application.config.middleware.use OmniAuth::Builder do provider :slack, ENV["SLACK_CLIENT_ID"], ENV["SLACK_SECRET"], scope: "bot,identify" end

Slide 99

Slide 99 text

OAuth #config/initializers/omniauth.rb Rails.application.config.middleware.use OmniAuth::Builder do provider :slack, ENV["SLACK_CLIENT_ID"], ENV["SLACK_SECRET"], scope: "bot,identify" end

Slide 100

Slide 100 text

OAuth #config/initializers/omniauth.rb Rails.application.config.middleware.use OmniAuth::Builder do provider :slack, ENV["SLACK_CLIENT_ID"], ENV["SLACK_SECRET"], scope: "bot,identify" end

Slide 101

Slide 101 text

routes # config/routes.rb Rails.application.routes.draw do get "/auth/:provider/callback", to: "sessions#create" # … end

Slide 102

Slide 102 text

controller # app/controllers/sessions_controller.rb class SessionsController < ApplicationController def create auth = request.env["omniauth.auth"] end end

Slide 103

Slide 103 text

oauth response {"provider"=>"slack", "uid"=>"UXXXXXXX", "info"=> {"nickname"=>"jwright", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX", "name"=>nil, "email"=>nil, "first_name"=>nil, # … }, "credentials"=> {"token"=>"xoxp-XXXXX-XXXXXXX-XXXXXX", "expires"=>false}, "extra"=> {"raw_info"=> {"ok"=>true, "url"=>"https://bf.slack.com/", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX"}, "web_hook_info"=>{}, "bot_info"=> {"bot_user_id"=>"UXXXXXX", "bot_access_token"=>"xoxb-XXXXXX-XXXXXXXX"}}}}

Slide 104

Slide 104 text

oauth response {"provider"=>"slack", "uid"=>"UXXXXXXX", "info"=> {"nickname"=>"jwright", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX", "name"=>nil, "email"=>nil, "first_name"=>nil, # … }, "credentials"=> {"token"=>"xoxp-XXXXX-XXXXXXX-XXXXXX", "expires"=>false}, "extra"=> {"raw_info"=> {"ok"=>true, "url"=>"https://bf.slack.com/", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX"}, "web_hook_info"=>{}, "bot_info"=> {"bot_user_id"=>"UXXXXXX", "bot_access_token"=>"xoxb-XXXXXX-XXXXXXXX"}}}}

Slide 105

Slide 105 text

oauth response {"provider"=>"slack", "uid"=>"UXXXXXXX", "info"=> {"nickname"=>"jwright", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX", "name"=>nil, "email"=>nil, "first_name"=>nil, # … }, "credentials"=> {"token"=>"xoxp-XXXXX-XXXXXXX-XXXXXX", "expires"=>false}, "extra"=> {"raw_info"=> {"ok"=>true, "url"=>"https://bf.slack.com/", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX"}, "web_hook_info"=>{}, "bot_info"=> {"bot_user_id"=>"UXXXXXX", "bot_access_token"=>"xoxb-XXXXXX-XXXXXXXX"}}}}

Slide 106

Slide 106 text

oauth response {"provider"=>"slack", "uid"=>"UXXXXXXX", "info"=> {"nickname"=>"jwright", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX", "name"=>nil, "email"=>nil, "first_name"=>nil, # … }, "credentials"=> {"token"=>"xoxp-XXXXX-XXXXXXX-XXXXXX", "expires"=>false}, "extra"=> {"raw_info"=> {"ok"=>true, "url"=>"https://bf.slack.com/", "team"=>"Brilliant Fantastic", "user"=>"jwright", "team_id"=>"TXXXXXX", "user_id"=>"UXXXXXX"}, "web_hook_info"=>{}, "bot_info"=> {"bot_user_id"=>"UXXXXXX", "bot_access_token"=>"xoxb-XXXXXX-XXXXXXXX"}}}}

Slide 107

Slide 107 text

Store Information # app/controllers/sessions_controller.rb class SessionsController < ApplicationController def create auth = request.env["omniauth.auth"] team = Team.create_from_auth auth user = User.create_from_auth auth, team bot = Bot.create_from_auth auth, team end end

Slide 108

Slide 108 text

Store Information # db/schema.rb create_table "bots", force: :cascade do |t| t.string "bot_id" t.string "access_token" t.integer "team_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["team_id"], name: "index_bots_on_team_id" end create_table "teams", force: :cascade do |t| t.string "access_token" t.string "domain" t.string "team_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "users", force: :cascade do |t| t.string "user_id" t.integer "team_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end

Slide 109

Slide 109 text

Start Bot # Gemfile #… gem "slack-ruby-client" #…

Slide 110

Slide 110 text

Start Bot EM.next_tick do client = Slack::RealTime::Client.new(token: bot.access_token) begin client.start_async client.on(:close) do restart end rescue StandardError => e # TODO: handle slew of errors here end end * over simplification http://api.slack.com/rtm

Slide 111

Slide 111 text

speaking module #S40926

Slide 112

Slide 112 text

Introduce Bot client = Slack::Web::Client.new(token: bot.access_token) response = client.im_open(user_id: user.user_id) client.chat_postMessage(channel: response.channel.id, text: "Hello there") http://api.slack.com/chat.postMessage

Slide 113

Slide 113 text

listen module #aaYg5

Slide 114

Slide 114 text

Event listening client = Slack::RealTime::Client.new(token: bot.access_token) client.on :message do |data| case data.text when /hello/ then client.web_client.chat_postMessage channel: data.channel, text: "Hi!" when /not now/ then client.web_client.chat_postMessage channel: data.channel, text: "Goodbye" end end http://api.slack.com/events

Slide 115

Slide 115 text

process module #9862sw

Slide 116

Slide 116 text

behaviors client = Slack::RealTime::Client.new(token: bot.access_token) client.on :message do |data| case data.text when /hello/ then #… when /not now/ then #… when did_something(data.text) then #… when did_something_else(data.text) then #… end end

Slide 117

Slide 117 text

behaviors class Bot < Slack::RealTime::Client include Behaviors::IntroducesSelf include Behaviors::RespondsToInsult include Behaviors::RespondsToWeatherCommand #… end

Slide 118

Slide 118 text

Natural language processing

Slide 119

Slide 119 text

Natural language processing Is BB8 ready to go?

Slide 120

Slide 120 text

Natural language processing Is BB8 ready to go? intent: charge_status

Slide 121

Slide 121 text

Natural language processing Is BB8 ready to go? intent: entities: charge_status target: "BB8" status: "ready"

Slide 122

Slide 122 text

Natural language processing Is BB8 ready to go? intent: entities: confidence: charge_status target: "BB8" status: "ready" 0.82

Slide 123

Slide 123 text

nlp as a service

Slide 124

Slide 124 text

nlp as a service

Slide 125

Slide 125 text

nlp as a service require "wit" response = Wit.text_query("Is BB8 ready to go?", ENV["WIT_ACCESS_TOKEN"]) bot.process_intent(response) http://api.wit.ai/message

Slide 126

Slide 126 text

nlp as a service "outcomes" : [ { "_text" : "Is BB8 ready to go?", "intent" : "charge_status", "entities" : { "target" : [ { "value" : "BB8" } ], "status" : [ { "value" : "ready" } ], }, "confidence" : 0.82 } ]

Slide 127

Slide 127 text

go and build bots

Slide 128

Slide 128 text

Thank you for learning about how to build me. go and build bots

Slide 129

Slide 129 text

go and build bots

Slide 130

Slide 130 text

I know I'm not as difficult to build as that pain in the ass gold-plated primadonna. go and build bots

Slide 131

Slide 131 text

go and build bots

Slide 132

Slide 132 text

…and it took Anakin 7 years to build that useless translator. go and build bots

Slide 133

Slide 133 text

Gotcha bot http://github.com/jwright/gotcha-bot

Slide 134

Slide 134 text

Tatsu http://tatsu.io

Slide 135

Slide 135 text

Tatsu http://tatsu.io

Slide 136

Slide 136 text

Resources http://dev4slack.xoxco.com

Slide 137

Slide 137 text

Resources http://api.slack.com

Slide 138

Slide 138 text

Resources http://twitter.com/slackapi

Slide 139

Slide 139 text

Resources http://medium.com/@slackapi

Slide 140

Slide 140 text

Resources http://botweekly.com

Slide 141

Slide 141 text

@jwright

Slide 142

Slide 142 text

Thanks for listening… …to a human? @jwright