 Thanks, everyone, for the warm welcome. Yeah, as Liam and Truse, I am Taylor Thomas. And this is choosing customizability and distributing dependencies with Wasm components. So who am I? Just a quick thing. That little icon on the right is something that actually Bailey, who's just speaking, generated. And it's very cursed looking, but it's kind of hilarious. So she generated it because I do a lot of rest, and I'm always wearing a hat. So she generated that to make a story. That's the picture. But yeah, I'm an engineering director at Cosmonic. I am a serial open source contributor and Wasm Cloud maintainer. I've done a lot of stuff in Kubernetes. I was a hell maintainer for a long time, all those kind of things. I'm also one of the co-chairs of the CNCF Wasm Working Group. So I do a lot of work over there in that side of things. And as I said, I'm our station. So I do a lot of rest. I come from doing a lot of go before that as well. And we all kind of touch all the languages at some point. So what's the agenda today? You'll notice this is really short. And there's a reason why I have this up here, because I'm going to be doing some things live, right in front of you. And I'll explain why. So let's talk about the component model. Now, some of these slides I'm going to show are actually the same as Bailey's, and that's on purpose. Number one, this is recorded, and people might watch it later. And number two, I wanted to drive home the point. So first off, this is just the quick overview of what the component model provides. You heard Bailey just barely talk a lot about this. And the main thing is that it is interface driven. And I'll explain a little bit more about that. But it boils down to everything is interface driven. As a developer, you have interface driven development. And as a platform operator, you operate your platform via interfaces and once you expose to your developers. You get SDKs for free. That's the whole other selling point that we really talked about. I'll give some examples of that. And then there's this cool thing called virtual platform layering. So let me dig into some of those points. So this is the slide that Bailey showed. And I want to drive this home again. We jokingly call these little things on either end, the nubs. They fit into other nubs. And so what it all boils down to is you have an interface that says, I am using logging. I am using a key value. I am using whatever it is. And you don't have to worry about the implementation details on the other side. So this means that code, everyone, this is a CNCF conference. Everyone's probably written at least a little go. We've all copy pasted those same 20 lines of HTTP server code and reconfigured them. Let's be honest with ourselves. There's no more of that because those things are now externalized from what you're actually doing. So how do you satisfy an interface? There's four different ways you can satisfy an importer and export inside of these WIT files that you've been seeing. One of them is locally. And so we do that in Wasm Cloud with things that are embedded in the runtime. There's a composed component, which will show a little bit more of. There is an optimized process external to the host, which I will also show. And then distributed component will do any of those three things. You're going to see it. This is an example of what we do inside of Wasm Cloud. Wasm Cloud is a CNCF project. It should be incubating relatively soon. It is a distributed system for running WebAssembly. So whoever asked the question about does networking matter, this is the answer to this. So we can do this in a distributed way or a local way. Now for the SDKs for free, this is another thing that Bailey showed, but I think it actually applies for this as well. You can write, OK, once again, CNCF conference. Remember those early days of using client go and then the JavaScript library popped up and then this library popped up and this library popped up and they all work slightly differently. It's so fun, isn't it? And there's no longer any of that. In a world where components exist, the go client would be it. Everyone would use that through a set of interfaces. And so that strictly divine interface makes it really easy to consume it and reuse these libraries. Now, let's talk about WasiWirt. So WasiWirt is a project that is meant to be an easy use library to do virtual platform layering. Now what virtual platform layering is, is it says, hey, I work at a big company and this needs to go through a specific proxy and I can layer something in and say, this is now going to go through a proxy. The developer didn't have to know about the proxy. There's no proxy settings that they had to set any of that. Or you could be saying, oh, file system access. Well, you might not want to grant file system access to your root nodes or whatever there might be. So you abstract that away and give it an in memory one or it could even be doing HTTP calls under the hood. It doesn't really matter. And so it also allows you to configure things. And that's another way of putting this, is you can say, I'm going to configure how my environment is going to operate by layering on something on top of it. And then just, I also want to call out a huge shout out to Guy Bedford who wrote this project. And he did a great job. We're going to see a little bit of this today. But to explain a little bit more clearly about how this works. So we have this component that we've written and it might have things like I need to import wazio or wazifile system or the environment or I need to get HTTP. And all of those things, especially IO and file system, I could want to abstract that away. I could make it an in memory file system or I could pass in a foobar environment variable. And so what that does is it glues it together and it says, I'm going to do it. And so what your new component looks like is this. So you end up with essentially four things it's trying to import, but then when you're finally going to run this, if you've virtualized away these things, you end up with a single export wazio HTTP, which is exactly what you want. This is very, very powerful because you can layer it multiple times, time and time and again to get whatever thing you need. It's a very powerful and core concept of the component model that we're going to see today. So to learn more about the component model, this is a QR code that leads to a talk by Luke Wagner. Luke Wagner is the guy who invented WebAssembly. He's a big leader in the space. He's done a bunch of stuff with the component model. He gives a very in-depth explanation of all this. Extremely good, highly recommend. It's a great talk to watch later today or tonight. Okay, so something to understand before we jump into these demos. Was in cloud 1.0, which is what we're releasing right now. We have our alpha branches out is components native. So everything it does follows all the standards and it means anything you use on it can be used with anything else that uses the standards. The whole goal of the component model in the first place. So now we're gonna go to demos. This QR code goes to the code I am going to show. I'm not necessarily going to dive deep into code because not everybody is familiar with Rust and that's what I wrote this in because I'm most comfortable in it. But also it's, we're talking about interface-driven development. So I'm gonna show a little bit of it, but don't worry too much about the details. So we're gonna go ahead and start. And the reason I'm doing this is we keep saying the component model is cool. The component model is cool and everybody's like, okay, that's great. I'm gonna show it to you. This is all live on stage. I'm gonna be coding this, building it, running it all in front of you to show you that this is very real and can be used right now. So I'm gonna start off with a simple HTTP demo. So this is going to be the simplest of simple, but I'm gonna start off by looking at wit. So like Bailey showed in her talk, there is a world. The world says, this is the environment I'm targeting. And this one is incredibly simple. It says, all I need, can everybody see this by the way? I can make it even bigger, but this says I am going to export an incoming handler. So I'm going to be an HTTP server. Nothing else, that's all it says that I want to have. So I'm gonna go ahead and build this. Now something you can note in here when I'm building this is I'm gonna be using the, basically the WasmCloud tool chain. Now I call that out for a very specific reason. So I'm gonna call wash build. This is just calling some cargo builds stuff underneath the hood. And it built and made this component. This component I'm gonna show run in a couple different ways. So let's go ahead and start by looking at what the final output of this looks like. So there's this cool tool called WasmTools. Component wit. And I'm going to take a look at the output of this. WasmTools, not tool. So this right here that you'll see in my terminal is what the final output world looks like. To make this work in the preview two, the preview zero dot two thing that Bailey was showing off, you have to have a few of these imports added in. But you'll see a couple of imports and you'll still see that exact thing we asked for, which is the export HTTP incoming handler. So I'm gonna start this first in WasmCloud. I have a host running on my machine. This is being done local, but to be very clear, everything I'm about to show could be distributed. Each of these components could be different, running in a different part of the world. That's another demo that we've shown many times and I can show you later if you come stop by the WasmCloud booth during the conference. So I'm gonna go ahead and start this and pull over this. So I'm just starting from a file because I'm starting this locally and I'm calling this this HTTP hello component. So I'm starting it inside of WasmCloud. We'll give it a second. It started up and now I'm gonna start something called a provider. So you remember that diagram I showed you earlier. I'm gonna show it to you again, but there's that one little import that's left. It needs to have an HTTP server. So what I'll go ahead and do, if I can get my mouse, there we go, is I'm gonna go ahead and start what we call a provider. It's another type of component that's stateful and allows you to spin up an HTTP server. So I've spun that up. Now I'm gonna give it a little bit of configs. I need to tell it like, you need to listen on a port. This is very similar to like a config map in Kubernetes, like it, oops, that's whoa, not what I was trying to do. So I just put some config, like a config map. Now this is the key thing. Because we're running in WasmCloud, we can allow for dynamic linking. We could hot swap this to another HTTP provider of some kind or we could patch a bug. Doesn't really matter what we decide to do, but I'm gonna go ahead and take that and run it right here with this link. So you'll actually see that the HTTP server started on my machine, proof that this is real. And I'm telling it to link to that interface that I exposed. Okay, so now this is all done and I can actually come over here and say curl 881 and you're gonna get hello from rest. Simple hello world example. Like I said, I'm not gonna show too much code, but the code for this is very simple. This is gonna be made even more simple as we improve the experience, but it is just saying, hey, I'm gonna handle a request and then I'm gonna write out a body to it. So very straightforward. Now let's go back to a diagram here. So this is what I just showed. So WasmCloud is satisfying the Wasi CLI environment, all those other imports that it's requesting. But then there is an HTTP call. We use something called WRPC, which is wit over RPC. It is a protocol that can be, it's fairly transparent. We use it over NETs and this thing is being sent to an HTTP server. In this case, it's just running on my same machine and it's very fast. But this can be running anywhere. So that's the first thing we did. Now, like I said, I built this with the WasmCloud tool chain, but this is something that can run anywhere. So there is a WasmRentime, which is very, it's kind of one of the more general purpose runtimes out there called WasmTime. So I'm gonna go ahead and take WasmTime serve and this is going to take that, you'll see it's the exact same component I started, build HTTP hello world and I'm gonna start it. Okay, you'll notice it's now running and if I come over to another tab and I do curl on 8080, hello for must. Exactly what you saw before. So I just took something that was running in WasmCloud, it's not locked in, you can take it and move it somewhere else. So all we did in this case for the diagram is we took WasmTime instead and we said WasmTime is actually providing the HTTP import for it. Really also just a straightforward thing, it's just saying I need something to plug in there. So let's go ahead and go to the next part of this. So the next thing I did was say, let's make this more difficult than just an HTTP server. Let's add in a database. Okay, that's always a fun thing. So let's go to our wit again. You'll see here we imported something different. You'll see at the very top we have some logging, we're gonna start logging some things and we also have this key value atomic. So now I am importing an interface from a key value, a standard key value interface we're working on in is part of what's called WasmCloud and we're pulling that in. And then when we build this, we're going to use that and we're gonna increment a number inside of a key value store and return that every single time. So we're gonna go ahead and build that. So let me come back over here and do it. So I will build this as well. Okay, that's all built and good to go. And now I'm going to change which component is running inside of WasmCloud. So you're gonna see this in WasmCloud again. So I'm just changing which thing it's using to be this latest thing that I just built. Okay, and it's updated. So now I need to have something that satisfies that key value import. So once again, because this is WasmCloud, I'm gonna go ahead and start this as another provider. And we're gonna use Redis. So I just have a Redis server running locally. It's in this tab right here in case you don't believe me. There's a Redis server running locally and I'm gonna give it a little bit of config too. This is where you'd pass in connection strings or whatever. And notice that it's entirely external as a platform operator which is the role I'm playing right here. I'm gonna come in and I'm going to give it some config. I'm telling it to connect the local host because I'm running everything local. And then I'm gonna go ahead and take this link I'm about to put in right here. And I'm gonna say, please link to that atomic interface, these two different components. So I'm dynamically linking it in place. Okay, now that's all ready. And if I go ahead and I curl this, hey, we're getting an incrementing number. Okay, that's pretty awesome. Now we're talking to a database. So we just added another layer of complexity yet it's still all behind interfaces. So let's go ahead and keep going on with that. What happens if I try to run this component inside of wasm time? Oh no, what are we ever to do? That is where the component model comes in. It's saying, hey, I don't have these things you're asking for. What am I supposed to do here? So we can do that by virtualizing it away. And in this case, because I'm running it locally, I'm going to go to something that we call a mock KV. So this mock KV, if we look at its width, you're going to see something a little bit different. You'll see that it's exporting the logging import that I need from the other thing and it's exporting a key value atomic and it's importing from the file system. So this component is going to put key values like the value of a key on the file system. That's what it's going to do. Just something super dumb, but this is a mock KV. This could be another implementation that forwards an HTTP request to another type of database. This could be any number of things. But in this case, I'm just going to build something super straightforward. So I'll go up to that mock KV and I'll go ahead and wash build that. And over here, we now are going to introduce one more tool. This syntax is a little complex. I know that, but I'm going to show it just so you know what it is. There's a cool tool called WAC. Now this is a tool that was built by Peter Hewn in the WebAssembly community. And WAC is a way, it's a super set of width that allows you to say how things are going to be composed together. Now there's a lot going on here. You don't have to understand it all. But essentially what it boils down to is I'm going to say, hey, I have this new mock KV, the thing that I just created that other way I showed you. And I have my hello KV thing that I've been doing. And you'll see that I'm putting in logging right there for it. And I'm putting in atomic right up here. So I'm satisfying, I'm providing an export that that thing can consume and I'm gluing it together. So what happens is now I can come over here and we like to call it WAC it, you WAC it together. That's a fun name. So we're going to go ahead and WAC it together. And it's now output at this output.wasm. So if I go ahead and I do the component, look up for the width, you'll see, so actually I'll show before and after. So we'll go ahead and do build HTTP hello world. And you'll see that we have these three types on the imports right now saying, hey, I'm importing these three things. And if you look at what we just created, you'll see that we ended up with none of those imports in there anymore. So now if I do wasm time serve, and I go over here and I curl it again, you'll see that I now have an incrementing key value store. So I went from airing out to patching over that dependency. What does this look like? Something very similar. So in this case, wasm time is still providing all the same things that it did before, but now I took my KV file implementation, my mock file server, I remember my KV and I put it in and glued it in and now we have a whole component again. It doesn't need anything else to be able to run. So inside of what we did in wasm cloud, we ended up with something that looked like this, right? The same things are still satisfied, but in this case, it's going to an external dynamically linked dependency. So just to emphasize this again, it is the exact same component. I did not change anything. All I did was layer on what was needed for this to actually function. And I'm doing this, like I said, this is all live, right in front of you. I'm not fudging any of this. This is actually how it works. So let's take it one step further. Let's say I want to add in a custom interface. So I've been showing ones that are all standards and a lot of people have these standards just kind of built into their host. We generally don't take that approach. We have these external dependencies, but what if I have a custom interface I want to build? So let's go back to the wit again. So if I come over here to my HTTP hello three, I added a new interface called Pong. We're keeping it simple today, but this could be anything. This is just a simple ping pong. I call ping, it returns the Pong of some string value, but it's entirely custom. This is not defined anywhere. This is something I just wrote. And I'm going to look at my world and say, hey, I have that key value atomic, but I'm also importing ping pong, which is that new interface I defined. So now when I actually build this, what I do is I can come over and build it over here. Okay, so that's built. And I'm actually going to go ahead and run it. But before we do anything, I'm going to go ahead and actually show you what we're going to do with this. So I will update it, but we're going to stop there. And I'm going to show you what we have to do. So you'll notice that we have now this dangling import that we have to do. So what we can go do is now create a Pong, something that implements it. So if we look at the wit here and we look at the world, you'll see that it's importing wazzy CLI environment and it's exporting the example of ping pong. Now this is one place I'll show you the code again really quickly because it's very fast and it matters for the next example. Right here, we're creating a component that it exports this ping interface for something to call. And it is using the environment to find an environment variable called pong so I can configure what the variable is going to say for it. So that's how this is being set up. So once again, I'm going to go ahead and go up to pong and I'm going to wash build it. Now let's go ahead and take a look at what this wit looks like. So you'll see here, we have all the imports that we've been seeing, but that wazzy CLI environment something I explicitly called for. In a highly distributed multi-tenant system like wazmcloud, we don't expose environment variables to people and that's going to be a common use case. It could be it's not available on your system, it could be that it's too small. So if I try to run this right now, it's going to call and we stub out the import and say you're not allowed to do this by default. So I'm going to say how do we get around this? Well, this is where that tool wazzy vert comes in. So wazzy vert allows us to do this with these common set of interfaces and it's something that we hope to be able to expand into things like wazzy cloud. So what I did with the key value store can be done later in the future. So I'm going to take wazzy vert and what I'm doing is I'm saying take build pong which is what I just built, I'm allowing random because I know that on our system, I need this because I've built it, but also we have a secure way of generating this so that it's not going to be a security issue and then I am going to manually pass in an environment variable called pong called with wazm day and I'm going to output this to a new component. So now I have this vert.wazm and if I go ahead and do vert.wazm, there we go. You'll notice all of those imports went away. All that's here now is I'm importing random and I'm exporting ping pong. So now this component has been entirely virtualized away from all of those CLI things. It's not allowed to do anything else. So now for our cases in the demo, in wazm cloud I start this as another component. So I'll go ahead and grab my component here and I'm going to start it. We'll give it a second start up. Okay, now my pong are set up and then I have to dynamically link it again. So now I've linked this, it's all put together and if I go ahead and curl it, you're going to see I got pong wazm day which is that value that I just set right here. That's what I was talking about this config element. So I've progressively built this up to now we're using custom interfaces. But once again, how is wazm time gonna do this? What is it supposed to do? Well, in this case, we can literally just glue those components together. What we just did distributed, I'm now gonna do local by gluing together. So if I come back over here, I'm going to use that wax syntax again. This one's the most complex because it's gluing everything together. But essentially, you can see down here at the bottom, I have, hey, this example ping pong thing is getting pulled in by my pong component that I'm pulling in for this composition. So when I come over here, this is one I definitely copied because it's a long command. So I'm gonna say, I'm gonna glue this all together and output it to output dot wazm. I need to go up a directory, sorry. Okay, so now I've built this output dot wazm and if I go ahead and do the output or actually I'll go ahead and run this. I'll go wazm time serve output dot wazm. So now it's serving on 8080. And I come back over here, I'm getting the exact same thing. So I just took this component to review. I took the component and I'll actually show you the diagram. I took the component and I have wazm time taking care of all the things it satisfies. Then I have wazzy key value that's being satisfied by my custom component I created. And then the Ponger thing that I created with wazzy word on top of that to make sure that it can't access the environment. And all of these things I was able to satisfy and put in all together here. Now once again, wazm time is a stand-in for any other standards compliant system. If someone else has implemented these standards, this exact thing I showed you, you can run there. And all of this can be done right now with tooling. As I said, this is using the alpha tooling of wazm cloud that'll soon be the full one dot o. But this is something that can be used anywhere you want to. So that is pretty much it for my demos. If you wanna learn more about this, there is the component tutorial that Bailey already mentioned. And you can come meet, I'll be over at the Cosmonic booth of the wazm cloud booth talking about this today. So with that, where am I on time? Actually fairly decent. So any questions? Taylor, I have a question. So when you're using this whack tool, to me, it sounded a little bit like the Unix pipe. That you were just taking these components and you back to the Unix philosophy, you were just infinitely chaining them together. Is that a good analogy? Yeah, essentially by the end, if we go back to this diagram, that's a chain of like three or four things that it's going through to make sure it gets the right value. Let's stay here for just a second. Now, but what's different though, is that each one of these components that you're chaining through isn't sitting on full posix, right? It just has the only the just the little worlds denied by default, you know, there are nothing? Yes, that's exactly right. So if you look at the, if remember that last example I showed with the PON component, that was two things. It imported one thing and exported one thing. There was none of, when we talked about the idea of libc, you're not exposing the 500 functions of libc with that, you're exposing one thing. And it's three functions, I think that are inside of get random. And that's much more secure. It's a very lightweight security footprint. Yes, each one of these are still separate WebAssembly modules with separate memory, linear space and all the advantages. Yes, exactly, and they can be reused. If you're using PON or somewhere else in a different way, I can pass you that interface or this exact component and you can use it in that place. Last question, then I'll turn over to the audience. And then this is all within a single process, right? That what Bailey was saying earlier. So this is all nanoseconds between components, right? Yes, this is very fast. That's incredible. Great question. Maybe can you share some insights how the debugging process would look like, especially if you have cross component calls and so on? How would this experience feel? Yeah, so those components, I could actually probably scroll back in some of my shell history right there and show you some of the output. That's something that's being actively worked on in the community. It isn't super great right now, but it is very clear when something goes wrong. So last night, I was trying to figure out why something wasn't working and it gave me a detailed list. Now I had to read through the list of things. But once I read it, I could see, okay, this call is failing because it hasn't been authorized with the proper link or it hasn't been put together. And so all those things are there. But the thing is you're still building, like when I was showing that stuff in Rust, I'm still building with the Rust tool chain. I can still use all the Rust things. It's once it's compiled as where we're working on what things we can do. But because everything's standard, you can start to see where you could extend onto those types of things. Something very interesting that I saw in the very first or maybe it was the second slide where you had the definition of the interface is that it looked very much like Rust. And one of the types was parametrized and it was like a borrow of a string. Does this mean that these interfaces not only define the shape of the data that's being transported, but also like ownership semantics? Yes, it does do ownership semantics. That's a really great deep technical question. So the reason why that's there is when you're sharing things that have different linear memories is what it's called, the different memory spaces, you wanna make sure that you know exactly who owns it. So that's indicating to the underlying code that basically lifts and lowers these types from the numbers in a trench coat Bailey mentioned. Those things are lifted and lowered and they have to know that this is owned by somebody somewhere. So when you say borrow, it's saying you do not own this, you cannot dispose of it. And so that way you don't end up with anything you're freeing resources that something else is using. So that ownership semantic has to be there, but it doesn't really, it's kind of under the hood for languages that don't necessarily have that semantic built into them. Okay, thank you very much. Hi, I work on the ManageMesh team at Salesforce. So I think a lot about sidecars and what I'm thinking about watching this talk is like, okay, so we have these composable components and what's stopping people from just creating a component that is their application and then a component that is a sidecar, essentially. Linking them together and using that to implement the sidecar pattern instead of using containers themselves, which would then have that, you know, inter-container networking aspect to it. Is there any aspect to NATS or any of the cross-host communication between WASM modules that are just running, forgive me for the ignorance like natively on the machine that would stop, you know, this sort of conversation from getting started? No, that's exactly the use case we've talked about with many people who are especially running Kubernetes and sidecar patterns right now is that you can glue it together and that's actually something we already put experimental support for but not fully in WASM Cloud is if it's running locally, it can just be routed locally and then if it's going to something remote, then it gets sent over our networking layer, which is NATS. And so it does not preclude any of those things because like I mentioned, this is all components standards compliant. So anything you build, you can run with or without that transparent layer that we have in between. So it would work for that sidecar pattern without much of a hassle. That's really cool. One more really quick annoying question. What was the terminal you were using? That's warp. Warp, thank you. Just to come back, there is a WIT cheat sheet that's floating around. You know, WIT is a larger domain than what you think about than what you have with the open API for example because it's designed to do some distractions that kind of bridge into thinking about operating system context. So if you check the component model docs earlier, there's a great link in some WIT education there. First of all, I very much like seeing NATS as a message broker or like a networking layer here. It's a very cool technology. To do multi-region, would you then use a super cluster or how do you do that? Yes, so for those not familiar with NATS, NATS has a very flexible distribution and creation of its topologies. Now you can put it out there and deploy it. So a super cluster is one where you have multiple clusters that are part of a bigger cluster. And yes, any of those will work. So you just have to shape your NATS cluster to be the traffic for whatever you do, cross region, cross zone, cross whatever you're going to do, which we have done at scale with multiple open source users and then cosmetic customers as well. Do you also then use multiple accounts to do multi-tenancy and stuff? Yeah, and that's something I think we can probably bring to the hallway track right after this and I can give you some more of the details because that's a, we know a lot about that. Cool, so. Great, I got time for a few more questions here, Taylor. Okay. Hello. Any direction for socket-based communication between awesome components and modules for streaming data? For streaming data? Yeah, so there's actually a concept of streams inside of WIT. So I can actually show that in the code. So the stuff that you were seeing there with the HTTP is actually stream-based. So if I come back here and go to the REST code for this and I hide this, you can actually see down here that there is an output stream that it uses and an input stream that comes in through this incoming request that gets our body. So the incoming request is an actual stream that I can then, or a thing that I can take the stream from and read body data out. There's gonna be another demo on here later that shows those streams in action with a Blob Store. I won't say more than that, but that's one of the, towards the end of the day today. But you do have streams that are native parts of WIT, specifically for those things. Okay, maybe time for one more question. Okay, please join me in thanking Taylor for an awesome talk. Thanks, everyone. Thanks, everyone.