I want to tell you a quick story about our first speaker. He is an insurance industry legend. He taught me more about this space than anyone else ever has. When I was 16 years old, I was supposed to go to Apple Marketing in Rogersville, Missouri. I was supposed to go to work on a Saturday from 4 to 10. I was 16. I was throwing up. I didn't feel well. It's about 3,330. I go to this man, my dad. And I say, hey, I don't feel like going to work today. Right? Whoever woke up, you're like, dude, I don't feel like going to work today. I don't feel like showing up. I don't feel like being my best self. Me too. And I tell him, hey, I'm throwing up. I don't feel well. I don't think I'm going to go to work today.  But you know what I would do. As of April 1st, here in a few weeks, he will have been in the insurance industry for 31 years. The dude shows up. I've learned from not only my father, but also an absolutely incredible mother.  So please help me welcome. The number one mentor in my life, the number one do to the insurance industry, and my best friend to jump out and kick it off for day two. Please welcome my father, Mr. Brian Askins. Hello, hey, this is Brian Askins with Secure Insurance Group. First of all, Cody, I want to thank you for that introduction.  Today I want to really talk to you about how to build an agency, how to build a successful team. And just to kind of give you some ideas here, I'm going to kind of walk through kind of what I've done over my career.  Make the absolute best of it.  We all only get one here on earth to do whatever we want to do in life, but make the absolute best of it. Don't let anyone or anything stand in your way of the dreams that you have. And you know, all I'm trying to do is encourage you to do in this talk today is to bet on yourself. I don't think, I don't think often enough we bet on ourselves. And so I'm just, I'm encouraging you today to bet on yourself. Don't take the easy route again, bet on yourself. There's so many times that we can take the easy route and it's easy and you know, there's no, it's just an easy route. But I'm just asking you today to bet on yourself and always remember, if you don't quit, you can't fail. Simply don't quit. At the end of the day, you'll be glad of what you built because you build something that you'll be proud of and something you can leave as a legacy to your love ones. And so again, today the focus is, you know, if you don't quit, you cannot fail. And I'm just asking you to bet on yourself. So let me tell you a bit about me and what my career has been. I started the insurance business as Cody mentioned, April of 1990. I started with a small little company called Reliable Life and I was with them from 90 to 97. I ran a debit route to where you go around and you collect monthly premium payments from individuals and I collected about 450 homes a month. And in 1991, I was fortunate enough to be the rookie of the year for Reliable Life and I set an all-time sales, a life sales record at that time in 1991. I'm sure it's been broken since, but in 1991 I did hold the all-time life sales record for Reliable Life. And then in April of 1997, I went to work for Mutual of Omaha. I was an agent for them for a couple of years. I'm sorry for a few months, I apologize. And then District Sales Manager for a few years. And then I became a general manager with them in 2010, I'm sorry, in 2000. And then 2010, I became the number one GM at Mutual of Omaha. And what people asked me, how did you take your agency from rank 47th in the company to number one in less than a 10-year period? And it all goes back to I surrounded myself with the right people, had tremendous, tremendous, tremendous people that I surrounded myself with. And so in this business, it's all about the people you surround yourself with. And so that's how we were able to become the number one agency at Mutual of Omaha. It's just the people that I surrounded myself with. And then in 2014, February of 2014, I started Secure Insurance Group. So Secure has been going now for just a little over seven years. And with Secure, it was probably the biggest bet on myself I've ever done. And it's been the one that's paid off the most. And there's so many people, they're just afraid to bet on themselves. And so again, just want to encourage you to do that. So let's start with Secure Insurance Group. Let me tell you a little bit about Secure Insurance Group and what, when I started Secure Insurance Group, I started with four agents. And Cody was one of those four. And we currently have nearly about 750 independent agents across the US now in seven years. And there are many of you listening today that there's no question about many of you listening today. They're much, much, much more talented than I am. You just have it bet on yourself. Your talent is greater than my talent. I'm very confident of that. And I've just been successful because again, like Cody mentioned earlier, I show up every single day. I don't let anyone outwork me. And I bet on myself. And I surround myself with the right people. And so I'm just asking you about yourself because it's definitely, definitely time. Some of you on this today, you've thought about doing certain things in the interest industry. You've thought about doing this or that. But you're scared and you keep talking yourself out of it because you don't want to bet on yourself. And again, I'm hoping after today, some of you will take that chance and you'll bet on yourself. So let me tell you a little bit about building an agency. This is some things that I've done to help build an agency. And I'm going to tell you what's kind of important. So the most important thing to me, period, is culture. And culture kind of goes back to, I think that the person who is, everyone's looking up to should be the hardest working person in the agency. And whether I was with Reliable Life, was with Mutual Law Hall, and our security insurance group. And that's been my three careers, or three companies I've worked for in 31 years is I truly believe I've been the hardest working person in any of those spots I've been in. And it's something that's important to me. I won't, you know, because I think you gain a lot of respect.  And if you surround yourself with a lot of people, talented individuals like I have, and you're the hardest working person in the office, they kind of, in the agency, they kind of see that and they step their game up. But nothing is more important than culture. Culture is absolutely the most important thing that there is. Hire people that fit well in your culture. Again, when you're hiring, it's all about do they fit in your culture. Because they could be, you know, an unbelievable individual, personnel, or as far as a talent and all that in production. But they don't fit well in your culture, they could be more harm than good. So it's all about the culture. If you ever have issues in your agency, handle those issues quickly, don't let those issues to where you, you may have a situation that starts out small. But really, really quick, it turns very large. Because it just continues to faster. Deal with whatever issues there are quickly so they don't, they don't grow. Because small issues are easy to handle. It's all about communication. And but when that, when those issues are just kind of swept under the rug and hoping they go away, they keep getting bigger and bigger each and every day. And then sooner or later, they're very large issues. Don't allow drama or negativity. Again, that can kill the culture. You know, we've all heard about the bad apple and the, and the, and the basket. It can run all the other apples. And it's very, very true. So surround yourself with people who are no drama, no negativity. They're positive, they're talented. They're excited about, about the opportunity that they have. So culture is number one. I could talk hours and hours on culture. Culture is absolutely the first thing I look for in interview. I spend, you know, 20, 25 minutes at least just talking about the culture, what we built and how we're not going to let someone come in and destroy it.  I don't care what, what I'm hiring an individual to do. If they're employee secure, 20, 25 minutes of the first interview is about culture. Because I want to set the stage at that time. The second interview, we talk again about culture. The third interview, we talk about culture. The first day on the job, we talk about culture again. So now let's talk about employee staff. Obviously, in order to grow your business, you can only be so big by yourself.  You can only grow so big by yourself.  You want to start instead of adding, you want to start multiplying. That's where tremendous great employees come into the picture at. And so regardless of what you have to pay the employees, you know, if they're great, they're going to more than pay for themselves, probably three, four, five, 10-fold if they're great employees, they'll pay for themselves in a big time way. One of the things about employees I always try to tell people is trust them to do their job, you know, trust your employees to do their job. Encourage them to be creative. You want employees that are creative. You know, the more that you get an employee involved, then the more they're going to be excited about the opportunity. They're going to be excited to come to work. They're going to be excited about everything that they have. And so listen to your employees' ideas. Some of the best ideas that we have come from, you know, our employees. You know, majority of our great ideas have come from our employees. I have an open-door policy. So if they've got an issue, they come to you. And again, that's something where, you know, the issues are handled quickly and it's all about communication. They're, again, communication is the key to any relationship. I don't care if it's a work relationship, a marriage relationship. I don't care what type of relationship, a friendship. I don't care what it is. Communication is the key to a long-lasting, productive relationship, regardless. Don't micromanage. I don't think you'd be on this call on today's event. Would say, you know, raise your hand, I love being micromanaged. I just love it.  You know, no one wants, I don't want to be micromanaged. I can't imagine that you'd want to be micromanaged.  Set the expectations, give them the tools and resources to be successful and let them do their job. Now you want to monitor and measure from, you know, make sure that, you know, they're the right person, they're getting the job accomplished. You know, I'm not saying that, but I'm saying to micromanagement, that drives people insane, it drives them away. And so that's why there's so much turnover and employee status and so forth is people just don't want to work for a micromanager. But make sure they're on the right seat on the bus. And the right seat on the bus, you know, you may have an individual that is, and I can tell you several examples. I've got a lady right now, I'll just give you one real quick. I've got a lady right now that to where she was a Medicare, I'm sorry, she was a life specialist for me. She was my personal assistant for life insurance. And she was doing a good job, not a great job, but I could tell she just wasn't enjoying it. And some of the things I was having to do and so anyway, so we had a role come available in the Medicare as a Medicare specialist. And we have moved her to that role and we've added some extra responsibilities on top of that. And now this lady is thriving. She is, she's head of our PR for, you know, she calls all her clients for their birthdays and all kinds of things of that nature and I'll kind of walk through some of those in a few minutes. But she is just absolutely thriving, one of the best employees we have now. And we just, we got her on the right seat on the bus. Make it fun, you know, like one of the things that she does, she's kind of our PR person for within our agency. She is, you know, she has birthdays. So every time that, you know, once a month, she does a birthday cake for all of our employees whose birthdays that month. She does team building events. We do those every quarter. And so our next one is St. Patrick's Day. But great employees pay huge dividends and I could talk all day long about great employees because that's the key to the success of great employees. Let's talk just for a split second here about customer service. And again, this goes without saying and I know I've been on this, every on this call, you know, I'm sure you do a tremendous, tremendous job of customer service and I'm sure your staff does a tremendous job. But the biggest thing is, is to teach your staff to go above and beyond for every client. Not just meet the needs of the clients, but go above and beyond. You know, let the client know they're the most important person in the world on that phone call, listen to the clients. What seems small to us is it can be huge to our clients. And so treat every time that the client has a need, a request, whatever it is, if it's possible to make it, to do that, do that. And I promise you those individuals will send lots of referrals to your office, to your agency, and they will absolutely love doing business with you and they'll tell others about it. People tell others whether it's good or bad about the experiences that they have. And so obviously we want those things to be positive. So let's talk about client retention. And so the client retention is just all about setting yourself apart.  Client retention is about the education process.   You educate individuals and let them make an informed decision, because obviously the best way to make a tremendous, a great decision is to be well informed. And so be an educator and your retention will just be 95% and above if you're an educator. But set yourself apart. And so some things that we do to help set ourselves apart with our clients is we do quarterly newsletter to every client. And so it's kind of funny, we just did one and on this last one, we had a caramel pie recipe in there and we've had several clients call and talk about how they made the caramel pie was delicious and they get some of them give us ideas to even add this to the ingredients, et cetera. So the caramel pie, we had to where, hey, find the logo, the secure logo. And if whoever found it called in and we put them in a drawing and we drew out, I think it was 10, 20 file or gift cards. And so, and we had dozens and dozens of dozens of clients calling in. Hey, I found the secure logo, et cetera. So it got the clients kind of involved. We do a lot of Medicare business, obviously. A lot of life annuities, other business, but Medicare is probably our number one. But thank you cards, birthday cards. So we do, every time a person buys a policy from us, we send them an email and it's a thank you email, but it's asking us, asking them to also leave us a review on Google. And so that has been tremendous for us. And then the birthday reminders, we send out birthday cards, but also we have a lady in our office that calls every client on their birthday and unless their birthdays are Saturdays and Sundays, if that's the case, they call them on Friday. She calls every client on their birthday and just wishes them a happy birthday.  We have a client appreciation breakfast once a year, right before AEP. And so in that, there's no sales pitch. Just simply thanking them for their business.  And towards last event, we had around 500 clients at this event, it cost us a lot of money, but we had, we fed them breakfast at door prizes, giveaways, bingo, trivia, but there was no sales pitches. At the end of the meeting, we just talked about how AEP is upcoming and we, you know, office will review everybody's plans and make sure they're on the right plans. And we had 10 staff members out front into where people got in line and set appointments up for their annual reviews. So there's so many different things you can do. So just kind of think outside the box and, you know, an individual thinks outside the box and is always thinking of creative new ways to do things is obviously that person is worth their weight and go. Let's talk just a second about recruiting. So obviously recruiting is very, very, very important. And so in recruiting, there's several things we can do on recruit or that we do currently on recruiting. We get a license list from various Department of Interances. And most of the time, those Department of Interances will send you that license list for no charge. And those are people who are newly getting licensed or they just added a new, you know, some type of new license to their already existing licenses, a new line of authority. But for most of them, it's brand new individuals.  And so they just need, they need to be put in the right situation. And so, you know, you can contact those individuals. You can contact those individuals by mail, by phone, by email, you know, et cetera. So obviously Google recruiting ads, Facebook recruiting ads, your current agents, you know, what other proxies do they have with other FMOs or IMOs?  And so we contact those to see, you know, hey, can we beat the comp levels? Can, you know, whether the support help, can we give you to help in that arena? So current agents, don't ever forget about your current agents because those are the individuals already doing the business for you. Referrals from existing agents. When you start getting referrals from existing agents, and that's where we've gotten a large, large, large majority of our current agents is referrals from existing agents. That's where you know you're doing something right. Now we can always continue to improve and we try to improve every day, but that's when you know you can do something right is when your existing agents refer you, refer you. And also recruiting webinars. We did a recruiting webinar two weeks ago. We had a hundred and I think it was like 118, 119 register event, 40 something attended event. And so great events to where opportunities for you to get a chance to kind of tell your story to multiple people. So recruiting webinars, all kinds of opportunities there. So let's talk about the opportunities that you might recruit to. We recruit to two different ones and this might give you some ideas. And most of you are probably already doing this, but I'll just kind of give you some ideas just in case. One of the opportunities is we recruited a lot of, we started an LOA program, which is a licensed only agent program. And that has really flourished and we're going to continue to expand that, the licensed only agent program. That's a program that we help, they can help us service our existing clients there in AP because obviously the larger and larger you get it becomes more difficult. We offer those individuals incentive trips and contest, but for those individuals, here's kind of what we do for those individuals and here's how kind of we structure this. We pay for their marketing support. You know, we give them all the training support, we pay for all their marketing, we pay for all their office space. So there's no monies out of their pockets. We also can, you know, some of them we've paid a salary to kind of depends we have a couple of different options, but those individuals, their commissions are paid to secure and those and secure then pays those individuals. So secure is basically splitting commissions with them. The street commissions are secure, obviously keeps the overrides, but we're splitting street commissions. But these individuals, they need marketing training. They need lots of training, lots of marketing.  And we pay for all the expenses for them. And in these individuals, we just had an agent, one of our LOA agents in the month of February produced 39 applications. And they all produced over 20, but one kind of went above and beyond. He did 39 this past month as an LOA. And these are individuals that, you know, that he met either at a Medicare seminar. We do lots of lead drops for those individuals, Medicare lead drops, you know, et cetera. So one other thing too, is obviously there's independent agents and those are individuals that they're looking for carriers, products, commissions, support, training, marketing, prospecting, all those type things. And those individuals, you know, they're typically most of the time paying for the majority of their own or if not all of their own marketing and prospecting. But obviously those individuals are receiving extremely, extremely high comp levels. And we'll talk a few more, we'll talk a bit about that here in a few minutes.  They want to be a part of something. And so they, you know, don't want to be just left on an island all the time and, you know, recruit them and then never, never speak to them again. So let's talk about training for a second. And again, this is where you just teach your agents to go above and beyond. And that's how you get referrals, is to go above and beyond. People refer people that they know they trust, people that's brought extreme value to them. And that's, and do things other agents are willing to do. And I'll just kind of give you a couple of ideas here today. Couple of ideas is, you know, like when a person needs to be enrolled in Social Security or Medicare, we do the enrolling. We will enroll them in Social Security, we'll enroll them in Medicare. We don't want to send them to the Social Security office or make them, you know, call in and, you know, because we can do that, we can assist them and do that in just a few minutes. It's very, very, very quick and easy. Same thing with Medicare. If they need to be enrolled in Medicare, you know, we take care of it for them if they need, if they've already got part A, but then you part B, we get them the applications, we do the, you know, online aromats, you know, et cetera. So lots of things that we can do for these individuals to help them if they qualify for, you know, Medicaid or extra help, you know, we help them with that. We help sign them up for that because we don't want them, we don't want to send them down just to the Medicaid office. We, you know, we want them, we want to be a resource to them. So anytime they need anything whatsoever, they contact us. And so once we've helped them in individuals on those type things, you know, obviously they become referral machines for us because how you need social security, this is what, you know, Brian can help you with that or whoever the agent is can help you with that. Train your agents on all new carriers, products. You have the best products on the market, but if you don't know about it, they can't sell it. So, you know, we have, obviously we sell a lot of, we sell it every product that a person can dream of naming and we also have the most competitive cares in the industry and I'm sure, you know, most of y'all have the same situation. You have the most competitive cares in the industry and the most competitive products where you never get beat on price. You know, we're never getting beat on price period or underwriting at all. If it's a way to place that case, you know, we're gonna have a carrier product to do that. But make sure your agents are aware of all the practice services you offer. I was on the phone with an agent this morning and this individual has pretty much done just Medicare. Got a little bit into final expense, but doesn't offer the hospital identity plans when he sells Medicare. Advantage plans doesn't offer the heart attack stroke plans, doesn't offer dental vision hearing plans, doesn't offer, you know, that's just a little bit in the final expense, but not much, been very limited. And so just kind of walking through some things of telling them all the other opportunities that are out there and how much it would drastically increase his income. And this agent was obviously extremely excited when he got the phone and that's what it's all about is getting his, you know, letting people know what you do because if you let people know what you do, then it'll snowball for you. Let's talk about carriers just for a split second here. Make sure your agents have the most competitive carriers, which we kind of mentioned that already, you know, to where again, you'll never get beat on price underwriting, you know, et cetera. The more competitive you are, the more allows you to cross sell. And so that's why that I want the most competitive carriers. You know, a lot of times people have a certain budget, maybe $100 a month, maybe $200 a month, maybe, you know, whatever per month and a budget. And so the more competitive you are, the more proxies you're able to get in that house and fill the needs that that particular client has. So let's talk about products just for a second. And again, we talked about this just briefly, but cross selling is so important and 40%, we have a 40% cross selling rate for hospital identity plans when we sell Medicare vanish plans.  So lots of opportunities there. One of the things that, the most difficult thing to do is to get in front of people. And so while we're in front of people, we might as well take advantage of it. Make sure that they know all the product and services that we do. Easiest person to sell something to is someone you've already, it's already bought from you. So one thing I try to teach our agents is when you're in front of a client, make sure the client knows all the product and services you offer. You may be there to sell Medicare, but have you a little sheet that shows all the product and services you offer? And so as you say, Mrs. Jones, today we took care of your Medicare. But let me show you the other product and services we offer. Mrs. Jones, do you have any life insurance? And let her talk for a second. She'll tell you, yay or nay, and there's a good chance you might improve your situation on whatever life insurance she currently has. Mrs. Jones, we do a lot of annuities which, you know, save money accounts. Do you have any money in CDs or money market in the market or annuities or whatever it may be? Any 401ks. And they'll kind of tell you. So just kind of walk through all the different product and services you offer and you'll be completely surprised to where the client will say, you know, you have bought a life insurance last week or, you know, I've had life insurance for years and when I've got term it's about to run out. All kinds of scenarios. So one thing I'll say on that and we'll move to the next topic here is on the cross-selling, you may go in there and sell a Medicare Advantage or a medical supplement or one product. And then, you know, each year you may go back to review it. I can promise you this, those individuals are buying those other product and services from other agents because those other agents are making them aware that they had those product and services. So don't kid yourself that they're not buying product and services from one else because they are. But because all you're doing is maximize your earning potential while you're in there, you're filling needs for the client, increases persistency, the more, you know, Limbers always told us for years and years which is a true stat. The more policy you have in your house the less likely they are to move their business. And so now we've talked about several things here. Now let's talk about commissions. And this is one thing that's kind of important and as you're recruiting. Now some people may disagree with a little bit about what I'm gonna say but, and there's different ways to go about this. So I'm not saying I'm right, I'm wrong, but this is my true opinion and my true belief on commissions. I wanna pay extremely high commissions. I want SIG, I wanna make sure that Secure Insurance Group puts all their agents at extremely high levels. And the reason being is because I do not wanna have that commission conversation again in the future. I do not want an agent to come to me and say, Brian you put me at 100% with this final expense carrier and this person just offered me 110 or 120 or 130. I don't wanna have those conversations. That's why we put, because if I put you at, say that I put you at 100 and someone else offers you 120 and then you came back to me and I said, well I can match that 120. Where's the credibility there? Where's the, because that agent's gonna, if I were the person I'd be thinking, why didn't we do that first? If you could do that, why didn't we do it first? Why do I have to threaten to leave you before that happens? And so I just don't like having the commission conversation. I want that full trust with every agent. Another reason is, is others are always trying to recruit your agents and obviously we're all recruiting. All the FMO's across the US are always recruiting and so if you pay them high commissions and you do all the things, we've talked about the support, the marketing prospecting support, et cetera. Your chance of you losing an agent are very, very slim. And commissions are extremely important again. And the reason being is because it allows them to hire more staff. So if you have an agent that's very successful, the more money they make, the more money they got to spend on their, on them. You may have an agent that, once they got to 500 Medicare clients needs an assistant. Well, if they're making tremendous amount of commissions, then all of a sudden they have the money there to do so. So it helps them hire support staff. It allows them to pay their quality staff even better. Because if you don't want to pay minimum wage for it then you probably not get the quality you're looking for. So obviously the more money you have at your disposal, the higher the quality of individuals you're gonna be able to bring to your team. Hey, if you enjoyed this, I got another one you're gonna love. It's right there, click on it, see ya. I was, we were talking earlier about how like there's more to what we do than just the money. You know, like there's riches in other ways. And that's not a,


Hey there, so I'm Josh Adams from ElixirCypx and Icetope11. I'm Robbie Clements, and I've watched ElixirCypx, and I'm from Center Source in Nashville, Tennessee. And we're going to talk today about building a visual programming language. In this case, it's for building chatbots. In a more general sense, it's about building a business rules engine. So we chose to do it in the domain of chatbots because it's an easier domain to get your head around, and it has not a lot of complexity. Giving talks is always a little bit stressful, we found it useful to do breathing exercises. So we wanted to start out by sharing some that we found helpful and I promise this is not a soft talk, we don't do that, there's lots of code, just bear with us. So just go ahead and just clear your mind and try to repeat the exercise you see on the slides. So first, just breathe in and out really deeply for a bit, and then try to breathe just a bit more rapidly. And then finally, just exhale as hard as you possibly can.  Okay, dope. So the structure of our talk closely resembles the structure of our project. So the concept is being able to change runtime behavior of your system through a visual programming language. Generally these are called business rules engines or production systems. The AST and its representation, this is a description of the types of programs we support building with this particular language. The compiler which turns an AST into a function, there's the front end which is an angular JS based browser application that lets you review and modify rules and store them in the back end. There's the API which is the component that allows storing and modifying the rules and it interfaces with the system that ultimately these rules are being run against. And then there's the demo where you decide to ask for our autographs. Okay, so to start things off, we'll just discuss this at a high level concept. At a high level it's just a business rules engine. So why do people use a business rules engine? Well, typically the idea is that your application is one relatively static concept and there's some configuration that can be filled with to make it behave differently. This configuration is the business logic. This way the application doesn't need to be changed or redeployed just to support tweaks to the business logic. And this helps support the core idea that things that change at different paces, they should be separate things. So that business logic, it should cover a bunch of things like the percentage of sales tax to charge based on the location of a purchase. Additional questions necessary to gather more information to make better decisions later on in an application. And suggestions of classification of a given domain in any based on some of its attributes. So an example of this one is we're doing a project where our client needs to categorize doctor visits and support ICD-10 medical coding based on the information they know about the doctor visit. So sometimes the person that's writing the rule knows that in this case, if we had like these other two questions answered, we would know enough information to make a suggestion. So they can write a rule that says, okay, if this is the case, then return a couple of questions we need asked. In other cases, they might know everything but there's two or three suggestions that they can make. And so they might want to build a rule that says, okay, in this case, I know to code it this way. And over time, business analysts can categorize more and more visits correctly. So without changing the application, the application gets better, right? So what is a visual programming language? So here's a screenshot of Scratch. This is a program built in Scratch. Scratch is easily the most popular visual programming language. I'm sure most people think of it when someone says this. Kids use this to make games without knowing how to program, except for it really is knowing how to program, right? This is a good way to learn it. Here's an example of a rules engine built in exactly the style that we're working on that's a bit further along. So it's not quite as pretty as Scratch yet and you can't really see it so easily on this screen with that washout. But this is the spiritual successor to the Angular app that we're showing in this talk and sort of the conceptual successor to the electric piece. So one category of rules engines involves non-programmers changing the runtime behavior of the system. Well, we built a custom visual programming language that allows you to build out the chatbots easily and modify their behavior at runtime without knowing how to program. So it's also impossible to construct a program without syntax errors in our program, which is a nice additional feature. So to support this, we define a custom AST that represents the rules where rules are really just tiny programs. They either return something or they don't. Okay, so we've mentioned the word AST a couple of times already and when I've talked about this with people, sometimes they ask me, what is that? So like all good programmers, you might go to Google to find out. So Google's great. Let's just click on that first result here. Yep. All right, so AST stands for Aspartate Amenote Transference, which is, right. So I think this is wrong. So we'll try again. Maybe it's the second result. Okay, so it's an abstract syntax tree. So this makes more sense, right? So here we have a tree that represents a program. You can't see my pretty line so well. That represents the structure of a program in an orderly fashion. So this might be the result of parsing a text-based language, right? In our case, since we're a visual programming language, you're just actually directly manipulating the AST of the program when you're building your rules. So here's an example that says, if the variable input contains the string table flip, then evaluate a response expression with the input awesome guy flipping a table out of joy. Anyway, so to actually run these rules, we go through a few transformation steps, which isn't that surprising since that's all that programming really is, right? Transforming inputs and outputs. So in our case, our input at the beginning is some JSON that is a slightly more verbose version of our idealized AST, and then we transform that into our AST. Then we transform that AST into Elixir's AST, your quoted forms. And finally, we compile that into functions that are ultimately run in processes by a further part of the system. So here's the end goal. So editing a program in the browser in a tactile way. So this AST is just a thing that checks for that rule we talked about earlier. This is a very tiny programming language, but the core idea is solid and can be expanded upon. So let's talk about how it works at runtime. At runtime, we have a process that represents a collection of rules, and it sent a message every time a document is evaluated against the rule set, and it returns all the responses that its rules returned. So during runtime, those rules can be changed, and when that happens, we just swap out the process of state that's holding the list of rules for that chatbot. All right, so now that you understand how this works holistically, let's get into the details. We're gonna look at the AST and its representation. So this is really comprised of two parts. Our language is idealized AST and the JSON representation. So we have to have both parts because we're choosing to transmit the AST by JSON. So if we use something like BERT or Transit or protocol buffers to transfer the AST, we could conceivably avoid the second part, the second representation, but we didn't. So, okay, so here are the tight specs for our AST. Essentially, an expression is a two tuple where the first element is the type of an expression, and the second element is the list of arguments. And these are the expression types that we support. So we have an if statement or an if-else statement, and it works just like you'd think. The first argument is just used as a conditional, and the second is the then branch. So then the third, if there is one, is the else branch. Then we have a var and it can fetch a variable out of the execution context. We put the message, the rules are run against into the input variable. So far, this is the only valid variable that we have right now. And then we have the contains. It just returns a boolean that says whether or not the first argument contains the second argument. And then the response just builds a response truck, which is defined in our code. Right now, this is all that our language defines. It would be really easy to add more general or special features as we wanted to. But as we mentioned, our AST, it can't be represented natively in JSON. Among other things, there are no atoms or tuples in JSON. And consequently, we define a representation of it that is JSON compatible. So here is how our AST comes from the front end in the JSON representation. And then we have a function called convert that takes in a string representing the JSON and outputs a two-tuple representing our AST. And here you can see the input and the output to the function for an example. And here's the implementation. So it all fits on one slide. Basically, we pattern match against different potential inputs. And then we return our idealized AST representation of the input. Okay, so now we have our AST. So the next thing is to transform it into valid elixir-quoted forms. So ultimately, you might consider compiling this into modules if you actually have a system that needs to go fast. It's a lot faster than interpreting quoted forms. You might expect. But for our use cases in this demo, this is plenty fast, so we're not doing that. The transform is a module that takes in our ideal AST and outputs an elixir AST. So we'll look at an example. And it's not the easiest thing to read there, but that's our table flip quoted form, our AST on the left. And then on the right, there's the elixir-quoted form that would represent sort of the program that that AST represents. And we have a test that just verifies that that works. Anyway, so here's the implementation. Very similar to what you saw before, except for this time we're using like unquote unquote. So we're just pattern matching on the expression type, and we're using quote and unquote to build out our quoted forms. This is obviously recursive, so for each argument in each expression, we generate elixir for it until we get to the leaf nodes and don't have to do it anymore. And then here's the implementation for var, response, true, false, binaries, and contains. So basically this is two slides to show everything that that consists of. It's not very complicated code. Okay, so now we have our elixir-quoted forms and we want to evaluate those against our input string. So the compiler is a tiny, tiny module that just returns a function that takes an input and returns the rules output given that input. So it receives our AST as its input and then it returns a function that evaluates the quoted forms that the transformer generates for the AST and it binds the input variable into its context so that we can get that var out. So we'll see what that looks like. And again, this is super tiny. So on the top left, we just have a test that takes that JSON table flip AST, compiles it down, and then asserts that we have a function that operates like we wanted it to. And then on the right, you can see the actual implementation which is literally just generate the quoted forms, call eval quoted on them, and then return the response. So that's the core of the pure functional part of the system. Next, we have a chatbot gen server. So this is an abstraction around a list of rules. In our current implementation, we aren't threading any state through this so it's not technically necessary for us to have a gen server here. But this would be the place that if you were building a system that built up state as rules were evaluated, this would be the place you would do it. So a chatbot just consists of a name and a list of rules and they run in their own processes. So they handle evaluating a given input against their list of rules and collecting the results to return them. And here's the type for a gen server state. As I mentioned, it's just a name and a list of rules. A rule can be one of two things. It's either a module name that has an apply function which takes a message and returns a response or it's just a function that takes a message and returns a response. And this was just basically for some prototyping I was doing. It could be just one or the other. I had some fun with this type spec because I'm pretty sure this is the first time I did a type spec that specged an anonymous function based on its input and output types. Anyway, and this is the public API for evaluating message. So this also includes the gen service handle call for that case. There's something kind of clever happening here and I wanna point it out. I don't know how clever it is but I enjoyed it the first time I sort of came up with doing it this way. Anyway, so this is the first case where like protocols made me super happy. There are other ways that we could do this thing but this makes me happy. So you can see here that we're calling the apply function for each of the chatbot rules and we're doing that inside of a for comprehension. So applying the rule is done differently depending on whether it was a module or a function but that's not really important. But the into key says that for our for comprehension we're gonna take the response of the for comprehension and put it into the chatbot DSL response. And so we do that with the collectible protocol. And so I just wanted to show the implementation of that for response. So here's what the response structs type looks like. It has a from string and we're using this to fill it with the chatbot's name and then there's a list of messages. And so this is super easy. So let's look at the implementation of the collectible protocol. So first things first at the bottom of the actual structs file I defined the collectible implementation and here collectible all it needs is an into function to be defined. And so I just delegate it to the response module like the module this is for. I've enjoyed doing it that way. I played with the like putting the implementation in the def-imple here. You may not prefer just doing a delegate but I enjoy it. Then let's look at the implementation of the into function because that's the important part. So it looks like a big function but that's just because there's lots of comments. So we'll walk through the bits that matter. So here and is that readable? I think it is but I'm not back there. So basically in the event that we return a nil in the inside of the for comprehension then we just basically don't do anything with it. We don't collect it into the response.  And this is just nice because this is the place that the nils go away. So in Ruby if I were doing something like this I might like have a big array and it might have some nils in it and I might call compact on it and then later on I might have someplace else that hadn't called compact on it so I might just litter compact throughout my code because that's how you solve the problem. But this is the only place this can happen so I never will have to worry about nils past this point. Anyway so I don't know this makes me happy a little bit. It's a tiny filter but it's fun to do it here. Anyway enough of that. So if we're collecting a message we put it into the list of messages. So this is sort of the field in the struct. This is where in some more interesting rules engines you might collect different types of return values into different fields in your struct so maybe you're building a more comprehensive response type and so maybe depending on the return value you put it into different positions in the structure that you're returning. Anyway in the medical coding engine for instance we might return additional questions those would go somewhere. We might return guidances they might go somewhere else. We might return ICD-10 codes. So here they're all just messages so we just collect them in the one spot. Anyway so you also could imagine that maybe we have since this is a chat bot thing maybe we wanna implement something that has some state so like maybe you're incrementing a counter based on giving kudos to a person in the room and so that would just be a response type and then the server would handle doing something with that response type and that would just be in a different field I would assume. Anyway so this is the next bit of the collectible protocol. This is basically we're done so here we're just returning the source now that we've collected stuff into it. You might use this for like doing some cleanup before you actually returned. I haven't found a case where I needed to do that but it seems fair like if you're collecting across something that has some open port or something. And then you also have to handle the case with the collectible halts. I also haven't had to deal with this ever but if you're gonna show it for completeness sake so you can actually implement this. Anyway so that's that. All right so now we have the ability to turn our AST into functions that do whatever we want. And now we need to make it easy to build out various ASTs and ultimately store them in a persistent store. Right now we're just gonna talk about the front end for a minute. So we built our front end in Angular. It communicates with our Elixir API and it consists of two parts. The first part just allows you to visually manage your AST elements and then the second part allows you to create multiple chatbots and each chatbot having a list of rules that it adheres to that consist of our AST. And so this is where it all begins right here. This is our AST builder HTML view. One of the cool parts about building this in Angular if you guys have never used it before is directives. These are just markers that you can place on a DOM element and they tell Angular's HTML compiler to attach a specified behavior to that DOM element. So you can see on line three we're just calling our AST element directive that's defined in our AST builder controller. And here is where that is defined. In the controller we have this directive called AST element and it has a template specified on line 47 and it will render that template if it's ever called. And it also has a create block function on line 50 that expects a type that sets our scopes AST based on the type that it receives. So this is how you can turn a placeholder element into an expression of a given type. For instance, if it's past the string if it sets our AST to contain the string if with the empty arguments. And then if it's past the string contains it sets the AST with the type contains and arguments that specify a type of var that should be an input and a type of string that contains a static string as its arguments. And then lastly, if it's past the string response it just sets AST with a type of response that has arguments of a static response string. So also our AST element directive has a function that checks our AST and if it's empty then this is gonna return true and if it does then our AST element template gets rendered. This is specified in the directive that I just showed you. So everything inside of the NGF on line two will be rendered. Angular's NGF directive it just removes or recreates a portion of the DOM tree based on an expression. So if you notice we're calling that function AST as empty. So since our NGF returns true we render a dropdown menu with a button that calls our create block function. And that passes the expression you choose based on the selected value from the menu. So next on line 13 you can see we're calling another function named AST as if. So back in our directive we have that very function it checks our AST again and it's just checking it this time for the string if. And if it returns true our directive is called and it renders its template that's defined on line 35. And then here's that template. So if you'll notice on line four it's calling the AST element directive that we initially called to start this process. So this is where the nesting of the AST elements begin but we had an issue with Angular because Angular doesn't allow directives to recursively call themselves. So we had to add a library called Angular recursion I think and that had the functionality that we needed for this to work. So back in our AST element template on line 16 we're calling the function AST contains and our AST is contains. And if it returns true it renders its template. So by now you probably notice that we're just using the directives to pattern match based on what type of expression that this AST node represents. Same thing with our AST contains function. If it returns true this is the directive that will actually be called. The difference between this one is it's actually like setting the AST and the scope based on what input that the user inputs and just enters that into our AST. And just for good measure our AST contains template that's rendered. All right so I'm going to go back to our AST element template. We move on to line 16. We're calling the AST as response. And if it returns true then this directive is called. You see what's going on here. And here's its response function just checking the AST for the string response. And then this is its directive that gets called. And then this one just like the other one sets the AST based on what input that the user enters. And then finally our AST response template. So I want to go back here one more time just to reiterate on what's happening. This is our AST element template. We're using the directives names like AST, empty, AST if, AST contains and AST response to pattern match based on the NGF before each directive. So it will render its template based on the type of expression that the AST node represents. And the AST if directive just calls the original AST element to keep nesting and doing our pattern matching process. So the second part of the front end is pretty simple. It's just the crud interface that allows us to create our chatbots and interacts with the Elixir API. It's just basic crud implementation. But I think it's important just because it's the segue into the next section of our talk. You can just see we're making calls to the API to manage chatbots and then the same thing here just to create rules for the chatbots. So after talking about all these calls to the API let's have Josh talk about the API. So that's the front end. It interacts with the API. Our main rules engine that we talked about initially is a separate OTP application. And our API is just a small Phoenix application that interacts with our rules engine application. This is our database oriented representation of a chatbot. It's basically the same as you saw in the OTP app. As you can see, it's just a name and a list of rules. Every time a new one is added or the details change we restart the gen server associated with a chatbot. Here's the model we use to store rules in the database. They have an AST field where they can store the AST for the rule and they belong to a given chatbot, so nothing too fancy. Here are our routes. This is all very basic Phoenix and Ecto stuff. Just some nested routes in an API pipeline. So we have a chatbot's resource managed by a chatbot controller.  Anyway, I'm pretty happy with the integration test for the API. I used a method I learned from a blog post by Dan Swain. And basically this is just a support library that can interact with our API using an HTTP client during our tests and then writing our integration test becomes very easy. So this thing encodes our request on the way out so we give it a map or a struct it turns into JSON. It gets decoded on the way in and that way we can easily specify the endpoint and anything we want to post to it. Here I'm just testing the status code of responses. So this is making sure that we can create chatbots in our API and it's very, very easy to write this test, right? We also make sure that when we try to make a chatbot with an empty name it's rejected. Similarly for the rules endpoints. So in our setup I use the API to create a chatbot. I fetch its ID out of the response and then we post the rules endpoint to create new rules on that chatbot. And we make sure we can't create an empty rule and that we can update a rule. And so our conceptual model says that we're gonna be replying the chats but our rules engine doesn't need to know anything about how that happens, right? We're just responding with messages from our rules but they don't need to do anything at that point. So consequently we have the XMPP bits living in the API project. And so Hedwig is an XMPP client that Sonny Skragan wrote and we're using it to connect to an XMPP server when we start our API up. And all the messages that get returned from rules get relayed to this handler module and this is sort of how you can build bots with Hedwig. And so when we see a message we turn it into the message struct that our rule evaluator knows how to deal with. Then we use a function on the chatbot from the OTP app called ScatterGather. We send it out serially to each running chatbot gen server. And then we loop through all the responses that came back and we call handleResponse on them. So the way that ScatterGather works is the chatbots in their net for the gen server they register themselves with PG2 into a group named chatbots and then ScatterGather just gets the list of PIDs and asks them serially to evaluate the messages. HandleResponse just sends the responses message back to the XMPP server and it prefixes it with the name of the chatbot that the response is from. And this is primarily because I only actually have one chatbot connected, otherwise you would just use its nick, right? And in the API's model for the chatbot we define how to start the chatbot DSL's gen servers for the chatbots. So we define this ensure started function. It takes a chatbot model. If one's running, if a gen server for that model is running it stops it, it starts a new one and then it registers with a name so that later we can find it to kill it again. We could just replace it state but here we're actually killing it. And so anyway, we call this function from the controllers whenever a chatbot or whenever it's rules are updated. And anyway, so now we have a demo and I need to, let me see, I'll actually run it up there rather than mirror my screen if I can figure out how to, no I don't. Bull honky. Oh, here we go, there we go. Oh, come on, really? I believe in magic. Okay. All right, fine. I will do this. You can't beat me. I don't think you can beat me. Hold on a second, that's what I needed. Okay, here we go. So here, if I can find my mouse, maybe I should have mirrored the screen. I know, it's huge. Okay, so here's a list of our chatbots. We create these two when we start the app so like there, it's seeds basically. And so you can go and look and this guy has the table flip rule. So if we look at his AST, where is it? He doesn't have any rules. This guy has rules. I don't think the other guy have a rule. Let me just back out here. Okay, there we go. So here's his rule. It's really hard to read it. So this is basically responsive design in action. Okay, here's my input. So if the input can then stable flip, then he responds with this guy, right? Let me go ahead with that. Sorry. Okay, so that's that rule and let's see it in action, right? So I've got here I have a Jabber client that is connected to this thing. And so I can say things. First off, I've got one that sort of runs all the time. He's just an uppercaser. So that gets up cased. If I can say table flip, right? And that happens. So that's good. And then we've got another guy who's really macabre. So anyway, but let's actually go and add a rule. So we're gonna add a new chatbot for this. Oh, hold on. I have to type in here. Okay. So this is the cop. So we have a new chatbot down here called cop. Gonna make a new rule. And we're gonna say, if the input contains something, then we're gonna respond with something. And I know this is a very basic sort of language, but it is very flexible. We've got a much more complicated thing. So let me come in here and find my presenter notes, which are totally not showing up. That's fantastic. In a moment, this is super important that I get this right. Because he, bear with me. Computers, how do they work? Okay, I believe in miracles. Okay, so we're making this rule. So we're saying, all right, if the input contains, now one thing that's worth pointing out, because somebody's gonna wonder this immediately, the bots don't respond to each other. So I'm not gonna get it. We thought about doing that, but then it just infinitely loop possibly. It'd be pretty boring anyway. So if somebody flips a table in this room, the cops' responsibility is to fix it. Oh, that's wrong, hold on a second, gotta get rid of that extra stuff. Yeah, so that's his responsibility. So we'll save it, and we haven't restarted anything, right? We come over here and let's go ahead and flip a table. Yeah, all right. So that's a live demo of editing rules. Obviously this is just chatbots, but yeah, it's honestly super flexible. So let us go back to presenting here. Okay though, so does anybody have any questions about this? Finally, again, I'm Josh from I-11.com and from ElixirCypx, and there's my GitHub. I'm Robbie from Center of Sources. I think that's it, guys. Okay, thank you.