WEBVTT

NOTE Sentence-level transcript of https://www.youtube.com/watch?v=Zf_e45GiNCE

NOTE One cue per sentence. Cue ids are the line anchors on /transcripts/Zf_e45GiNCE.html. A cue ends where the next begins, or 2 s after its last word.

s1
00:00:01.309 --> 00:00:03.309
[music]

s2
00:00:12.480 --> 00:00:13.519
Welcome everybody.

s3
00:00:13.519 --> 00:00:14.880
Thanks for joining my talk.

s4
00:00:14.880 --> 00:00:24.560
In the upcoming 20 minutes, I want to give you an introduction on how you can build ultraast agents and MCPs with spin and run them globally distributed.

s5
00:00:24.560 --> 00:00:25.680
So my name is Tossen.

s6
00:00:25.680 --> 00:00:38.320
I work as a senior developer advocate with Ecomi and um I guess all of you have already built either MCPS or agents and they are no different than any other kind of application.

s7
00:00:38.320 --> 00:00:46.399
So they obviously demand super fast response times so that we can deliver the best possible user experience.

s8
00:00:46.399 --> 00:01:03.039
However, traditional regionbound architectures or infrastructures fall short when you want to address a global audience and they they come with some frictions which lead to the inception of edge native

s9
00:01:03.039 --> 00:01:04.400
architectures.

s10
00:01:04.400 --> 00:01:12.479
So obviously latency is one of the biggest concerns depending on where you deploy your MCPs or your agents.

s11
00:01:12.479 --> 00:01:25.200
It might be fast for a subset of your global audience, but others might experience a way lower latency and resulting in a way worse user experience.

s12
00:01:25.200 --> 00:01:27.920
Um, depending on your distributable unit, right?

s13
00:01:27.920 --> 00:01:42.479
Even so, if you even either choose containers or VMs, you may experience a cold start delay that might range from several seconds up to multiple minutes, especially when you have to scale

s14
00:01:42.479 --> 00:01:46.720
dramatically fast to meet unexpected user demand.

s15
00:01:46.720 --> 00:01:52.240
However, we can overcome that obviously uh by overprovisioning the infrastructure.

s16
00:01:52.240 --> 00:02:06.479
However, keeping around many many containers or servers and actually not utilizing them results in obviously higher cloud spendings and is not sustainable from an environmental footprint.

s17
00:02:06.479 --> 00:02:28.080
So there are higher level solutions uh that we can use to run MCPS or agents but they usually or often come with proprietary SDKs or uh deployable units or have their own way on how you should treat them in order to make them work in a production grade environment.

s18
00:02:28.319 --> 00:02:43.280
Once you figured out about those constraints, moving away or migrating your workloads, your agents to another hyperscala to another kind of infrastructure, it's often rather complex and extremely costly.

s19
00:02:43.280 --> 00:02:59.760
So, but there's a solution to that and that solution involves a new way of how we as engineers could build backend or serverside applications and this is done by adopting web assembly on the server side.

s20
00:02:59.760 --> 00:03:05.280
You can think of web assembly as um as containers relate to virtual machines.

s21
00:03:05.280 --> 00:03:12.800
So, they are binaries super tiny in size, easy to distribute, super fast to run and portable.

s22
00:03:12.800 --> 00:03:21.200
What I refer to as the edge native AI stack is a combination of a CNCF project called spin and echcomi functions.

s23
00:03:21.200 --> 00:03:25.840
One runtime where you can run those web assembly applications.

s24
00:03:25.840 --> 00:03:28.239
So let's dive into spin for a minute.

s25
00:03:28.239 --> 00:03:41.120
Uh spin as I said is a CNCF project that is vendor agnostic and it allows you to build web assembly applications that are meant to be executed on the server or in the cloud.

s26
00:03:41.120 --> 00:03:44.080
Spin itself consists of three major pillars.

s27
00:03:44.080 --> 00:03:48.879
So it is a CLI that we as developers use to address all our day-to-day concerns.

s28
00:03:48.879 --> 00:03:52.640
So everything you know in the realm of the inner loop.

s29
00:03:52.640 --> 00:03:53.760
It is a runtime.

s30
00:03:53.760 --> 00:04:05.280
So it's based on WM time um that allows us to run these kinds of applications either locally or on microcontrollers or constrained environments.

s31
00:04:05.280 --> 00:04:18.880
Last but not least, Spin gives us language specific SDKs to boost the developer productivity when it comes to day-to-day jobs like for example interacting with HTTP services, integrate interacting with databases

s32
00:04:18.880 --> 00:04:22.000
or different kind of things.

s33
00:04:22.000 --> 00:04:37.840
Although we have language specific SDKs, spin itself is language agnostic and you can choose from all the languages that are able to be compiled down to web assembly including the web assembly system interface or shortwi

s34
00:04:37.840 --> 00:04:41.280
and you can learn more about spin on spin framework.dev.

s35
00:04:41.280 --> 00:04:46.639
So scan this QR code and you will end up on the spin documentation.

s36
00:04:46.639 --> 00:04:52.639
So spin is the developer tool that we use for building these kinds of applications.

s37
00:04:52.639 --> 00:05:02.000
Echi functions is the first truly serverless computing platform that is globally distributed and has zero cold start at all.

s38
00:05:02.000 --> 00:05:13.919
So every application that you deploy to Ecomi functions is cold started per request that hits your endpoint and on average we can cold start in less than half a millisecond.

s39
00:05:13.919 --> 00:05:17.440
It's fully managed and it's again developer centric.

s40
00:05:17.440 --> 00:05:19.680
Your developers deploy the workload.

s41
00:05:19.680 --> 00:05:30.080
No knobs to turn, no terraform to write, just a simple oneliner and your app is globally distributed at no extra cost.

s42
00:05:30.080 --> 00:05:34.400
Security is um is observed by web assembly's sandbox.

s43
00:05:34.400 --> 00:05:45.039
So there's no way a workload could interact with external resources without us as developers explicitly granting those permissions to our workloads.

s44
00:05:45.039 --> 00:05:52.000
And to be a full-fledged serverless computing platform at the edge, we need some kind of persistence layer.

s45
00:05:52.000 --> 00:05:57.840
So Echami functions comes with a built-in key value store that is again multi-tenant.

s46
00:05:57.840 --> 00:05:59.919
You don't have to roll credentials.

s47
00:05:59.919 --> 00:06:05.520
It is automatically associated to your app if your intent is to use it.

s48
00:06:05.520 --> 00:06:07.039
Again, there is a QR code.

s49
00:06:07.039 --> 00:06:10.080
Scan that and you can find out more about Echo My Functions.

s50
00:06:10.080 --> 00:06:17.120
Sign up for a trial or a free a free account there and you know explore it.

s51
00:06:17.120 --> 00:06:25.440
So these are the technical underpinnings that I want to use in order to build first MCP servers.

s52
00:06:25.440 --> 00:06:36.960
So instead of handrolling a new MCP server, I mean we can implement the HTTP protocol or the uh the specified API on top of HTTP to build an MCP.

s53
00:06:36.960 --> 00:06:40.720
There is a smarter way of doing that and a smarter way is WMCP.

s54
00:06:40.720 --> 00:06:45.440
WMCP again is a CLI that integrates seamlessly with spin.

s55
00:06:45.440 --> 00:06:57.120
So what it what this allows us to do is basically to focus just on the business logic and in in the in the realm of an MCP business logic basically means we implement our tools

s56
00:06:57.120 --> 00:07:12.160
we implement our resources or prompts and we are good to go everything else all those non-functional requirements that we have to tackle right like for example authenticating users using of 2 and OIDC

s57
00:07:12.160 --> 00:07:28.319
that's done by WMCP and we then take readyto-use components off the shelf and compose a final MCP server component together and run that on spin or on a myi functions

s58
00:07:28.319 --> 00:07:30.720
and that's what we are going to do right now.

s59
00:07:30.720 --> 00:07:41.039
So I have installed wmcp on my machine it's github.com wmcpwasmcp and it gives you a nice little CLI.

s60
00:07:41.039 --> 00:07:43.759
So we can do womcp new.

s61
00:07:43.759 --> 00:07:48.000
We can choose a language, Rust, TypeScript, uh, Python.

s62
00:07:48.000 --> 00:07:49.520
And we can choose from templates.

s63
00:07:49.520 --> 00:07:54.000
The default template is me only caring about tools for now.

s64
00:07:54.000 --> 00:07:56.560
And let's call this new MCP server hello.

s65
00:07:56.560 --> 00:07:57.599
We get instructions.

s66
00:07:57.599 --> 00:07:59.440
Hey, move into hello.

s67
00:07:59.440 --> 00:08:02.240
Uh, hello.

s68
00:08:02.240 --> 00:08:06.000
Then let's open up a new terminal on this side.

s69
00:08:06.000 --> 00:08:08.560
CD into hello over here as well.

s70
00:08:08.560 --> 00:08:14.000
And let's run npm install because that takes a few seconds.

s71
00:08:14.000 --> 00:08:20.960
And let's open this one in the editor and let's do this full screen.

s72
00:08:20.960 --> 00:08:22.879
So what do we get over here?

s73
00:08:22.879 --> 00:08:31.360
Uh we get a boiler plate that's uh ready to use and those squirrel lines will go away once mp npm install is done.

s74
00:08:31.360 --> 00:08:37.120
So all we have to do is we have to express the scheme on which inputs we expect.

s75
00:08:37.120 --> 00:08:40.560
We have obviously to provide the list of our tools.

s76
00:08:40.560 --> 00:08:51.200
So again we have to be good citizen over here and have to provide precise descriptions so that humans and LLMs know how to handle these kind of tools.

s77
00:08:51.200 --> 00:09:05.200
So we list them in a simple array and then there's one ingestion function that's called call tool and depending on uh the the payload that we receive we have to decide which tool we have to execute.

s78
00:09:05.200 --> 00:09:21.040
If we jump into handle example tool over here, we can see uh all incoming arguments are validated and if everything's fine, then we basically uh concaten concatenate the received input with a prefix

s79
00:09:21.040 --> 00:09:23.200
and return that back to the user.

s80
00:09:23.200 --> 00:09:25.040
Nothing fancy.

s81
00:09:25.040 --> 00:09:28.880
So let's close the editor over here and follow the instructions.

s82
00:09:28.880 --> 00:09:30.720
Next on list is make.

s83
00:09:30.720 --> 00:09:36.000
make goes on and takes the JavaScript code, compiles that down to web assembly.

s84
00:09:36.000 --> 00:09:43.600
So we end up with a tools web assembly component which is not yet a full-fledged uh MCP server.

s85
00:09:43.600 --> 00:09:46.399
Next in line would be where MCP compose.

s86
00:09:46.399 --> 00:09:54.399
Let's compose a full-fledged MCP by taking our tools and saying hey please give me an MCP for the sake of this demo.

s87
00:09:54.399 --> 00:09:58.399
I don't care about authentication.

s88
00:09:58.480 --> 00:10:06.959
Okay, it pulls all the necessary uh other components and composes together an MCP server and gives me instructions on how to run that.

s89
00:10:06.959 --> 00:10:14.720
I can do a spin up -f server.wazm and we should see that running on localhost 3000.

s90
00:10:14.720 --> 00:10:22.959
Okay, let's bring back the other terminal and let's run np npx the uh mcp inspector over here.

s91
00:10:22.959 --> 00:10:24.399
That should fire up in the browser.

s92
00:10:24.399 --> 00:10:25.519
There we go.

s93
00:10:25.519 --> 00:10:29.600
Uh it's already pointing to localhost 3000 right here.

s94
00:10:29.600 --> 00:10:31.200
So let's connect.

s95
00:10:31.200 --> 00:10:32.320
Let's list tools.

s96
00:10:32.320 --> 00:10:33.760
There's our example tool.

s97
00:10:33.760 --> 00:10:35.920
We provide fu as an input parameter.

s98
00:10:35.920 --> 00:10:39.200
We run the tool and we should get back foo.

s99
00:10:39.200 --> 00:10:39.600
Great.

s100
00:10:39.600 --> 00:10:41.760
Nothing fancy cool works.

s101
00:10:41.760 --> 00:10:43.600
But that's the local experience.

s102
00:10:43.600 --> 00:10:52.320
So how can we take that to become a glo or how can we turn that into a globally distributed MCP server?

s103
00:10:52.320 --> 00:11:02.800
Well, instead of globally distributing uh the hello world MCP server, I have a decision lock MCP server and let me open up this one first.

s104
00:11:02.800 --> 00:11:08.240
So there is this one is implemented in Rust for the sake of implementing it in Rust.

s105
00:11:08.240 --> 00:11:11.279
Um so let's go into lip RS over here.

s106
00:11:11.279 --> 00:11:15.680
There is an equivalent class or structure in Rust.

s107
00:11:15.680 --> 00:11:26.800
As you can see, we're looking at the call tool function where we branch out and either use one of the CRUD APIs or tools that is provided by my MCP server.

s108
00:11:26.800 --> 00:11:33.120
If we dive into the actual implementation um let me no this is wrong.

s109
00:11:33.120 --> 00:11:38.079
I want this and then I want to do that uh decision.

s110
00:11:38.079 --> 00:11:50.399
RS if we go to the bottom of the file you can see this is slightly different syntax but the same meaning right I have to define my tools and if we go to line 15 or so yes list decisions

s111
00:11:50.399 --> 00:12:06.639
you can see over here that I use a store so on my local machine spin recognizes hey toen wants to use the key value store so it automatically creates a key value store using SQLite

s112
00:12:06.639 --> 00:12:26.160
on my machine for development time purposes and on ecom myi functions it's leveraging the globally distributed um key value store without me having to configure anything from here it's actually the same story right I have to use that make file and compose the server

s113
00:12:26.160 --> 00:12:40.079
however I think it's smarter to update the application manifest and concatenate those tasks so that I can remain in the spin developer experience and basically do a spin build

s114
00:12:40.079 --> 00:12:44.320
to compile compose and compile my MCP server.

s115
00:12:44.320 --> 00:12:52.320
However, I can also combine this one with spin ecomi deploy.

s116
00:12:52.720 --> 00:13:01.519
So this right now composes the server asks me hey how do you want to call that MCP server on a my functions?

s117
00:13:01.519 --> 00:13:03.519
I call it ADR MCP.

s118
00:13:03.519 --> 00:13:09.040
I allow um my terminal to interact with the service registry.

s119
00:13:09.040 --> 00:13:22.959
Now it's taken my Wom file and my application uh manifest generating OCI layers from those files uploading them to Echcomi functions on the server side or on the service side.

s120
00:13:22.959 --> 00:13:30.320
We receive those two files and we distribute them across the globe through all the service regions.

s121
00:13:30.320 --> 00:13:38.240
Every region has to confirm a that it received the workload that is capable of running the workload.

s122
00:13:38.240 --> 00:13:43.600
Then we instantiate the workload once and do a internal health check.

s123
00:13:43.600 --> 00:13:56.079
And once that came back for all the service regions with an HTTP 200 then we roll a generic subdomain on your behalf so that you that your MCP server

s124
00:13:56.079 --> 00:13:58.639
will be on the public internet.

s125
00:13:58.639 --> 00:14:11.920
Obviously you can shield that with other products and services uh like the property manager to shield it behind whatever you want to enforce before uh forwarding users to the MCP server.

s126
00:14:11.920 --> 00:14:13.360
So we get that URL.

s127
00:14:13.360 --> 00:14:17.920
So we are globally distributed in roughly 60 seconds.

s128
00:14:17.920 --> 00:14:20.480
Let's move over to an uh to a client.

s129
00:14:20.480 --> 00:14:26.399
I use Z over here but that works with any client that basically supports MCP.

s130
00:14:26.399 --> 00:14:29.120
I add a server.

s131
00:14:29.440 --> 00:14:35.519
I go to remote over here and let me replace this one with the URL that we received.

s132
00:14:35.519 --> 00:14:36.560
Add the server.

s133
00:14:36.560 --> 00:14:39.040
And we can see I have five tools already.

s134
00:14:39.040 --> 00:14:42.320
I can go here and say view tools.

s135
00:14:42.320 --> 00:14:46.720
And these are the CRUD tools that my MCP defined.

s136
00:14:46.720 --> 00:14:54.560
So I can go back and chat with my IDE in the context of my project so that it could leverage uh my MCP server.

s137
00:14:54.560 --> 00:15:04.160
track a decision to use or of 2.0 Hello for awful.

s138
00:15:04.160 --> 00:15:10.560
Okay, so it should now identify my intent and ask permission to run the insert decision tool.

s139
00:15:10.560 --> 00:15:12.079
We can see the raw input.

s140
00:15:12.079 --> 00:15:12.639
Looks good.

s141
00:15:12.639 --> 00:15:13.680
We allow it.

s142
00:15:13.680 --> 00:15:25.920
It now calls out to echo my functions has already has already tracked my decision and I can say give me all the decisions please.

s143
00:15:25.920 --> 00:15:40.720
Now the intent is to use the list decisions tool and again we are uh yes it might want to read uh details to give me everything that it tracked

s144
00:15:40.720 --> 00:16:00.240
or and uh with that we have a globally distributed um MCP server that's routing all the requests to the closest service region no matter where your users are and again you can write those tools or prompts or resources using TypeScript, Python or Rust templates.

s145
00:16:00.240 --> 00:16:00.880
Cool.

s146
00:16:00.880 --> 00:16:02.720
Uh let's move on with agents.

s147
00:16:02.720 --> 00:16:06.639
Um so, oops, nope, this one.

s148
00:16:06.639 --> 00:16:09.360
So, for AI agents, the story is no different.

s149
00:16:09.360 --> 00:16:18.000
However, instead of using another CLI, uh we can simply pick any kind of SDK that's out there and that's popular.

s150
00:16:18.000 --> 00:16:23.519
Um I I think the Verscel AI SDK is pretty nice to use.

s151
00:16:23.519 --> 00:16:28.639
So this allows us basically to create a new spin app using TypeScript.

s152
00:16:28.639 --> 00:16:34.720
Just bring in the Versal AI dependencies and to build custom agents.

s153
00:16:34.720 --> 00:16:38.320
Again, let's move back to the terminal to see how that looks like.

s154
00:16:38.320 --> 00:16:44.160
Uh so let's move one up and let's CD into a simple game agent over here.

s155
00:16:44.160 --> 00:16:48.720
And what's going on over here?

s156
00:16:48.720 --> 00:16:54.320
Obviously, I have created a new spin app using a template so that I can get started pretty quickly.

s157
00:16:54.320 --> 00:17:01.279
I'm leveraging a large language model deployed to a Lenode instance with a dedicated GPU.

s158
00:17:01.279 --> 00:17:04.000
And all my spin app does it defines the tools.

s159
00:17:04.000 --> 00:17:15.520
So, this is a simple game agent for the sake of demonstration purposes that can flip co flip coins that can roll a dice where you can specify how many sides that dice should have.

s160
00:17:15.520 --> 00:17:28.079
And over here in the actual HTTP handler, we load the config and we define our agent, you know, pointing it to the old lama instance running on the node.

s161
00:17:28.079 --> 00:17:34.160
We give our agent an identity and an instruction on what its intent actually is.

s162
00:17:34.160 --> 00:17:40.240
We register our tools and we give it some constraints of of how many steps it might take.

s163
00:17:40.240 --> 00:17:44.799
We generate a response and return it back to the collie.

s164
00:17:44.799 --> 00:17:59.840
Okay, let's uh go let's do a quit all over here and let's do another spin aka deploy no confirm build and it asks for the name that's the game agent.

s165
00:17:59.840 --> 00:18:07.200
So while it is uploading let me explain what happens when we compile a lang an interpreted language.

s166
00:18:07.200 --> 00:18:15.360
So during compilation time we load the interpreter, we load your custom JavaScript and then we evaluate the global scope.

s167
00:18:15.360 --> 00:18:27.600
This has one advantage that not just the runtime is hot also all the dependencies are loaded and then we take a memory snapshot write that to WM store that on disk meaning

s168
00:18:27.600 --> 00:18:37.679
that every web assembly application written in JavaScript is faster than a native JavaScript application when it comes to cold starts and runtime performance.

s169
00:18:37.679 --> 00:18:46.400
The only trade-off though is that we have to ship the JavaScript runtime along with our um with our user code.

s170
00:18:46.400 --> 00:18:52.640
But we use an optimized JavaScript runtime called stalling monkey which is roughly 10 megabytes in size.

s171
00:18:52.640 --> 00:18:55.200
So we get back an URL.

s172
00:18:55.200 --> 00:18:58.880
Let me replace this URL over here.

s173
00:18:58.880 --> 00:19:02.000
And let's say toss a coin.

s174
00:19:02.799 --> 00:19:05.440
And we see um we see a response back.

s175
00:19:05.440 --> 00:19:15.679
And if we look at these headers, we can see uh the point of presence where we enter the Ecomi network is Santa Clara and the closest service region for our

s176
00:19:15.679 --> 00:19:18.559
AI agent is LAX.

s177
00:19:18.559 --> 00:19:22.720
Another interesting header is X envoy upstream service time.

s178
00:19:22.720 --> 00:19:40.480
And this tells me and you right now as well that it took 33 34 milliseconds to receive the request to run through the business logic to reach out to the large language model to generate a response and to go all the way back to the user.

s179
00:19:40.480 --> 00:19:42.000
Oh, there's an internal server error.

s180
00:19:42.000 --> 00:19:42.480
Great.

s181
00:19:42.480 --> 00:19:42.960
Awesome.

s182
00:19:42.960 --> 00:19:44.160
Let's try this again.

s183
00:19:44.160 --> 00:19:45.120
Oh, yeah.

s184
00:19:45.120 --> 00:19:47.440
That was an user error.

s185
00:19:47.440 --> 00:19:48.240
Sorry.

s186
00:19:48.240 --> 00:19:51.840
So, the error was staying 30 cmters in front of the screen.

s187
00:19:51.840 --> 00:19:55.840
Um looking at it now we are 866 milliseconds.

s188
00:19:55.840 --> 00:20:04.000
Um that is more realistic because we have to go through the LLM to basically see that uh our to our toss resulted in tails.

s189
00:20:04.000 --> 00:20:05.440
Let's do that again.

s190
00:20:05.440 --> 00:20:08.880
Tails tails tails tails.

s191
00:20:08.880 --> 00:20:09.760
Oh, there's a hat.

s192
00:20:09.760 --> 00:20:10.400
Nice.

s193
00:20:10.400 --> 00:20:21.600
So roughly 820 milliseconds is what we could achieve with a full loop through the LLM by taking our agent and deploying it to a functions.

s194
00:20:21.760 --> 00:20:24.960
Okay, so the developer workflow is always the same.

s195
00:20:24.960 --> 00:20:38.080
No matter if you build any kind of line of business application, if you build an MCP or if you build an agent, you implement your application using any language that you could compile down to web assembly.

s196
00:20:38.080 --> 00:20:42.400
Rust, TypeScript, Python, Go are the most prominent ones these days.

s197
00:20:42.400 --> 00:20:46.080
You can test it locally with the spin CLI.

s198
00:20:46.080 --> 00:20:49.760
You deploy it using a single command called spin a deploy.

s199
00:20:49.760 --> 00:20:56.000
And finally, your you point your clients to your MCP or to your agent.

s200
00:20:56.000 --> 00:21:02.080
So final or key takeaways from my from my point are portability.

s201
00:21:02.080 --> 00:21:07.200
You can take those spin apps and run them on any Wii compliant runtime.

s202
00:21:07.200 --> 00:21:12.400
Echi functions is one runtime and it's the globally distributed runtime.

s203
00:21:12.400 --> 00:21:14.559
Everything is based on open standards.

s204
00:21:14.559 --> 00:21:19.600
So spinners, CNCF, Wesi, Web Assembly are governed by the bite code alliance.

s205
00:21:19.600 --> 00:21:21.840
But ultimately you gain speed, right?

s206
00:21:21.840 --> 00:21:23.919
You have fast response times.

s207
00:21:23.919 --> 00:21:31.600
Even the time to market for your developers to build MCPs and to build agent goes down because you don't have to roll the infrastructure.

s208
00:21:31.600 --> 00:21:34.799
You don't have to implement non-functional requirements.

s209
00:21:34.799 --> 00:21:36.720
That's all taken care of.

s210
00:21:36.720 --> 00:21:40.000
And in terms of infrastructure, there's no ops.

s211
00:21:40.000 --> 00:21:42.799
It's spin aka deploy is all you need.

s212
00:21:42.799 --> 00:21:50.880
There are other commands in the box so that you can g gather metrics that you can retrieve logs that you can upgrade and so on and so forth.

s213
00:21:50.880 --> 00:22:01.280
But developer experience is our our highest metric when we started spin and while we continue in that direction.

s214
00:22:01.280 --> 00:22:09.600
Um we have a new website that's called the Ecomi developer hub where we share stories and experiments and and experiences like these.

s215
00:22:09.600 --> 00:22:11.200
So go check out developers.accomi.com.

s216
00:22:11.200 --> 00:22:20.320
ecomi.com and if you have any further question find me at the Akcomi booth and with that thank you very much.

s217
00:22:35.210 --> 00:22:37.210
[music]
