Intro0:00
Okay, we're going to kick this off. We're trying to sort out some internet options here, but in the meantime I'll give us our little intro. So first of all, we're— I'm Kyle, this is Jeremy. We're from Dagger, and you'll see more about what Dagger is through this workshop where we're going to build a cool, sweet agent, and we're actually going to deploy it to GitHub.
And so even, like, worst-case scenario, if we can't get things running locally when we actually push things to GitHub and see agents run in GitHub, then that's going to be out of our internet hands and it's all going to be really cool.
So, first of all, on the left side here— cool. On the left side here we have kind of where we're getting started from. So this is the documentation site where we have install instructions, so I'll walk through those real quick.
And then our quick starts where we're actually going to walk through these as, like, the content of this workshop. And then also a shout-out to tomorrow night, we have a hack night at the Cloudflare office. It's on the external events list for this conference as well, but here's a QR code for it.
Okay, so real quick—
So there's a question about whether there's a Slack, I think. Slack for the workshop? Yes, absolutely. So if you go to the Slack, it says dagger-workshop.ship agents.ship. Got it. Okay.
Cool. Let me pull that up as well. So there's questions. Put them in there or raise your hand and Jeremy will get to you. Climb over people.
I will. I will do.
Yeah. Make it happen.
Yes. I'll do my best.
Awesome. So, yeah, if everyone— if you're following along, awesome. If you can't, like, because you don't have a desk room or can't get the internet or whatever, I'm going to walk through it live because I already have everything on my machine.
And then you can always, you know, check back with us later on once you have a solid connection. So if you're not able to get at your computer or follow along, just watch me and I'll go through it and it's going to be really neat.
But if you are following along, here's the installation page on docs.dagger.io so you can install from the Homebrew tab or straight from our install script or with winget, you can install the Dagger CLI. The only other dependency is that you need a container runtime such as Docker or Podman or Node CTL, so like anything that can run containers because Dagger itself runs its engine as a container and I'll explain what that means in a second.
But if you're following along, get started on this. We'll, like, talk through a bunch of stuff about what we're actually doing and what all these technologies are trying to accomplish. So.
I'll take a—
Yep, go for it.
Pause you real quick. Yeah, just for the folks on the tech team and so for some of you in the room, we're having— we're finding the Wi-Fi may or may not work for you. Use a hotspot if you got one, if that works down in the basement.
You're— then you're amazing. Also, I'm trying to do a little something through the wired connection here, but for the tech team, it's requiring a password for me to use this service. So anyway, if you have that, slip me a note at some point.
But otherwise, yeah, we're working on— we're working on getting more connectivity as we speak.
Awesome. Yep. There we go. So the QR is actually for the hack night tomorrow night.
The docs and what we're going through are at docs.dagger.io, so that's like the main content for what we're going to walk through. And I guess real quick, we can intro as well if you want to intro yourself first, Jeremy.
Yeah, sure. I'm Jeremy Adams. I look after kind of the ecosystem. I'm part of the ecosystem team that Kyle and I are both on. And I've been at Dagger for a few years, and so I've got to see already a progression of folks using us for all sorts of things, and most recently a lot around AI agent kind of workflows.
But I love in this workshop we're going to blend together some of the classic use cases we've seen with Dagger around CI and dev workflows as well as, you know, giving those to agents.
Awesome. Yeah. I'm Kyle. I'm on the same team. And I have a background in, like, DevOps and platform engineering. So much more on the kind of cloud infra side of things versus that building side. So it's cool to come at this from that perspective of, you know, trying to deploy agents somewhere and make things work.
And that's why in this workshop we're going to deploy things to GitHub because that's eventually what you're going to want to do when you build an agent. You have to put it somewhere to run it. It can't just live on your machine all the time, I guess, depending on what agent it is.
Anyway, so if you've made it this far, you've made it to the docs, then we're going to talk a bit about what Dagger is and why we're building agents with it. And so basically Dagger is, like I said, it's a container runtime.
It's a workflow engine. And so people have historically done things like build their CI/CD with Dagger because you're building these pipelines that orchestrate containers, run all these tasks, and it runs the same on your machine as it runs in any cloud, like in, you know, in your Kubernetes, in GitHub, wherever your CI might run, but it runs the same everywhere.
What is Dagger5:40
So you're making these workflows. And the cool thing is that's also what agents are,right? Is that they're just these processes where
we have a bunch of tools we want to give to an agent. Anyway, okay, we're going to see it in action. And so let's see, we have components,right? So Dagger itself is made up of core components like containers, like I said.
Also repos, directories, files, and now LLMs are also a component that you have to work with within this kind of toolbox of Dagger and how we're building things. And so it's just another building block,right? It's not a framework special, like, just built for making an agent and then you have it living next to your software.
It's another component within your toolbox. And so you're bringing LLMs into these existing workflows, and that's why it's a little bit different.
Yeah. You could think another way of thinking about Dagger in a nutshell is Dagger's for software engineering workflows and environments. So you're going to see us building some environments, essentially some containerized environments with some functions, and all of these things become tools that, you know, human software engineers, AI agents use for both development side as well as app delivery side of things.
So you'll see that kind of, of course, these areas are all blending and kind of squishing togetherright now. We're seeing all this stuff happen in real time. So Dagger is kind of going to be one tool that you could use for that whole range.
You explained Dagger as a tool to build containerized environments. What's the distinction between Dagger and Docker?
Yeah. So the question was, if Dagger is a tool to build containerized environments, what's the distinction between Dagger and Docker? So, yeah, Docker has been around for a long time, and in fact, the founders of Docker are the founders of Dagger.
And so we can think about the scope of the original scope of Docker was really about containerizing an application and making that thing portable so it can run on my laptop or Kyle's or up in Kubernetes or anywhere.
So now what we're doing is we're taking a whole workflow and making that a portable thing.
With multiple containers?
So, yeah, there's definitely multiple containers and other types of objects, but everything's sandboxed by default. So you get— so, yeah, and we'll see as we get into it. Great question.
Yeah. So we're writing code that is workflows itself. So that code can be Go, Python, TypeScript, Java, PHP. We have all these different languages you can write with. And the cool thing is that you're not kind of choosing your language for Dagger and then that's the world you live in.
Dagger has this cross-language interop. So if I write a cool Dagger module with— oh, it's going to want to load. That's why I have it.
Oh, you're amazing.
Yeah. Error occurred. That's why.
Wow. Okay.
I don't know. Okay. So.
I broke it.
If I write a cool module with Dagger that, say, does, like, TypeScript build or something,right? I can share this on the Daggerverse and maybe I wrote that module in TypeScript and you're writing your modules in Python. You can just install my module and you have these native bindings in your language to work with Dagger modules across language.
So anyway, that's my point in that we're not— when you pick a language, you still get to benefit from the whole Dagger ecosystem. And we don't have images on these. That's okay.
There's some sweet animations there.
Yeah.
Like, oh, it's happening. It's so cool.
Yeah. Like, the coolest animation you could think of. Awesome. So I think we can probably skip forward here.
Yeah.
And so hopefully we've installed or we're downloading— maybe we're still downloading Dagger. So I'll run through real quick kind of the basics of Dagger. So hopefully that's big enough. Maybe I'll make it a bit bigger.
Yeah. That's good.
There we go.
Yeah.
Cool. So we've installed Dagger. We've got these things like container runtime somewhere. And so the first thing we can do is create containers. So if I'm in Dagger shell, which I think I am over here.
That's definitely got to get bigger.
Yeah, yeah, yeah.
So I'm in Dagger shell and I can say container, I think. I don't know.
Let's go over here.
Fighting the internet.
And so what Kyle's showing is there's, like, a few different ways of using Dagger on the command line and including kind of a non-interactive, just fire off a Dagger command to run one of these workflows, a function that's one of these workflows.
Or you can use it in this kind of interactive shell mode that he's showing here.
Yeah. And it's all about building building blocks,right? So, like, with the basics of Dagger, you have, like I mentioned earlier, things like containers, directories, LLMs. But with our code, we're actually going to be building larger blocks out of those blocks to assemble, like, an actual, like, part of a workflow.
And then I'll take those blocks, build bigger workflows out of those. So as we're using shell, we're always going to be interacting with some level of a workflow here. But, like, with container, I can say from Alpine and now I've got an Alpine container and I can get— we can do things with that, like anything you might want to do with a container,right?
So I could literally say, give me a terminal. And now I've got a terminal in a container. And this is the exact kind of tools that we're actually giving to our agent as we're building these pipelines,right? So it can— you can give it a container, but you can build a specialized workspace for your agent to do things like write the code.
So there's a lot of setup to say that we've got all these primitives that we can give to agents to build some really effective software engineering agents by giving them the exact tools they need to complete the job.
But also, like we mentioned earlier, people use Dagger for CI/CD because you can create these workflows for, you know, running your tests for your application or whatever. And the cool thing is that if you've done that, you can take that same code that you wrote for running your tests and give that to your agent.
So now your agent isn't just guessing at some code that it's generating, but it can actually run your actual tests the same way that your developers and your CI do to make sure that the code it's generating is valid code and that it can iterate on these things within the agent.
So this is all we're going to buildright now.
Yeah. And we were just talking to somebody outside before the session who was telling us that in his organization they get, you know, not infrequently now because of people like a product manager who's discovered vibe coding or a team that's using, you know, AI-powered IDEs or whatever that people are, like, cranking out these, like, massive PRs for him to review, like 25,000 line PRs.
And, like, the PRs don't even stay static. So he was like, he's like, oh, I just got this PR and I have to review it. And then, like, I come back and now there's five more commits on it that, like, you know, and so you've got this thrash happening.
And so part of what the reason why CI and AI bringing that together makes so much sense is we actually have to bring some balance back.
Yep.
You know, we've got this fire hose where we can all now just create so much code. But how do we make sure this is actually code that we can test and that we can deploy with some kind of confidence at some point?
So we need to balance out and make sure that there's software delivery workflows that are there to test and build and validate things before we put them out in production. So some of what we'll get into today.
CI Pipeline14:08
Awesome. So, yeah, let's actually get into writing something. So zoomed out a bit so you can see where I landed in the docs here. On the left side we have Quick Start and I clicked on Build a CI Pipeline.
And that's basically to get us to a point where we have a project that we're going to make an agent inside of that that can build new features for that project. So it's just going to be a real quick thing where we kind of set up this example project with functions that know how to build and test the project.
So I'm on this page and we've already talked through installing Dagger and we talked a bit through the basics. So now we have this example application called Hello Dagger template. And if you go to GitHub and say use this template, you can name it whatever you want, like Hello Dagger workshop or just Hello Dagger, it doesn't matter.
You can create a repo in your GitHub from this template. And the important reason for that versus cloning it is that that's going to make it way easier when we actually push things to GitHub in a little bit to make it easier for you to run the GitHub Actions that actually run the agent.
So we're going to use that template. And I've done that over here in this repo where I have my Hello Dagger Py because I've done this in every language. You can use whatever language you want to use. I'll be walking through Python today because I think that's probably what a lot of people here today are most comfortable with.
But if you're not, I can switch between languages. Just raise your hand and say, show me Go. And that's okay. So I've got, let's see. So I've got this application in my GitHub now. I've cloned it to my machine.
So now I can look at the code and it's like this view app that has a bunch of things in it. But the main thing is we want to be able to make an agent that develops it,right? Optionally, you can configure Dagger Cloud, which is, let me just start loading that web page now.
It's basically a visualization. So you can really easily see what your agent's doing,right? Because that's the hardest part of building agents a lot of the time is understanding, like, what are they tripping on? What's actually going on inside the agent?
How is it interacting with its tools? What tools is it even seeing? So with this visualization, you're able to really easily see everything that your agent's doing. And that's helped me a lot, like, develop my prompts. Like, if I see prompts and environments,right?
If I see a lot of times that, okay, the agent fails because it tries to call this tool incorrectly, I can improve, like, the description of the tool or maybe I need to change how the tool works completely.
And so being able to see how the agent's behaving is a huge part of that. Whether you're using Cloud or any other thing to visualize your agents, that's, like, the most important part of making it reliable. Okay. So we've cloned the project.
We now want to create a Dagger module. So if you've installed Dagger, you'll run this command, Dagger init, with whatever SDK you're using. So we have these tabs here. So I'm going to be using Python. And then the name of the module is going to be Hello Dagger.
And that's important because that is basically the name of our object that gets created. So if I open this up and I've run Dagger init and now I can open in my .dagger folder. And sorry, that's really small.
I don't remember how to make that bigger in Z. But we can.
It's in the, it's in the preferences.
To zoom the sidebar.
Command, comma.
Oh.
You command, comma, and it'll.
Yeah, yeah.
And you just put the, there's a, the top. There's a, there's a, well, I guess you don't have your set, but it's a font size.
Font size.
That one. UI font size. Change it to, like, 25 or something. Gotcha. There you go. Save that. Bam.
Boom. Okay. So now hopefully we can see the sidebar a bit better. So I'm in this .dagger directory and apparently I've written Go for this one. It's just, oh, because that's the wrong project. Cool. Let's go to the correct project.
Let me open that up and close all these things. Okay. So I'm in the correct project. And in my.dagger, I've got this source, Hello Dagger, main Py. And so we would have generated when we said Dagger init, it'll have basically these files, but some different content.
So it's going to have, like, the basic generated things to get you started building modules. But we're going to say, let's see, Dagger functions. It'll show us what's available in this Dagger module that just got created. And so this is basically how you interact with Dagger, is with the Dagger CLI.
And you have this code that are just functions of how to interact with your application. So, for example, this build one, we have a container. If we go down to this function and you see we're just building building blocks, we have a function that gives us a Dagger container that is from this base and we put these files in it and we run this command.
And so in that container, when we want to do a build of our app, we can
call that other function to get that container with our code in it, run another command, and then get a directory from that. And so this is, like, really basic Dagger stuff of how you create your dev tools using Dagger.
This is, like, good to call out here. So originally we had this example from Kyle where he showed us running, like, a container and then we said, give me a scratch container. Oh, wait, give me an int from an image from Alpine or from Node or from whatever.
And then you can layer on more things, like add a directory of source code to that. Run exec a test command, whatever,right? Chaining these things together. So you notice I'm using this builder pattern here in code instead of in, like, a CLI.
So it's all the same API under the hood. It's just in this, in this case he's using a Python SDK into that same API. But the same things are happening either way. Same one unified cache where all that stuff is being, all those cached operations are at and one API.
So that's why it becomes really easy to use different languages, different language SDKs, because it's ultimately all one API under the hood.
And so we got this code in this, the next step of this where it says construct a pipeline. We've copied this code into that main file. And that has all of those functions, like publish, build, tests, and that build env one we looked at.
And build env as in, like, your build environment. And so when we run Dagger functions, we'll have those shown up here with their descriptions and everything from the code. So now we've, at this point, like, we've got the project that we want to build the agent in.
Agent Workspace21:07
We've got some Dagger functions that let us build and test the project. We've got the project itself. So now let's actually get the agent started. And so now I'll zoom out again so you can see because I jumped to the next page here, which is add an AI agent to an existing project.
And so we're starting from exactly where we just left off there with that previous guide where we pasted in that code. We have our build, build env, publish, test in our Dagger functions.
Lots of useful functions, but the expectation was the human was probably running those,right? Or you were having them run in CI. You'd kind of set that up, but nothing really agentic yet.
Right. So we have, you know, we're just running our unit tests or our build and creating a production container. And this is what you as a developer or your CI environment are running these functions. But now we want to create an agent for developers to interact with or, you know, to run anywhere.
But also our agent should be able to use these functions as well. And so we're in this next guide and we're going to now create a submodule. Because I mentioned, like, our agents want these refined environments where we give them access to exactly what tools they need to complete their tasks and nothing more than that.
No, no, wait. I thought you were going to give agents, like, every possible tool. You want to let them have, like, a thousand functions that do very powerful things and just let them run crazy. Is that not the best practice?
Well, the, yeah. Maybe not based on the smiles across the room.
Okay. Yes.
What happens if the tool needed changes at runtime?
Oh, yeah. So the question is, what if the tool needed changes at runtime? How about dynamic kind of tools,right? So in a lot of cases we're working with MCPs. We might have a lot of static tool kind of experience and where do things change?
What does happen, Kyle?
Well, so the main thing is, like, you want theright amount of tools for that agent to solve its task, whatever that task is. Like, it needs the flexibility to be able to solve complex problems. So it's not just going straight down a workflow and saying, okay, I do this and I do this and do this because you don't really need an AI to do that.
It needs the amount of tools to select, to choose its own path, to solve whatever task you throw at it. But you don't want so many tools that now this is a generalized agent that does anything,right? It needs to have some amount of focus so that it can solve a specific set of problems really well.
But we will see, like, in the agent loop that's going to happen, we will see the ability for the LLM to see this, like, menu of tools it has and that for it to select theright tool at theright time given the context.
Yeah. But yeah, definitely, like, a big part of iterating and building these agents is determining, like, the scope of the tools. So, like, the kind of the balance between flexibility and reliability where you want it to be able to solve a breadth of problems.
So it needs a variety of tools that it might need. You don't know exactly what it's going to need ahead of time, but you don't want to give it so many that now it's getting lost and confused and fails half the time,right?
And so that's what we're going to focus on here with this. We're going to create a submodule basically that is kind of its playground. It's a specific set of tools that lets it edit our source code. And so if you've worked with maybe agent frameworks in the past that have, like, file system tools, we're actually going to build that in our own coderight now.
And it's just a few lines of code, so don't let me scare you with that. But that's the idea is, like, we're creating these building blocks and as you scale this up, you can consume these from that other people have written.
You don't have to write it all from scratch. But for the practice of building this as a workshop, we're going to write it all. And so.
Allright. Where are we going to give the, where are we going to give, we're putting this workspace. What kind of functions are we going to use?
Yeah. So we do another Dagger init here and we say .dagger/workspace. So we've created in our file system another subdirectory here, workspace under .dagger. And so this is another Dagger module. And this one's just going to have just the functions that we want the agents to have access to.
So you can imagine it wants to read the files in your source tree. So we have a function and again, a file is one of those core components of Dagger. And so we just, our workspace has a Dagger directory, which is our source code.
And so we give it a function to read a file from that. So it just gets the .contents of that file. And that's just the Dagger API to say, this is a path through a file. I can do lots of things with a file.
One of those is to look at the contents. Another function it needs is to be able to write files to the workspace, obviously. And so it's a very similar API here where we say, okay, give me the path and also the contents to write to that file.
And then it needs to be able to know what files are in the workspace. So it needs to be able to list the files. And it's just going to literally do a tree in that workspace so it can quickly see the file structure of your code.
And so now basically with those three, we have another one that we're going to look at in a second. But with those three now, it can do all the code editing you might ask it to do within your file system,right?
And with more complex projects, you might need more advanced capabilities of these. Like, you might need to be able to read specific lines from a file or scan files or insert lines into files. But with our kind of demo agent that we're buildingright now, it's like just the most basic where we can just read and write files and list the files.
So if the agent had access to this workspace object, it would see those functions as tools. Read file, write file.
Exactly. It will in a minute, yeah.
Not yet. We haven't plugged the brain into the robot body yet. We haven't.
Right. Soright now we're building, if you think about the agent as a robot body with a brain plugged into it, we're building the robot body. And the brain is going to come in just a second here.
Which could be any LLM. I mean, kind of a brain in a jar,right?
Okay. So our last one finally that I mentioned earlier is test. So when it generates this code in its workspace, it needs to be able to test to make sure that the code it generated is correct. And if it didn't, it'll get the test failures and iterate until it's producing good code,right?
And so this is kind of the most important part of building this good agent is some sort of validation tool, whether that's like a test or a lint or just something to check that what it's generated is correct.
Or maybe it's all of these things,right? There could be different levels of complexity. But anyway, here now we've got this workspace. So if I go in my workspace, I have this exact code over here. And if I run, I think I have the function down here.
If I say dagger dash m, so now dash m points to a specific Dagger module. And I say functions. Remember before we were in just Dagger functions. If I run dagger dash m, .dagger/workspace functions, I'll see exactly those functions that we just created.
Okay. So the next step is we want our main Dagger module to have that as a set of tools it can use. And so we're going to say dagger install that workspace module. So now it's installed as a dependency of my main module.
So it has this object available. And we'll see why that's really cool in a second. But basically all your dependencies of Dagger, like I mentioned, like we have, you know, I can look at this real quick. We have a big community of people building things with Dagger.
And with that, we have the Dagger verse, which is this massive index of like thousands of Dagger modules that do different specialized things. But whenever you install one of these into a Dagger module, it creates, if we look at my Dagger JSON in this project, we have this list of dependencies.
And so your Dagger module has basically its own Dagger client that is the core Dagger API in addition to all of your dependencies. And so that when you're writing code, you can, like I mentioned earlier, like native in this language, you'll see all of these things available on the main Dagger client.
So you can do all these complex tasks. So basically we've built two modules already. We've built this workspace module and the main module where we're doing our tests and builds. And so we want to create the agent now that can take that workspace and our tests and we can actually ask for new features or modifications or whatever.
Agent Develop29:52
So that's the next step in this guide we're looking at where we want to create an agentic function.
Could we have mixed and match? Like, could we have written that workspace in TypeScript or in Go and still installed it into our Python module?
Yeah, exactly. So like the other modules, any individual module can be written in any language and you can mix and match however you want.
I knew the answer to the question. I was just checking, just checking. But yeah, we see people do this a lot where they have different teams where like, you know, maybe there's a front-end platform team and then a back-end platform team and maybe these folks are TypeScript, these folks are Go, but they can interop and user stuff.
So yeah.
Yeah. So like everything, every task or workflow or whatever that you do with Dagger is a function in your code. And so an agent is no different,right? It's just going to be another function. And we're going to call this one develop because we're going to ask it, we're going to give it an assignment to complete in our project.
And it's going to complete that assignment. So the develop function is our agent. And so this is going to give us the code to copy and I'll just open it in the editor so that it looks a bit nicer.
Don't worry. It's only like 500 lines. Totally fine.
And you know what? It's really short.
But wait, it's not 500 lines?
Yeah, this is itright here. So we have a few lines.
You have it all like spaced out nicely.
Yeah. So we have a new function called develop and it takes in an assignment. This annotated thing is just a Python way of getting us these doc strings for the parameters. But in different languages, like we can see back here, if we go like Go, your arguments just look like this where this little comment is basically the help string when you're using the Dagger CLI and say Dagger functions.
It'll say the assignment parameter is assignment to complete, which is really cool. And we see our source here, which is like our project source. But of course, we don't want to have to pass that as a parameter when we're calling our agent.
So there's this cool thing with Dagger where you just say default path is slash and that's going to be the root of our Git repo. So if we don't pass in explicitly a source parameter, it's just going to pass in our Git repo as that parameter.
And so now we just have to say develop, build me a cool new feature and it's going to kick off our agent. So let's look at the components of the agents real quick. So the environment is like the main thing,right?
And I've used that word a lot today and hopefully a lot of people are using the same word in the same way. But you have your robot body and the brain, like Jeremy said, where your environment is basically not just the tools that it's using to complete the task, but also
your inputs and outputs for the agents, any objects or state that it's working with. All of this is the environment. And so we want to construct this environment and then plug in the LLM, which is our brain, and say, here's your environment, here's your task slash prompt and complete the task.
And so this is the environment we put together where the assignments is a string input. So we have this cool kind of way of declaratively building your prompt,right? Where our assignment is the assignment to complete. This workspace input is a workspace with tools to edit and test code.
So now that our agents, when we connect these things, we'll see this as the description of this thing that it can use and say, okay, we're building up this prompt by annotating our code basically. And so with this workspace input thing, that's referring to the submodule we just created.
The workspace.
Exactly. So if we called that something else like foo workspace and we installed that, this would be with foo workspace input,right? We're dynamically generating all of these functions for the environment type to say,
any objects of my dependencies I can have as an input or an output of my environment. And so we notice that we also have a workspace output, which is the completed task because all objects in Dagger are immutable.
And so I give it an object, it's going to do a bunch of things and give me back a different object that's its completed task. And maybe that's like a boring detail, but the main thing is the thing I passed in is still going to be the same, but it's going to have a new version that's given me back called completed.
I mean, I think a lot of people are dealing with this kind of stuff now,right? With the different APIs and like doing a bunch of JSON parsing and validation,right? And trying to, you know, there's different frameworks doing it different ways.
But you could just think of it as this is our way of saying like, here are the typed inputs. These are typed inputs. We're expecting a typed output back in the end. And this gives us a way to ensure that we're getting what we actually asked for.
That'sright. And now next we need our prompt. So we have the environment and the prompt and we give both of those to the agent basically. So the prompt, I believe, is just a bit lower here if you're following along here.
So it wants you to create a .dagger/develop prompts.markdown and it looks like this. So I'll just open it again over here on my editor. So this is our prompt. And so we're saying you're a developer on this project.
You're going to get an assignment and the tools to complete it. Your assignment is dollar sign assignment. And so this is basically, it's going to be templated in by the assignments in our environment. So it's going to drop thatright in that prompt.
So the agent itself doesn't have to go read this other variable in its environment. It knows, okay, my assignment is make this cool new feature. And then we have a bit of prompt structure here,right? Where if you've built a lot of these agents, you've probably kind of refined how you build your prompts and what those structures look like.
This is a really simple agent, so it doesn't have a ton of structure. But we do say before you write code, make sure you analyze the workspace to understand the project structure. So it's not just going to create some garbage and be like, cool, I made this new file, but I didn't look at the project first.
Don't make unnecessary changes because sometimes you'll see, especially certain models without theright constraints will go make the change you asked for and then change four other things and be like, cool, it looks good, ship it. And always run the test.
So we do have to ask it to run the tests once it's made those changes. So it's not just going to see the test function and be like, oh, I should probably call that. We want to make sure to tell the LLM like, okay, you have a tool that can validate the code you're writing.
Make sure you use that tool. And then don't stop until you've completed the assignment and the test pass. So this is telling it, you know, keep working until you've satisfied what I asked it to do and the test pass.
Some good reinforcement. You kind of like told it, run the test twice.
Oh yeah.
And this comes from experience.
Maybe a third time will help too.
It doesn't hurt at all. And maybe in all caps because it's like what we find, we end up running evals on these things,right? Where we'll try different LLMs plugged in and then we'll iterate on the prompts and until we're getting the results, the consistency we want across the different ones.
And yeah, it comes from experience of knowing like how they veer off track and et cetera, how we're writing these.
Yeah. And that's like when I mentioned earlier, like using something like Dagger Cloud to be able to see the visualization of all the work the agent is doing. If I'm frequently seeing like, okay, the agent is just calling write file and then returning, I know that, okay, I have to tell it to look at the code.
I have to tell it to test the code. And that's going to be different for every model. And especially like the prompt structure is different for different models.
Is it possible to implement things like reflection agents as well to police each other?
Yeah, yeah. So the question is like, can you implement like reflection agents to police each other? And that's something I probably have an example of that I can show at the end if we have time. But yeah, like remember with this, each agent is just a Dagger function.
And so you can create all these agents layered on other agents. And even in your environment, you could actually put an agent in the environment and say, hey, you have this agent at your disposal if you need it to do something,right?
And I have examples of that too, but it's like similar to the concept of like Google's A2A where you say, if you're not familiar with that, it's basically this structure where you tell an agent, listen, you can do these things, but you also can talk to these other agents and that's what each of those other agents do.
And so if you need to, you can reach out to them and say, hey, other agent, I need you to tell me how to write TypeScript. And that comes back,right? So you can put agents in environments. It's all just piecing functions together,right?
It's just the same code we've always been writing, but now there's an LLM component. Cool. So now this lineright here, line 94, most important line of the workshop because this is the agent where we've actually taken our Dagger client and .llm.
So this is another type within the Dagger client.
Should make it bigger just for a second, you know?
Sure, yeah.
So it's off the screen. Makes sense. It's so important.
I feel like it's not even getting that much bigger. It's just.
So huge.
Yeah, there we go. Yeah, cool. So like we've said, allright, from the Dagger client, we need this LLM type. We give it an environment, we give it a prompt, and that's the agent. So now we've got this thing work that is a Dagger LLM with the agent.
See, people want pictures of it. You got it, you got it. You center it. You got to make it look good. There you go. If you need your pictures, you can get one with Kyle and
commemorative. We've got like frames outside. You can slide it in.
Yes. I'll autograph it. So that's the agent. Like that's literally because we've asked it, like we've said in this prompt, we didn't really ask, we told it. We told it in the prompt, this is your task, this is how you work.
Don't stop until it's done. And so now this work variable in our code is the completed work. And so from that work, we can look back at the environment in that and say, I have this output called completed.
Because you remember in our environment, we defined a workspace output called completed. And this thing should be a workspace. If it's not, somebody screwed up. That happens sometimes.
It's a good final check.
Exactly.
Type check. Yeah.
And so from that workspace, we want to grab the completed directory, which is the source. So if you remember in our workspace object here, it has an attribute called source, which is the directory. And so this is all like a few layers of complexity, but we've said in that workspace, we have a source thing that's a directory and ignore the node modules folder because maybe that's going to break in my machine.
And then now that we've got that, just to make triple sure, because remember, I mean, we did tell it three times to run tests.
Told it to test.
But now we get this back and in our code, we're saying, allright, now run the test because this is all the same code that we're using throughout our project to run tests. So we can say, okay, completed. Now manually run the tests.
And if that fails, you could maybe kick it back to the LLM and say, hey, this failed, try harder.
That's pretty huge,right? So that's like trying to put the agents on rails or give them guardrails, whichever metaphor you like better. But it's like, you know, that's pretty key because we're trying to like let them do the creative stuff they do, the generative stuff they do, like write some code for us.
But we need to enforce certain standards,right? It could be compliance things, could be like you said, linting.
So we don't just dump that garbage back to your machine. And remember all these changes that it was making as it's iterating on these things, that was all done in a container. It's not just changing your file system as it's doing its work.
And that's a key thing too, because now maybe you have 10 of these agents running. They all have their own sandboxed workspace where they're editing these files. They're not messing up your local state. And before we do mess up our local state, we triple check that the test pass and then we say, okay, return that completed directory.
And so now this function, and we'll just triple check here on the guide side that didn't miss anything. We say Dagger functions and we have this develop one that shows here. So now if I go into Dagger shell, which is hopefully what it asks us to do, it is.
Local Run42:38
I say hopefully, I wrote this. So, you know, we're just checking myself here. And I can go in and say Dagger. Now before I do that, one thing I don't think I called out at the very start here was that we had to like configure an LLM provider.
So with Dagger, you bring your own model. You can use OpenAI, Gemini, Anthropic.
Local models.
Ollama, Docker model runner, like literally any.
Bedrock.
Anything you can hook up to, Bedrock. So you do have to configure some environment variables to be able to, for Dagger to make API calls to that,right? Because we're just the agent with the tools, the model's living somewhere else.
And so this configuration page, configuration slash LLM, shows all the different options on how to configure things. One really cool thing to call out, I'm just going to type something really scary.
Oh my gosh.
So Dagger also has cool secrets provider integrations. So I don't have my actual API key echoed there. I just have my one password reference. It's just sitting in one password somewhere. And so let's see. Yeah, so it's just pointing at this credential.
Yeah. And then if I reveal in plain text.
No way.
So I've configured this in my environment. So now when I say Dagger, it's going to take a second to spin up. And this is the part where if you're struggling a bit with Wi-Fi, this might be a bit tough, but it's okay because if you are following along, we're going to push this to GitHub in a second and it's going to run in GitHub and it's going to be on GitHub's network.
So we don't have to be beholden to that.
Can you run LLM?
Yeah, exactly. So now if I say LLM pipe model, for example, where you see my little one password prompt.
Nice.
So it's got my key. It's going to take a second to think about it. And so with each model provider, we have a default model, but you can also specify one. We can also specify one in code. Butright now, by default, it's going to use Claude 3.5.
So maybe we're not going to get the best results.
OG. Classic.
Yes. A classic. Yes. Cool. So now I have that and I can say dash help and we have that new develop function,right? So I can say dot help develop. And so this is the thing we just made.
Can you bump that up a little bit?
For sure. Yeah, yeah.
Perfect.
So we have that required arguments of assignments and that was our assignments complete. We have an optional argument source, which again, it's just going to be my repo. And this is going to give us back a directory. So here's how I use it.
I just say develop and then do the assignments. So let's say develop. And then we didn't actually look at the project we're daggerizing yet, but I promise it's like a Vue.js website. So let's ask it to, I think in here we say
the example thing is to make the main page blue. And I'll say make the main page, say hello workshop people.
Whoa. It doesn't say thatright now.
And I've never run this, so maybe it'll succeed. And so now we can see this happening. We see our prompts getting passed in. We see the little person face. That's the prompting and the little robot head of the model, which is Claude 3.5 on it saying, cool, let me do these things.
And we can actually see it calling tools,right? So it's looking at the functions available. We see that workspace.
Oh, it's the ones you said. Yeah, list files.
Yeah, the ones that we made. Yeah. And so it figured out, okay, I can look at my files. Now here's this specific file I might need to edit. So let me read that file. And so it now sees the contents of this.
And while this is running, let me just open up Cloud and hopefully this will load. So we can actually see like the cloud visualization of this because it's maybe a bit easier to see because it's sign in.
I'm clicking the button. I think my Wi-Fi is failing me on this auth flow. But while it's running, we'll just watch this.
It's the same open telemetry in both places. So that you're getting streaming to your terminal UI and the web UI.
So we see a call, write file with some new file contents. And now it says now that we've made the change, let's run the tests. And this is the part that really might fail on this Wi-Fi because it's doing an NPM install and downloading a bunch of NPM modules or node modules.
But it should pass in a second. We'll just let it go and we'll talk through it. But we can see that our agents is actually, it wrote the files and then it's writing, it's running the tests, which is really awesome.
Cool. So this opened up over here.
The Wiz NPM install?
Yeah.
Was part of the tool that you gave it?
So this is, oh yeah. So we see it's saying like with exec NPM install, with exec NPM run test unit. If we go back to our workspace
and our test function, that was part of it. So this is like the agent just had to call test and we've defined what happens when you call test. And so.
It's not like the random ones like, you know, sometimes you're like, you know, make sure testing. It's like, I'm going to try pytest with these crazy options. You're like, why did you think that was going to work? Instead, you just give it exactly what it should be.
We could give it more flexibility in how it runs things, but in this case, like we already know like this is how you run tests in the project. So we just give it a test function. Like that's probably the biggest thing in like creating reliable agents with Dagger is like giving flexibility where it's important for completing tasks and removing it where you know exactly how things are meant to happen.
So you know exactly how tests need to run. So it doesn't need the freedom to just run any command in a container. We know, okay, all you need to do is modify files and run this test function. And for more complex agents, maybe there's some other functions there too, but for this one, like this is the amount of freedom we've given it.
Can we like open another.
Well, hold on. So we got Cloud.
Oh, okay. Okay, we got Cloud. So yeah, we'll get back to my pipe tree in a second.
Allright. So let me see if I can expand this. And so this is like the visibility that we want to see when we're running these agents. So we saw the prompt and we saw the assignment is to make the main page say hello workshop people.
Cool. And then, so this is a prompt we gave it. Now, Claude 3.5 is looking at this and saying, first, let's look at what objects we have and check out the workspace, make the changes, and then run the tests.
Sounds good. It runs list objects, which lets it see what it has in its environment, which is like this workspace tool,right? Cool. And then it's going to say list methods. So it's going to see what it can do with a workspace, like what the heck is a workspace.
It says it has tools to edit and test code. And then we expand that. And so this is like this kind of visibility into the agent's environment where we say, oh, there's this workspace write file function that gives it back a workspace type.
And these are the arguments.
Oh, you mean, so we don't have to write any of the JSON kind of, you know, description of tools. It just gets generated from the functions.
Yeah. So we just gave it that Dagger module and then it all got wired up into the agent's environment. And so it says, cool, let me select these methods. So now I have these as tools to call. And then let's see what's in the project.
So it's going to call workspace list files. And remember the way that it does that in our workspace code was it creates like an Alpine container and runs tree. And so we can see the tracing of that too, which is like the underlying actions of the tools being called.
We also see the return of that, which is what the agent sees. And it sees this whole file structure. Cool. And then we can see. Says, cool. Sounds to make it say that we should probably modify this one or this one.
So let's see what's in those files. We can see it read the file. And that's, it's going to see this whole file of
the word hello world.vu that says, okay, I don't think that was it. Let's see the app.vu. And then it reads that file. And then eventually it says, I see that that app.vu uses the hello world component and passes a message to it.
So now it's going to write the file. It's going to change app.vu to pass a different message to it. And let's see, we can expand this to see the whole thing. Yes. Awesome.
Nice.
So hopefully if this ever, if it doesn't finish, it's fine because we're going to push it to GitHub in a second and then GitHub can run it for us. But now it's running those tests. So this is the part that it's currently at in my shell where it's been running for like five minutes.
So yeah, that's the visibility part I'm talking about where we can see exactly what the agent sees and what's happening under the hood.
So then this is, to be clear,right? So this is all running on your laptop and yet it's all inside that Dagger engine in containers, totally isolated from your laptop.
Dagger Cloud is just showing me the visualization. It's not running anything for me. This is on my machine, which is why it's still running.
Well,right. And this is like because of the connection we have and because of, you know, whatever the load we're putting on it. But the other thing to think about is it could be like we're using Python here. We're using Node,right?
We're using a bunch of different tools. So like the app is Node, but the workflows that Kyle's writing are in Python. You could have a laptop, say, or any server that just has Dagger and a connection to the internet and you don't need any tools installed.
So that's why the environments, environments is not just for the agent developer. I mean, it kind of goes all the way through. So you could have a brand new laptop with just Dagger and it would, because it's using a Python runtime container for the workflow he wrote in Python, that's just implicitly there.
So you don't need to install Python. You don't need to struggle with VMs or any other versions or whatever. It's just, it's done. And then inside of that somewhere, there's Node container that happened,right, in order to create this environment, the build env and the build and all that.
And that, again, it's all just nested inside of there and cached and everything else automatically. So you could kind of just do this with a very bare-bones machine setup and everything will just work.
Yeah. So what we can see that we probably won't get to run this part locally just because I don't, we'll come back to it if it finishes. But anyway, I'll just describe this flow here where we say, okay, we're in shell.
That happens. Like we ran that develop thing and it gave us back something. But now in Dagger, like I keep saying, we're in shell. Dagger, when you type Dagger and get into
this view, it is a shell, just like Bash,right, where we can actually do things like create variables and chain things together. And so what we could do if this finished is say, okay, let's actually save that output of this thing because remember it returns a directory.
Save that to a variable called completed. And then we could pass that to our other functions because remember they default to using our Git source from our machine, but we could pass in that optional directory to all of our functions to say, use this directory instead.
So now I could actually run the whole thing as like a local, like I could see the results of this before even saving it to my machine. So let me just go over here. I don't know why I keep any of this folder, but we'll go to the correct directory
and we'll open another shell here. And I'll just type in part of this command because what I can do is I can run the output from the agent as like I can run the whole site. I can build it and serve it to my machine.
And I can see what it's built before I even save it back to my disk to say, yes, this is a good solution. So once we get this connection here, just waiting on pipes to connect to each other.
And we'll let that run for a second. But the main thing is we can pass this around. We can run all of our functions with that completed directory and then finally say, allright, we say export. That saves it back to your disk and we're done.
So the next step is, allright, we're good with that. We know how to use this agent locally to ask it to make cool tasks. That's fine. But my people requesting features on my site, they don't have this installed.
GitHub Workflow55:14
They don't have Docker and Dagger installed on their machine. They don't want to use Dagger shell. They just want to go to GitHub and say, make this new feature. So that's the next step here. And it sounds ambitious, but it's really quick.
So we've got plenty of time to look at the solution here. And we'll look at it in Python once again. And so the first thing we're going to do is actually install another dependency from the Dagger verse. And this is my module called GitHub issue.
And it's basically if we go to Dagger verse.
We saw it installed earlier when you showed us that Dagger JSON.
Exactly. That's because I skipped ahead.
Oh, I see.
Yeah.
Nice.
So if we search for that and we have this module called GitHub issue, it's got a bunch of functions that let us do things with GitHub issues. Like we can list GitHub issues in a repo. We can list the comments on a particular issue.
We can write comments. We can create pull request comments, all kinds of things with GitHub issues and GitHub pull requests. So with this module where I've just basically used the GitHub Go SDK in this Go module to connect my Dagger functions to the API calls, I can install this in my Python project.
And now I can have the ability to work with GitHub issues. And so all it needs is a GitHub token. And so we create, we add another function to our code called develop issue. So remember we created develop.
Now it's develop issue. And all this is going to do is say we have a GitHub issue out there with our feature request. We want to read that GitHub issue, give it to our agent. The agent's going to do all its things, then give us back a directory.
We're going to take that directory and make a pull request.
Oh, so like really similar to like the assignment that we gave it, instead it's going to be reading the GitHub issue. And instead of just getting the directory back ourselves, we put the directory into a PR.
Yep. So you can see the code here. And so this is the entire thing here where we're not writing a new agent to do this. We're using our other agent. We're just, we're wrapping it with some other pieces to say, go here to get the assignment.
Once it's done, put that completed work over here, which is the from here was like read a GitHub issue. And then we get that assignment and I can open the editor. So it's probably easier to see.
Okay. So we get that GitHub issue. From that issue, we get the assignment from the issue body. We pass that to our develop function because this is our agent and say, here's your assignment. Here's the source, which came from that same defaulted input argument.
And then we get the issue title and URL, which is going to be really cool because then we can actually in GitHub automatically have the new pull request linked to the GitHub issue just by having this, the body say closes this issue.
And that's going to create a pull request. And so this whole thing, like you can run this part locally too. You don't have to run this part in GitHub, but it just takes the GitHub token and an issue and the repo name so it knows where to put the PR.
And then it does that whole flow. But we actually want that to run in GitHub. And that's super easy. So we've made that thing. We just saw the code. Now we create a GitHub Actions workflow. The first two things we need to do is in the repo, we need to create two repo secrets, one for our cloud token.
Again, that part's optional. But if you want to see all those things happen in Dagger Cloud, you just put that token in the environment. And then whatever LLM key you're using, so the same one I use locally is going to be in that repo secret.
So if I go over here in my repo and I say, and I zoom out a bit so I get all the buttons. I say settings.
We wait for the page to load. And then down here under secrets and variables, actions, I have two repo secrets here that we just saw from that screenshot.
Make it big again.
Sure. And then there's one more thing, which is, let's see, that's how we get our Dagger cloud token to paste in there. There's a little checkbox we have to press over here to let GitHub Actions create PRs because that's disabled by default.
So if I go under, okay, under actions general, and then at the very bottom, there's this checkbox allow GitHub Actions to create and approve pull requests. So I've done that. Now I just need to create a workflow. And the workflow is super short.
This is the thing you can copy paste. And I'll open it up over here under GitHub workflows. We have develop. And so now we have this GitHub Actions. If you haven't used GitHub Actions, I'll explain this real quick, but it's basically a CI platform.
And we have, with this configuration, we tell it when events happen, go do these things. So in this case, we say when a GitHub issue is labeled and the label is called develop, then run this command. And this command is the Dagger call develop issue with those arguments like GitHub token, the issue ID, and the repo.
And these things are all coming from GitHub Actions automatically. So like the environment's GitHub token is created here where we say this command needs a GitHub token with permissions to write contents. Contents are like commits to your project, read the issues, and write pull requests.
And so we've put that in the environments. We've given it the API key for our LLM and the cloud token. And so now just by running this Dagger call, that connects the dots where GitHub Actions, whenever we create that label, is going to run that Dagger function.
And that Dagger function has all the capabilities to run the agents and open a PR.
So that's like us in the Dagger shell when we call, when we are running like the develop function or some other build function or whatever, this is just having GitHub Actions run the develop issue function for us.
Yep.
Why are you having GitHub Actions do it? So that it takes into the issues?
So we're having GitHub Actions do it because we want this flow to be automated inside GitHub. So I'll show the flow real quick, but it can run anywhere. So you can run it. It doesn't matter.
It doesn't matter where it runs.
Yep. This just happens to be GitHub Actions because we're already in a GitHub repo. It's free because this is like, we're not using any crazy compute to run this thing. And most of the hard stuff's happening on your LLM that you're paying for.
And they have better internet connection at GitHub than GitHub today.
Exactly. So let's say, let's create a new issue and we'll say change the greeting. And we want to, what did we ask for before? We asked for like the main page, say.
Live PR1:02:26
Hello workshop, something like that.
Hello workshop people. Okay. So we'll create this GitHub issue. And remember this, this whole thing kicks off when I add the label develop. And so I've already run this on this repo and obviously made a typo as well at one point.
But if you don't have it there, you can just say foo and you'll have a button to say create a new label develop. So we want to call it develop.
So I click that and now my issue has been labeled. And so now that kicks off GitHub Actions to call my Dagger thing. So let's go over here in the actions tab and we should see something running. And it says change the greeting.
And we can watch this run over here. We can also pull it up in cloud because remember I put that cloud token in there because this stuff is all too hard to see flying by my screen in real time.
So let's go back here.
And this is GitHub Actions,right? But it could be any kind of orchestration or CI orchestration. It could be Jenkins, could be GitLab CI, it could be anything, Azure, DevOps, whatever you got. Yeah, question.
How much, if any, like prompt modification are you guys doing? Is it literally just what's in that one Markdown file or do you add, like is it aware that it's in Dagger or?
It is. Yeah. So we have, the question is like how much prompt modification does the agent have? Dagger has its own system prompt that it adds that kind of guides it towards like how you use tools within Dagger.
So it knows like call the select methods and list functions and those things we saw doing. You can add more to the system prompt. You can get rid of that system prompt if you want to. But yeah, there is a default one.
Yeah.
We have to make further edits because the agent is not able to develop theright code or logic.
Yeah.
How do we correct after the develop but before the rest of the stuff?
Yeah. So if the agent does something, if it calls develop and it runs and it produces something that we say, okay, that's notright. How do we go back and say, make these changes?
Can we just edit the completed source?
Oh, yeah. So yeah. So you can edit the completed source if you want. If you say, if you see the source and say, oh, it needs one more change. Or I can show you another function where we say, we have an ability to give it more feedback to say, okay, you've done this so far.
Here's some more changes to make because you didn't get it quiteright. And so we'll see that happening. Yeah, go ahead.
What's the possibility you can give Dagger to Dagger Agent access to the test directory? So that on purpose, so it doesn't write like junk tests, just so that the test passes.
The test directory.
Or it doesn't have access to it?
I think it should. Yeah. So the question was giving the agent access to the test directory. I think in tests it runs that. And I think in our workspace we just give it the.
We give it like the full source of the repo. So it could get down in there if it wanted to.
Yeah. I think it's kind of a funny thing, like making sure the tests pass because sometimes if the agent broke the test, it'll go change the test. And sometimes that's correct,right? Sometimes we actually change the behavior and the tests need to be updated.
But maybe more often that's not correct. So you might want to maybe have that as part of your prompting or part of your validation to say, make sure the agent didn't change the test or
it's kind of tough to decide like whether that's correct or not. Yeah.
I noticed that there wasn't the Dagger install step. Is that done behind the scenes by the action?
So in.
It's a one-liner.
Yeah, yeah. So in our workflow, we installed Dagger, but it's really just, there's a Dagger for GitHub Action. And so we just said.
Oh, a three-liner in this case.
Three-liner. Yeah. So we said this version of Dagger, but this installs Dagger in your GitHub Actions runtime basically. So we used checkout to check out a repo and then this to install Dagger.
The dependencies, like can you install the dependencies, like external dependencies? Wasn't there like a GitHub issue one?
Oh, yeah.
Does that happen automatically?
Yeah, exactly. So this is in our Dagger JSON, we have all of our dependencies listed. And so you don't have to say like Dagger install or anything. When we say Dagger install, it adds it to this and then we just run it.
We don't have to do anything like npm install like that. It just, it knows to make sure your client's generated.
But that is the nice thing about having those dependencies
in a file saved in Git alongside the project. So because like what we've done essentially, like when we first got this project, this view app project, it didn't have any Dagger. It didn't have anything,right? It was just like an app that you could run.
And then we said, oh, well, let's Dagger in it in this thing. And then we got that little dot Dagger where we started developing our build and test functions,right? Kind of like our tools for development or for CI, just alongside.
And then in there is where we've been installing more modules, like the workspace, the GitHub issues module, like anything else you would need. So now, and that's all in Git. So the thing's now like this fully loaded like Daggerized project.
So it's kind of carrying around its own tools on its back for working, you know, just for a developer to use or platform engineer to use or for an agent to use.
Yeah. We're just like waiting for things to load here. Yeah, go ahead.
Have you gotten anything like Dagger in Dagger where you have it spinning up like agent fleets and maybe different roles?
Yeah. Yeah. Yeah. So that's, I mean, myself as someone that builds a lot of Dagger code, I have agents that need to write Dagger code. And so to reliably validate those things, they need basically Dagger inside of Dagger.
So that's exactly like a thing that you can do. And I can even pull up, if we go to, we're a bit short on time, but we're basically done with that guy.
Yeah, we're just waiting for it to run.
Yeah. But we have
Advanced Agents1:08:58
an examples thing here on the docs. And there's tons of examples here. But one of the really cool ones that I like the most because I wrote it is.
I thought you were going to show mine, but that's fine.
Let's see. No, it's fine. It's fine.
Oh, it's not. Okay.
Oh.
We're going to add to the list of examples.
We're going to add to the list. It's going to be an even cooler list soon.
So we have.
What's your question next?
Yeah. There's this repo under my GitHub, KPenfound slash Dagger Programmer. And this thing is something I use to, like in the docs we saw those tabs of all the different languages. And so whenever I write a new guide, I have to have it in five languages.
And so this agent can take it in one language and produce all the languages. And that's just an agent that knows how to write Dagger. And so to do that, it has a lot of cool things in addition to be able to like run Dagger in Dagger.
So if you look at the code for that, it's just like.
This one's in TypeScript.
Yeah, this is the TypeScript one. And when it runs tests, it runs the Dagger thing. And there's this flag privilege nesting so that the inner container can talk to the engine. And this is writing Dagger code basically.
Yeah. Question here.
Curious, how does this relate to MCP? And will you use Dagger to implement MCP servers? And is there some overlap because you have all these modules, which maybe you could imagine having multiple MCPs as a different mechanism?
Yeah, absolutely. So one way to think about it is we were kind of doing this thing with Dagger modules before MCP came on the scene. And then obviously we're like, oh, this is super aligned with the way we think things should be in a lot of ways.
And so you can today even take a Dagger module and you can say Dagger dash M, the name of the module, MCP. And so you can expose a Dagger module as an MCP server, for example. And yeah, we've got some more things that we'll be probably sharing soon about that kind of stuff.
But yes, we think the vision is compatible in that way. And yeah, you can use the MCP ecosystem as well.
Yeah. So there's a few different layers here,right? There's within our agent that we just built, we installed modules and that uses basically our internal implementation of MCP to talk between modules within Dagger. But you can also take a Dagger module, expose it as an MCP server, and then in, I don't know, the near future, next week or something, you could connect to external MCP servers to bring them into Dagger as well.
Yeah. I mean, I wanted to speak clearly, like the internal implementation, it's before MCP. So it's not MCP per se, but it very much logically you can think of it in a similar way. Yeah. And because you can expose everything as MCP servers, it ends up being practically very much the same for users.
Check it out. We got our PR.
What?
Finally.
Oh, we got a PR?
So we got our PR open, says make the main page say that. It closes that issue we created. We have that commit pushed up and we see the user is this GitHub Actions bot. And we have on the welcome.vue, it changed from documentation to, so maybe that'sright.
Oh, I deleted this other thing too because it decided that's not needed.
Who deleted it?
Cool. So we have a really cool agent. Yeah, it needs lots of.
It's just vibing back there, you know, the agent's just like.
But yeah, the main thing is we were able to get it to run in GitHub. So I was able to request that feature and it ran hands-free. And now.
Is that the thing that just deleted?
Yeah, exactly. Soright now we only built in the one thing where it says we create an issue, that's a feature request. But if we look at, I think on this examples list, we have this one, this greetings API, which is my main demo project.
And it has a ton of stuff in it. There's like five different agents in here. And one of them is I want to give feedback on a PR. And so we can probably open one of these. And I say, I give it some feedback.
I say slash agent, add this other feature. So this one, the original one is like make a new endpoint for my API. And then it did that. And then I say, okay, here's some feedback. The endpoint should be authenticated.
And then it picks up again and pushes some new changes. And then I have another agent where I say slash review. And that will create a review for my PR with any other changes that I need. And then I can say, okay, make those changes.
And then also please don't delete all the tests. Very important to add.
And that could be like you don't have to be inserting yourself at every one of those points,right? But in this case, it's great for when we're showing it.
Yeah. If you want an example of how you can take what that workshop just built to the next level where you have all this feedback and more advanced things, this is a great repo to look at, this greetings API, because it has all of these different agents doing tons of things.
It even has one where if we look at if I as a human push up a broken thing, because we still have humans developing stuff sometimes,right? So I pushed a broken thing and the test failed, which is super annoying because I skipped running tests because I didn't have a good prompt that told me to run tests three times.
This agent can actually look at the test failure automatically and propose a fix for that, that I can just click on it and fix that test change,right? So this is all stuff in this demo repo where you can see like how to build all these things yourself.
So question over here.
There's a lot I really love here. I just had a question almost getting at the motivation for some of this stuff.
Yes.
It feels like there's a world where Dagger could have really prioritized just like the containers, the workflows, and let you just bring your own AI agent. Like what's the motivation behind making it its own primitive and going down that path?
I think there's a lot of levels here,right? Like if you're already really baked into like Pydantic or OpenAI Agents SDK, you can still use those container workflows in that. And I'll show it. Maybe I shouldn't, but I have.
So crazy.
If you've done the OpenAI Agents quick start, if it loads here, or sorry, this is the agent quick start we have, but with the agent SDK, where I've used the OpenAI agent SDK that says like, here's my completion model.
This is actually using Ollama. This is what their SDK looks like. But in that SDK, I'm actually still using Dagger. So I actually recreated that same workspace where you have read file, write file, and build. But I've created that with Dagger inside of the OpenAI agents SDK.
So I'm using their agent, but using Dagger code for the containers.
Is breaking counter like why you use Dagger? I guess it's a bit lighter.
Yeah, the main thing is like this, I had to write all of these tools and how to use them. If it's all within Dagger, you get that cool thing where we have that whole Dagger versus modules. I can just plug one in and that's just given to the agent,right?
Yeah, your whole method signature is instantly translated into theright form to work with tools,right? You get tools for free as well as functions. And yeah, and we do have some people in our community that are using Dagger. They're like with Pydantic and other things where they're just like, they want the sandbox capability because they're like, oh, I don't want to, you know, maybe I don't want to use another cloud sandbox vendor or whatever.
I want to have it locally, but I don't want it on my computer in my file system either. I want containers. I want it easy. So yeah. But I think, yeah, the sweet spot is kind of doing it all because it just harmonizes really well.
Yeah.
Question there.
Thanks for the great demo. So I had a question. Let's say if I want to build an agent for programming HTML games.
Yes.
Which run in browser. So for that game building agent, I would need the testing, so the running and testing environment to be browser.
Yes.
So does Dagger have those sort of constructs? Like let's say if I want to spin up a browser environment and then do some kind of automation in that for testing that game which the LLM might have written.
Yeah. I mean, you certainly can. I mean, I've done some headless browser stuff. I've also done some browser stuff and then connect over VNC or different. Yeah, you can do a lot of, you know,
you can do a lot of stuff with Linux containers. So yeah, we should talk about it. You should come in the community. Let's like do it. Yeah.
First of all, great demo and thanks for compressing a lot of information. So is my understanding that you build CI/CD, infra, and all these things once and then let Dagger do the asynchronous job with guardrails and, you know, all the things in place?
Like is my understanding that Dagger is sort of this asynchronous AI agent that does things on its own, but with guardrails, not just leaving Claude code or something in a trust all mode and then let it do its thing?
Is thatright?
I think, yeah, so the question was like, yeah, what is Dagger in a certain sense too? But Dagger gives you this platform to create these software engineering workflows that can be used for shipping software, that can be used for developing software, you know, and the environments that we saw.
And then you can use them as a platform engineer or as a developer, but then you can also hand them off to agents. And so we think that's really powerful, the fact that you can use that same platform to do all those things and to create those guardrails, like you say.
You can. The one thing I wanted to show, and you got one minute, can you just show your terminal and just let's get vibey for just one second. So you're connected to an LLMright now,right? So go ahead, just like let's talk to this LLM.
So it turns out that we've been using the shell mode, which lets you, you know, kind of like very declaratively say like I want container from Alpine with this file and give me a terminal into that or whatever.
Now, what we've done is we just had, we're like, we're chatting now directly with the connected LLM. And this LLM can see all the Dagger objects you have. So another way you can use Dagger is you can just say like, allright, I'm just going to create this container.
And I'm going to say, hey, LLM, you see that container? Why don't you write some software in it? So you can get that kind of kind of workflow going too. So there you go. So he's actually saying like, hey, give me a Python container.
And so it's going to actually look and see what methods exist in the Dagger API. And it's, oh, there's this container method in the API, which we were using earlier. And then it's going to like, you know, decide, oh, I'm going to use container, maybe from, container from, container with exec to execute.
So these are just, it's exploring the Dagger APIright now.
Got it.
And now it's going to like, it's actually pulling a Python 3.11 container. Then it can do things with that. So, you know, it's actually using containers like kind of like computer use or something like that. But so yeah, so you can get, you can go, we didn't even show that side of it because, you know, we're trying to show the guardrails, but you can also use it in this kind of a style too.
Got it. And one follow-up question. Typically, LLMs are good at small to medium tasks, and that's what we have seen like a small to medium task here. How good is Dagger at orchestrating like a large task which needs design or some user input or, you know, multi-turn prompt?
Like, you know, not a small medium task, but a large task. How good is Dagger with that?
Yeah, the question is like the size of tasks that Dagger is good for. I think if you make it, if you decompose things down and you can architect thingsright, it can handle a lot of different sizes. And we should, I know we're at time now, so we're going to like, we're going to end here.
We'll take some more questions outside the room.
But in the hall, for sure. Thank you so much for everybody that attended.
Thank you guys.





