← All AI Engineer talks

AI Engineer World's Fair 2025

Ship Agents that Ship: A Hands-On Workshop for SWE Agent Builders

About this talk

Dagger presenters Kyle Penfound and Jeremy Adams demonstrate how to build a production-minded software engineering agent, starting from a Hello Dagger application template and giving the agent narrowly scoped tools for inspecting a workspace, editing files, and running tests. They discuss balancing autonomy against reliability, demonstrate Claude-assisted code changes and a GitHub issue-label-triggered workflow, and examine TypeScript implementations, nested container execution, and more advanced example repositories. Audience questions and intermittent workshop connectivity problems are also captured.

Chapters

  1. 0:00Introductions, workshop setup, and deploying agents to GitHub
  2. 14:35Hello Dagger template and practical agent tool boundaries
  3. 25:34Workspace access, project analysis, and Claude-driven testing
  4. 54:41Reviewing generated changes and triggering GitHub issue workflows
  5. 1:09:24TypeScript examples, privileged nesting, advanced agents, and audience questions

Talk transcript

  1. 0:00

    [upbeat music] Okay, we're gonna kick this off.

  2. 0:16

    Uh, we're trying to sort out some internet options here, but, uh, in the meantime, I'll, uh, give us our little intro. Um, so first of all, we're... I'm Kyle, this is Jeremy.

  3. 0:27

    We're from Dagger. Uh, and you'll see more about what Dagger is through this workshop, where we're gonna build a cool, uh, sweet agent, and we're actually gonna deploy it to GitHub.

  4. 0:38

    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 gonna be out of our internet hands, and it's all gonna be really cool.

  5. 0:49

    So, uh, first of all, on the left side here... Cool. Uh, on the left side here, we have kind of where we're getting started from. So this is the, the documentation site where we have, uh, install instructions.

  6. 1:04

    So I'll, I'll walk through those real quick. Um, and then our quick starts, where we're actually gonna walk through these as, like, the content of this workshop. Um, and then also a shout-out to, uh, tomorrow night.

  7. 1:16

    We have a, a hack night at the Cloudflare office. It's on the, the, um, external events list for, uh, this conference as well. Um, but here's a QR code for it.

  8. 1:29

    Paul. Paul.

  9. 1:30

    Um, okay, so real quick.

  10. 1:33

    What's the Slack? No other way of doing it. So there's a, there's a que-

  11. 1:36

    Yeah, go for it

  12. 1:36

    ... there's a question about whether there's a Slack, I think. You're s- Slack for the workshop? Slack for the workshop? Yes, absolutely.

  13. 1:41

    Mm.

  14. 1:41

    So if you go to the Slack, there's, it says dagger-workshop.

  15. 1:48

    Ship agents that ship. Is... Got it? Okay. [laughs]

  16. 1:51

    Cool. Let me s- pull that up as well. So if there's questions, put them in there or raise your hand, and Jeremy will get to you. Climb over people.

  17. 1:59

    I will. I will do-

  18. 1:59

    And yeah, make it happen.

  19. 2:01

    Yes. I'll do my best.

  20. 2:03

    Awesome. So, um, yeah, if, if everyone, if you're following along, awesome. If, if you can't, like, because you don't have desk room or, uh, can't get the internet or whatever, I'm gonna walk through it live 'cause I already have everything on my machine.

  21. 2:17

    Um, and then you can always, uh, you know, check back with this later on once you have a, a solid connection. Um, 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 gonna be really neat.

  22. 2:31

    Um, but if you are following along, uh, here's the installation page on, uh, docs.dagger.io. So you can install, um, from the Homebrew tab or, uh, straight from our install script, or with Winget, uh, you can install the Dagger CLI.

  23. 2:50

    Um, the only other dependency is that you need a container runtime such as Docker or Podman or, uh, nerdctl, so, like anything that can run containers, uh, because Dagger itself runs its engine as a container, and I'll explain what that means in a second.

  24. 3:04

    But, uh, if you're following along, get started on this while I talk through a bunch of stuff about what we're actually doing and what, um, all these technologies are trying to accomplish.

  25. 3:14

    So-

  26. 3:14

    I'll take, I'll take, I'll-

  27. 3:15

    Yep, go for it

  28. 3:15

    ... pause you really quick. Yeah, just for the, for the folks on the tech team, um, and so for some of you in the room, we're having-- we've, we're finding the Wi-Fi may or may not work for you.

  29. 3:25

    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, uh, for the tech team, it's requiring a password for me to use this service.

  30. 3:39

    So, um, anyway, if, if you have that, slip me a note at some point. Um, but otherwise- We're working on it ... yeah, we're working on, we're working on getting more connectivity as we speak.

  31. 3:49

    Awesome.

  32. 3:51

    Can you put the QR code one more time?

  33. 3:51

    Yep. There we go. Uh, so the QR is actually for the, the, uh, hack night tomorrow night. The, um, the docs and what we're going through are at docs.dagger.io.

  34. 4:01

    Um, so that's, like, the main content for what we're gonna walk through. Um, and I guess real quick, we can intro as well, if you wanna intro yourself first, Jeremy.

  35. 4:10

    Yeah, sure. I'm Jeremy Adams. I look after kind of the ecosystem. Uh, I'm part of the ecosystem team that Kyle and I are both on. And, uh, I've been at Dagger for a few years, and so I've got to see already, uh, a progression of folks using us for all sorts of things, and most recently, a lot

  36. 4:32

    around AI agent-

  37. 4:33

    Mm-hmm

  38. 4:33

    ... kind of workflows. Um, but I love in this workshop, we're gonna blend together some of the classic use cases we've seen with Dagger around CI, um, and dev workflows, as well as, you know, giving those to agents.

  39. 4:48

    Awesome.

  40. 4:48

    Go, Kyle.

  41. 4:48

    Yeah. I'm, I'm Kyle. Um, I'm on the same team.

  42. 4:51

    Yep.

  43. 4:51

    Um, and I have a background in, like, DevOps and platform engineering, uh, so much more on the, the kind of cloud infra side of things versus, um, that building side.

  44. 5:02

    So i- it's cool to come at this from, uh, that perspective of, you know, trying to deploy agents somewhere and, and make things work. And that's why in this workshop, we're gonna deploy things to GitHub because that's, uh, eventually what you're gonna wanna do when you build an agent.

  45. 5:17

    You have to put it somewhere to run it. Uh, it can't just live on your machine all the time, uh, I guess, depending on what agent it is. Anyway, um, so if, if you made it this far, you've made it to the docs, uh, then we're going to talk a bit about what Dagger is and why we're

  46. 5:32

    building agents with it. Um, and so basically, Dagger is, like I said, it's a, um, container runtime. It's a workflow engine. And so people have historically done things like build their CI/CD with Dagger 'cause you're building these pipelines that orchestrate containers, run all these tasks, uh, and it runs the same on your machine as it runs in

  47. 5:54

    any cloud, like in, um, you know, in your Kubernetes, in GitHub, wherever your CI might run, but it runs the same everywhere. So you're making these workflows, uh, and the cool thing is that's also what agents are, right?

  48. 6:08

    Is that they're, they're just these processes where we have, um, we have

  49. 6:15

    A bunch of tools you wanna give to an agent. Um, anyway, okay, we're g- we're gonna see in action.

  50. 6:19

    Yes.

  51. 6:20

    Um, and so, uh, let's see. We have components, right? So Dagger itself is made up of, uh, core components like containers, like I said, also repos, directories, files, and now LLMs are also a component that you have to work with, uh, within this kind of toolbox of Dagger and how we're building things.

  52. 6:41

    And so it's just another building block, right? It's not, uh, a framework special- like, just built for making an agent, then you have it living next to your software.

  53. 6:49

    It's another component within your toolbox, and so you're bringing LLMs into these existing workflows, um, and that's why it's a little bit different.

  54. 6:58

    Yeah. You could think... A-another way of thinking about Dagger in a nutshell is, Dagger is for software engineering workflows and environments. So you're gonna see us building some environments, essentially some containerized environments with some functions, and all of these things can become tools that, you know, human software engineers, uh, AI agents, uh, use for both development side

  55. 7:23

    as well as, uh, app delivery side of things. So you'll see that kind of... Of course, these, these areas are all blending and kind of squishing together right now.

  56. 7:31

    We're seeing all this stuff happen in, in real time. So Dagger is kind of, uh, gonna be one tool that you could use for that whole range.

  57. 7:39

    Um, can you say... You explained Dagger as a tool to build containerized environments. What's the, what's the distinction between Dagger and Docker?

  58. 7:46

    Yeah. So the question was, uh, 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.

  59. 8:00

    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.

  60. 8:11

    So now what we're doing is we're taking a whole workflow and making that a portable thing.

  61. 8:16

    And that's containers?

  62. 8:17

    So yeah, there's definitely multiple containers and other types of objects, but everything's, everything's sandboxed by default. So you get... So yeah, and we'll see as we get into it.

  63. 8:27

    Great question.

  64. 8:28

    Yeah. So we, uh, we're, 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.

  65. 8:38

    Um, 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. Um, Dagger has this cross-language interop.

  66. 8:48

    So if I write a cool Dagger module, um, with... Oh, it's, it's gonna wanna load. That's why I have it in.

  67. 8:54

    Oh.

  68. 8:55

    Yeah.

  69. 8:55

    You're amazing.

  70. 8:56

    Yeah.

  71. 8:56

    Yeah.

  72. 8:57

    Error occurred. That's why.

  73. 8:58

    Wow, okay.

  74. 8:59

    Um, I don't know. Okay. [laughs] So, um-

  75. 9:04

    I broke it

  76. 9:05

    ... i-if I write a cool module with Dagger that, say, does like, um, a TypeScript build or something, right? Um, I, I can share this on the Daggerverse, and maybe I wrote that module in TypeScript, and you're writing your modules in, uh, Python.

  77. 9:21

    You can just install my module, and you have these n-uh, native bindings in your language, uh, to work with Dagger modules cross-language. So anyway, that's, that's my point, in that we're not...

  78. 9:30

    When you pick a language, you still get to benefit from the whole Dagger ecosystem.

  79. 9:35

    Um, and we don't have images on these. That's okay.

  80. 9:38

    There's some sweet animations there-

  81. 9:40

    Yeah. Imagine, like-

  82. 9:41

    ... of like code happening. It's so cool

  83. 9:42

    ... yeah, like the coolest animation you could think of.

  84. 9:45

    Yeah.

  85. 9:45

    Um, awesome. So I think we could probably skip forward here.

  86. 9:48

    Yeah.

  87. 9:49

    Um, and so, uh, it... Hopefully, we, we've installed or we're downloading, we're... maybe we're still downloading, um, Dagger. Uh, so run through real quick, um, kinda the basics of Dagger.

  88. 10:00

    So hopefully that's big enough. Maybe I'll make it a bit bigger.

  89. 10:03

    Yeah, it's good.

  90. 10:06

    Um, there we go.

  91. 10:06

    Yeah.

  92. 10:07

    Cool. So we've, uh, we've installed Dagger. We've got these things, uh, like, uh, container runtime somewhere. Um, 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,

  93. 10:23

    um-

  94. 10:23

    That's definitely gonna get bigger.

  95. 10:25

    Yeah, yeah. So I'm in Dagger shell, and I can say container, I think. I don't know.

  96. 10:39

    Let's go over here. Fighting the Internet. Uh.

  97. 10:49

    And so what Kyle's showing is there's, like, a few different ways of using Dagger, and you, uh, on the command line, and, um, 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.

  98. 11:04

    Or you can use it in this kinda interactive shell mode that he's showing here.

  99. 11:08

    Yeah, and it's all, 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. Uh, but with our code, we're actually gonna be building larger blocks out of those blocks, uh, to assemble, like, a, an actual, like, part of a workflow, and then I'll

  100. 11:24

    take those blocks, build bigger workflows out of those. So as, 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, uh, Alpine, and now I've got an Alpine container, and I can get, uh, a-- We can do things with that, like anything you

  101. 11:44

    might wanna do with a container, right? So I could literally say, uh, "Give me a terminal," and now I've got a terminal in a container. Uh, and this is the exact kind of tools that we're actually giving to our agent as we're building these pipelines, right?

  102. 11:56

    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. Uh, so it's a lot of setup to say that we've got all these, these primitives that we can give to agents to build some really effective software engineering agents, uh, by giving them

  103. 12:15

    the exact tools they need to complete the job. Um, but also, like we mentioned, uh, earlier- People use Dagger for CI/CD because you can create these workflows for, you know, running your tests for your application or whatever.

  104. 12:28

    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 test the same way that your developers and your CI do,

  105. 12:41

    uh, to make sure that the code it's generating is valid code and that can, it can iterate on these things within the agent. So this is all what we're gonna build right now.

  106. 12:49

    Um-

  107. 12:49

    Yeah, and we were just talking to somebody outside before the session, uh, who was telling us that in, in his organization, they get, uh, you know, not infrequently now because of people like a product manager who's discovered vibe coding or a team that's using, uh, you know, AI-powered IDEs or whatever, that people are like cranking out these

  108. 13:14

    like massive PRs for him to review, like 25,000-line PRs and like, the, and 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."

  109. 13:29

    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, some balance back.

  110. 13:43

    Yep.

  111. 13:43

    You know, we 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, at some point?

  112. 13:54

    So we need to balance out and make sure that there's, uh, software delivery workflows that are there to, to test and build and validate things before we put them out in production.

  113. 14:05

    So some of what we'll get into today.

  114. 14:08

    Awesome. So yeah, let's actually get into writing something. So zoom 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.

  115. 14:18

    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.

  116. 14:26

    Uh, so it's just gonna be a real quick thing where we kind of set up this, uh, example project with functions that know how to build and test the project.

  117. 14:35

    Um, so I'm on this page, and we've already talked through installing Dagger, uh, and we talked a bit through the basics. Um, so now we have this example application called Hello Dagger Template, and if you go to GitHub and say Use this template, uh, you can name it whatever you want, like Hello Dagger Workshop or just Hello

  118. 14:54

    Dagger, it doesn't matter. Uh, you can create a, a repo in your GitHub from this template, and the important reason for that versus cloning it is that that's gonna make it way easier when we actually push things to GitHub in a little bit, uh, to make it easier for you to, uh, run the GitHub Actions that actually

  119. 15:11

    run the agent. Um, so we're gonna use that template, and I've done that over here

  120. 15:18

    in this repo where I have my Hello Dagger Py, uh, because I've done this in every language. Uh, you can use whatever language you wanna use. Uh, I'll be walking through Python today 'cause I think that's probably what a lot of people, uh, here today are most comfortable with.

  121. 15:34

    Um, but if you're not, I can switch between languages. Just raise your hand and say, "Show me Go," um, and that's okay. So

  122. 15:43

    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, uh, view app that has a bunch of things in it.

  123. 15:59

    But the main thing is we want to be able to make an agent that develops it, right? Um, optionally you can configure Dagger Cloud, which is... Let me just start loading that webpage now. [laughs]

  124. 16:12

    Um, it's basically a visualization, so you can really easily see what your agent's doing. Right? 'Cause that's the hardest part of building agents a lot of the time is understanding like what are they tripping on, what, what's actually going on inside the agent?

  125. 16:24

    How is it interacting with its tools? What tools is, is it even seeing? Um, so with this visualization, visualization, you're able to really easily see, uh, everything that your agent's doing, and that's helped me a lot like develop my prompts.

  126. 16:37

    Like if I see, um, the prompts and environments, right? If I see a lot of the times that, okay, the, the agent fails 'cause 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.

  127. 16:51

    Um, and so being able to see how the agent's behaving is a huge part of that. Um, whether you're using Cloud or, or any other thing to visualize your agents, that's like the most important part of, um, making it reliable.

  128. 17:03

    Um, okay. So we've cloned the project. We now wanna create a Dagger module. So if you've installed Dagger, uh, you'll run this command, Dagger init, uh, with whatever SDK you're using.

  129. 17:14

    So we have these tabs here. Um, so I'm gonna be using Python and then the name of the module is gonna be Hello Dagger and that's important because that is basically the name of our, um, object that gets created.

  130. 17:26

    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 Zed, but we can-

  131. 17:36

    It's in the, uh, it's in the, uh, preferences.

  132. 17:41

    To zoom the sidebar?

  133. 17:42

    Command comma.

  134. 17:47

    Oh.

  135. 17:47

    You command comma and it'll... Yeah.

  136. 17:49

    Yeah.

  137. 17:49

    And you just put the, there's a, the top. There's a, there's a s-

  138. 17:55

    Well I guess you don't have your set, but it's a- [laughs] It's a font size.

  139. 17:59

    Font size.

  140. 18:01

    That one. UI font size. Change it to like twenty-five or something. Watch it.

  141. 18:07

    There you go. Save that. Bam.

  142. 18:09

    Boom. Okay. So now hopefully we can see the sidebar a bit better. Um, so I'm in this .dagger directory and apparently I've written Go for this one. Is this...

  143. 18:19

    Oh, because that's the wrong project. Cool. Uh, let's go to the correct project.

  144. 18:26

    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've generated when we said dagger init, it'll have, um, basically these files, but some different content.

  145. 18:43

    So it's gonna have, like, the, the basic generated things, uh, to get you started building modules. But we're gonna say, um, see dagger functions.

  146. 18:54

    It'll show us what's available on 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, uh, interact with your application.

  147. 19:07

    So for example, this build one, uh, 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, uh, is from this base, and we put these files in it, and we run this command.

  148. 19:25

    And so in that container, when we wanna do a build of our app, uh, we can

  149. 19:31

    call that other function to get that container with our, 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.

  150. 19:43

    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.

  151. 19:53

    Oh wait, give me an im- from an image from Alpine or from Node or from whatever." And then you can layer on more things like add a directory, a source code to that, run, uh, exec a test command, whatever, right?

  152. 20:05

    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.

  153. 20:15

    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-

  154. 20:23

    Yeah

  155. 20:23

    ... one unified cache where all that stuff is being, uh, all those cached operations are at, and, and one API. So that's why it becomes really easy to use different languages, different language SDKs, 'cause it's ultimately all one API under the hood.

  156. 20:39

    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, test, uh, and that buildenv one we looked at, uh, and buildenv as in, like, your build environment.

  157. 20:56

    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, we've got the project that we want to build the agent in.

  158. 21:07

    We've got, um, 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. Um, and so now I'll zoom out again so you can see, 'cause I jumped to the next page here, which is add an AI agent to an existing project.

  159. 21:23

    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, our, um, build, buildenv, publish, test in our Dagger functions.

  160. 21:36

    Lots of useful functions, but-

  161. 21:38

    Yeah

  162. 21:38

    ... the expectation was the human was probably running those, right? You-- or you were-

  163. 21:43

    Exactly

  164. 21:43

    ... having them run in CI. You'd kind of set that up. But nothing really agentic yet.

  165. 21:49

    Right. So we have, you know, we're just running our unit tests or our, our build and creating a production container. And this is what, uh, you as a developer or your, your CI environment are running these functions.

  166. 22:00

    But now we want to create an agent for developers to interact with, um, or, you know, to run anywhere. But also our agent should be able to use these functions as well.

  167. 22:10

    Um, and so we're in this, this next guide, and we're going to now create a sub-module. 'Cause I mentioned, like, our agents want these, uh, refined environments where we give them access to exactly what tools they need to complete their tasks.

  168. 22:24

    We don't-- and n-nothing more than that.

  169. 22:25

    No, no. Wait. I thought you were gonna give agents, like, every possible tool. You wanna let them have, like, a thousand functions that do very powerful things and just let them run crazy.

  170. 22:36

    Is that not the-

  171. 22:37

    Well-

  172. 22:37

    ... best practice at this point?

  173. 22:38

    The, uh, yeah, m-maybe not based on the, the smiles across the room.

  174. 22:42

    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?

  175. 22:53

    So in a lot of cases we're working with MCPs. It might-- we might have a lot of static tool kind of experience. You know, what if things change? What, what, what does happen, Kyle?

  176. 23:01

    Well, so the, the main thing is, like, you want the right amount of tools to, for that agent to solve its task, uh, whatever that task is. Like, it needs the flexibility, uh, to, to be able to solve complex problems.

  177. 23:13

    Uh, 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.

  178. 23:21

    It needs the amount of tools to select, to choose its own path, uh, to solve whatever task you throw at it. But you don't want so many tools that now this is a, a generalized agent that does anything, right?

  179. 23:32

    Right.

  180. 23:32

    It needs to have some amount of focus so that it can solve a specific set of problems really well.

  181. 23:38

    But we will see, like in the agent loop that's gonna happen, we will see the ability for the a-- for the LLM to see this, like, menu of tools it has, and then for it to select the right tool at the right time given the context.

  182. 23:52

    Yeah. But yeah, definitely, like, a big part of iterating and building these agents is determining, like, the scope of the tools. So, like, um, the, kind of the balance between flexibility and reliability, uh, where you want it to be able to solve a breadth of problems, uh, so it needs a variety of tools that it might need.

  183. 24:10

    You don't know exactly what it's gonna need ahead of time, but you don't wanna give it so many that now it's getting lost and confused and fails half the time, right?

  184. 24:18

    And so that's what we're gonna focus on here with this. Uh, we're gonna create a, a sub-module basically that is kind of its, its playground. Its specific set of tools that lets it, uh, edit our source code.

  185. 24:29

    And so if you've worked with, uh, maybe agent frameworks in the past that have, like, file system tools- We're actually gonna build that in our own code right now.

  186. 24:39

    Um, and that... 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, we're creating these building blocks, and as you scale this up, uh, you can consume these from...

  187. 24:49

    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 gonna write it all. And so-

  188. 24:57

    All right. What are we gonna give the... What are we gonna give... Look, we're putting this workspace. What kind of functions are we giving it?

  189. 25:01

    Yeah. So we, we do another Dagger init here, and we say, uh, .dagger/workspace. So we've created, in our file system, another subdirectory here, uh, workspace under .dagger. And so this is another Dagger module.

  190. 25:15

    Um, and this one's just gonna... Just the functions that we want the agent to have access to. Um, so you can imagine it wants to read the files in your source tree.

  191. 25:23

    Uh, 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.

  192. 25:34

    Um, and so we give it a function to read a file from that. Um, so it just gets the .contents of that file. Um, and that's just the Dagger API to say, "This is a path through a file.

  193. 25:44

    I can do lots of things with the file. One of those is to look at the contents." Um, another function it needs is to be able to write files to the workspace, obviously.

  194. 25:52

    Uh, and so it's very similar API here, where we say, "Okay, give me the path and also the contents to write to that file." Uh, 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 gonna literally do a tree in

  195. 26:08

    that workspace so it can quickly see the, the file structure of your code. Um, and so now basically with those three, we have another one that we're gonna look at in a second.

  196. 26:17

    But with those three now can do all the code editing you might ask it to do within your, your file system, right? And with, with more complex, um, projects, you might need more advanced capabilities of these.

  197. 26:30

    Like you might ne- 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 building right now, it's like just the most basic where we can just read and write files and list the files.

  198. 26:44

    Um-

  199. 26:44

    So if the agent had access to this workspace object, it would see those functions as tools, read file, write file. It, it basically-

  200. 26:55

    Exactly. It will in a minute, yeah.

  201. 26:56

    Yeah.

  202. 26:56

    One, one-

  203. 26:56

    Not yet. We haven't-

  204. 26:57

    Not yet

  205. 26:57

    ... we haven't plugged the, the brain into the robot body yet. We haven't-

  206. 27:00

    Right. So right 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. Uh, and the brain is gonna come in just a second here.

  207. 27:09

    Which could be any LLM. I mean, kind of-

  208. 27:11

    Yeah

  209. 27:11

    ... the brain in a jar, right? Analogy.

  210. 27:13

    Okay. So our last one finally that I mentioned earlier, um, is test. So when it g- generates this code in, in its, uh, workspace, it needs to be able to test to make sure that the code it generated is correct.

  211. 27:25

    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, the most important part of building this good agent is some sort of validation tool, whether that's like a, a test or a lint or just something to check that what it's generated, uh, is correct.

  212. 27:44

    Uh, 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.

  213. 27:57

    And if I run... I think I have the function down here. If I say dagger.m, so now dash m points to a da- a specific Dagger module, and I say functions.

  214. 28:08

    Remember before we ran just Dagger functions. But if I run dagger-m.dagger/workspace functions, I'll see, uh, exactly those functions that we just, uh, created. Okay. So the next step is we want our main Dagger module to have that as a set of tools it can use.

  215. 28:27

    And so we're going to say dagger install .workspace module. So now, uh, 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.

  216. 28:40

    But basically, all, all your dependencies of Dagger, like I mentioned, like we have, um, 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 Daggerverse, which is this massive index of like thousands of Dagger modules that do different specialized things.

  217. 29:00

    But whenever you install one of these into a Dagger module, it creates... If you look at my dagger.json in this, uh, project, uh, we have this list of dependencies.

  218. 29:12

    And so your, your, um, 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, uh, like I mentioned earlier, like native in this language, uh, you'll see all of these things available on the, the main Dagger client.

  219. 29:31

    So you can do, uh, 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, our tests and builds.

  220. 29:43

    Uh, 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, uh, or modifications or whatever.

  221. 29:52

    So that's the next step in this guide we're looking at, where we wanna create an agentic function. So-

  222. 29:58

    Could, could we have mixed and matched? Like could we have written that workspace in TypeScript or in Go and still installed it into our Python module?

  223. 30:09

    Yeah, exactly. So like the other modules... A- any individual module can be written in any language, and you can mix and match however you want.

  224. 30:17

    I knew the answer to the question. I was just, you know, check- just checking. But, 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 bla- back end platform team, and maybe the- these folks are TypeScript, these folks are Go,

  225. 30:31

    but they can interop and use their stuff. So yeah.

  226. 30:34

    Yeah. So like every- everything, every task or workflow or whatever that you do with Dagger is, uh, a function in your code. And so an agent is no different, right?

  227. 30:42

    It's just gonna be another function, uh, and we're gonna call this one Develop 'Cause we're gonna ask it... We're gonna give it an assignment to complete in our project, uh, and it's going to complete that assignment.

  228. 30:53

    So the, the develop function is our agent. Uh, 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.

  229. 31:03

    Don't worry, it's only like 500 lines. [laughs] Totally fine.

  230. 31:07

    And you know what? It's, it's, it's really short. And-

  231. 31:09

    Oh, wait. H- it's not 500 lines?

  232. 31:11

    Yeah, this is, this is it right here. So we have a few lines. Maybe-

  233. 31:15

    You have it all, like, spaced out nicely.

  234. 31:17

    Yeah, it's...

  235. 31:17

    Yeah.

  236. 31:18

    So we have, um, a new function called Develop, uh, and it takes in an assignment. And this annotated thing is just a Python way of getting us these, these, um, doc strings for the parameters.

  237. 31:30

    But it... 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 in, say, Dagger functions.

  238. 31:43

    Uh, it'll say, "The assignment parameter is assignment to complete," which is really cool. Uh, and we see our source here, which is like our project source. Uh, but of course, we don't wanna have to pass that as a parameter when we're calling our agent.

  239. 31:55

    Uh, so there's this cool thing with Dagger where you just say default path is slash, and that's gonna be the root of our Git repo. Uh, so if we don't pass in, uh, explicitly a source parameter, it's just gonna pass in our Git repo as that parameter.

  240. 32:08

    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 agent real quick.

  241. 32:18

    So the environment is like the main thing, right? And I, I've used that word a lot today, and hopefully a lot of people are using the same word in the same way.

  242. 32:27

    But w- you, you have your, uh, 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, um,

  243. 32:40

    uh, your, your inputs and outputs for the agent, um, any, any objects or state that it's working with, all of this is the environment. And so we wanna construct this environment and then plug in the LLM, which is our brain, and say, "Here's your environment.

  244. 32:55

    Here's your task/prompt, and complete the task." Um, and so this is, this is the environment we put together, where the assignment is a string input. Um, so we ha- we have this cool kind of way of, um, declaratively building your prompt, right?

  245. 33:13

    Where our assignment is the assignment to complete, but this workspace input is a workspace with tools to edit and test code. So now the- our agent, when we connect these things, will, will see this as the description of this thing that it can use and say, "Okay, we're, we're building out this prompt by, uh, annotating our code,"

  246. 33:31

    basically. And so with this workspace input thing, that's referring to the sub-module we just created. So if-

  247. 33:38

    The workspace.

  248. 33:39

    Exactly.

  249. 33:40

    Yeah.

  250. 33:40

    So if we called that something else, like foo workspace, and we installed that, this would be with foo workspace input, right? We're, we're dynamically generating all of these functions for the environment type to say, um,

  251. 33:57

    a- any objects in my dependencies I can have as an input or an output of, uh, my environment. And so we notice that we also have a workspace output, which is the completed task.

  252. 34:08

    Um, because all objects in Dagger are immutable, and so you... I give it an object, it's going to do a bunch of things and give me back a different object that's c- it's completed task.

  253. 34:20

    Um, and maybe that's like a boring detail, but the main thing is the thing I passed in is still gonna be the same, but it's going to have a new version that's given me back called Completed.

  254. 34:31

    I mean, I think a, 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?

  255. 34:39

    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.

  256. 34:46

    These are typed inputs. We're expecting a typed output back in the end," and this gives us a way to ensure that, uh, we're getting what we actually asked for.

  257. 34:57

    That's right. And now, w- uh, next we, we need our prompt. So we have the environment and the prompt, and we give both of those to the agent, basically.

  258. 35:05

    Um, so the prompt, I believe, is just a bit lower here, if you're following, following along here. So it wants you to create a .dagger/develop prompt.markdown, and it looks like this.

  259. 35:17

    So I'll just open it o- again over here on my editor.

  260. 35:22

    So this is our prompt. And so we're saying, "You're a developer on this project. You're gonna give... You're gonna get an assignment and the tools to complete it. Your assignment is $assignment."

  261. 35:33

    And so this is basically, it's gonna be templated in by the assignment in our environment. So it's gonna drop that right in that prompt so the, the agent itself doesn't have to go read this other variable in its environment.

  262. 35:47

    It knows, "Okay, my assignment is make this cool new feature." And then we have a bit of prompt structure here, right? Where, uh, if you've built a lot of these agents, y- you've probably kind of refined how you build your prompts and what those structures look like.

  263. 36:02

    Uh, this is a really simple agent, so it doesn't have a ton of structure. But we do say, uh, "Before you write code, make sure you analyze the workspace to understand the project structure."

  264. 36:12

    So it's not just gonna create some garbage and be like, "Cool, I made this new file, uh, but I didn't look at the project first." Um, don't make unnecessary changes, 'cause sometimes, uh, you'll see, especially certain models, uh, without the right constraints, will go make the change you asked for and then change four other things and be

  265. 36:28

    like, "Cool, it looks good. Ship it." Um, and always run the test. So we do have to ask it to run the test once it's made those changes. So it, it's not just gonna see the test function and be like, "Oh, I should probably call that."

  266. 36:41

    We wanna 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." Uh, and then don't stop until you've completed the assignment and the test passed.

  267. 36:52

    So this is telling it, you know, keep working until you've satisfied what I asked it to do, and the test passed.

  268. 36:59

    Some good reinforcement. You kind of, like, told it run the test twice. [laughs]

  269. 37:02

    Oh, yeah.

  270. 37:02

    Yeah, you better... Yeah, and this has comes from experience, right?

  271. 37:04

    And may- maybe a third time will help too, I'll say.

  272. 37:06

    It, it doesn't hurt at all [laughs] because, yeah, and, and maybe in all caps. Because it's like, what, what we find, we end up running evals on these things, right?

  273. 37:13

    Where we'll try different LLMs plugged in, and then we'll iterate someth- on the prompts and until we're getting the results, the consistency we want across the different, the different ones.

  274. 37:24

    And, um, and yeah, it, it comes from experience of knowing, like-

  275. 37:27

    Yeah

  276. 37:28

    ... how they veer off track and etc., how we're writing these.

  277. 37:32

    Yeah, and that's like when, when I mentioned earlier, like using something like Dagger Cloud to be able to visual... or see the visualization of all the work the agent's doing.

  278. 37:41

    If I'm frequently seeing like, okay, the, the agent's 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 gonna be different for every model, and especially, like, the prompt structure is different for different models.

  279. 37:55

    Is it possible to implement things like reflection agents as well to police each other?

  280. 38:00

    Yeah, yeah.

  281. 38:01

    Yeah.

  282. 38:01

    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.

  283. 38:09

    Um, but yeah, like, remember, in the... with this, each agent is just a Dagger function, and so you can create all these agents layered on a- other agents. Um, and even in your environment, you could actually put an agent in the environment and say, "Hey, you have this ava- this agent at your disposal, uh, if you need

  284. 38:28

    it to do something," right? And I have examples of that too, but it's, like, similar to the, the concept of, like, Google's A2A, where you, you say, uh... If you're not familiar with that, it's basically this, um, structure where you tell an agent, "Listen, you can do these things, but you also can talk to these other agents,"

  285. 38:45

    and that's what each of these other agents do. And so if you need to, you can reach out to them and say, "Hey, other agent, um, I need you to tell me how to write TypeScript," and that comes back, right?

  286. 38:55

    So you, you can put agents in environments. It's all just piecing functions together, right? It's, it's just the same code we've always been writing, but now there's an LLM component.

  287. 39:05

    Um, cool. So now this line right 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.

  288. 39:18

    Make it bigger just for a second, you know? Just-

  289. 39:20

    Sure, yeah

  290. 39:20

    ... so it's off the screen since it's so important. [laughs]

  291. 39:23

    I feel like it's not even getting that much bigger. It's just... [laughs]

  292. 39:26

    So huge.

  293. 39:27

    Yeah, there we go.

  294. 39:27

    Yeah.

  295. 39:28

    Uh, cool. So, like, we, we've said, all right, from the Dagger client, we need this LLM type. Uh, we give it an environment, we give it a prompt, and that's the agent.

  296. 39:38

    So now we've got this thing work that is a, a Dagger LLM-

  297. 39:43

    See, people want pictures-

  298. 39:43

    ... with these things

  299. 39:44

    ... of it. You gotta, you gotta-

  300. 39:45

    Oh, yeah

  301. 39:45

    ... center it and make it look good. There you go.

  302. 39:47

    Boom. I can-

  303. 39:48

    If you need your pictures-

  304. 39:49

    I can give one for buy it

  305. 39:49

    ... you can get one with Kyle and... [laughs]

  306. 39:53

    Commemorative. We've got, like, frames outside. You can slide it in after.

  307. 39:56

    Yes.

  308. 39:57

    Cool.

  309. 39:57

    I'll autograph it. Um-

  310. 39:58

    Yeah

  311. 39:59

    ... so that, that's the agent. Like, that's literally... Because we've asked it, like, we, we've said in this prompt... We didn't really ask. We told it. We told it in the prompt, uh, this is, this is your task.

  312. 40:09

    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.

  313. 40:24

    'Cause you remember in our-

  314. 40:25

    Oh, yeah

  315. 40:25

    ... environment, we defined a workspace output called completed, and this thing should be a workspace. If it's not, somebody screwed up. Uh, that happens sometimes. Um-

  316. 40:35

    It's a good final check.

  317. 40:37

    Exactly.

  318. 40:37

    A good type check. Yeah.

  319. 40:38

    And so from that workspace, we wanna grab the completed directory, which is the source. So if you remember in our workspace

  320. 40:48

    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 'cause maybe that's gonna break in my machine.

  321. 41:03

    Yeah.

  322. 41:03

    Uh, and then now that we've got that, just to make triple sure, 'cause remember... I mean, we, we did tell it three times to run tests.

  323. 41:10

    We told it to test.

  324. 41:11

    But now we get this back, and in our code, we're saying, "All right, now run the test," 'cause this is all the same code that we're using throughout our project to run tests.

  325. 41:20

    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."

  326. 41:28

    That's pretty huge, right?

  327. 41:29

    Yeah.

  328. 41:29

    So that's like, like, trying to put the agents on, on rails or give them guard rails-

  329. 41:33

    Mm-hmm

  330. 41:33

    ... 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?

  331. 41:46

    Yeah.

  332. 41:46

    It could be compliance things, could be, like you say, linting, testing, whatever.

  333. 41:49

    So, so we don't just dump that-

  334. 41:51

    Garbage

  335. 41:52

    ... that garbage back to your machine.

  336. 41:53

    Yeah.

  337. 41:54

    Uh, 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.

  338. 42:07

    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 passed, and then we say, "Okay, return that completed directory."

  339. 42:21

    And so now this function, uh, and we'll just triple check here on the guide side they didn't miss anything. We say Dagger functions, and we have this Develop one that shows here.

  340. 42:33

    So now if I go into Dagger shell, which is hopefully what it asks us to do... It is. I say hopefully. I wrote this, so, you know, this... we're just checking myself here. [laughs]

  341. 42:44

    Um, and I can go in and say Dagger. Now, before I do that, um, one thing I don't think I called out at the very start here was that we had to, like, configure an LLM provider.

  342. 42:54

    Mm.

  343. 42:54

    So with Dagger, you bring your own model. You can use OpenAI, Gemini, Anthropic, um-

  344. 42:59

    Local models

  345. 43:00

    ... Ollama, Docker Model Runner. Like, lit- literally any-

  346. 43:03

    Whatever. Bedrock. Anything

  347. 43:04

    ... anything you can hook up to. Bedrock.

  348. 43:05

    Yeah.

  349. 43:05

    Um, so you do have to configure Some environment variables to be able to s- for Dagger to make API calls to that, right? Because we're just, we're just the agent with the tools.

  350. 43:17

    The model's living somewhere else. Um, and so this is... This configuration page, configuration/llm, uh, shows all the different options on how to configure things. Um, one really cool thing to call out, I'm just going to type something really scary.

  351. 43:37

    Um-

  352. 43:38

    Oh my gosh. [laughs]

  353. 43:39

    So Dagger also has cool secrets provider integrations. So I don't have-

  354. 43:44

    Phew

  355. 43:44

    ... my actual API key, uh, echoed there. I just have my one password reference, uh, just sitting in one password somewhere. Um, and so

  356. 43:54

    let's see. Yeah, so it's just pointing at this credential.

  357. 43:57

    Oh.

  358. 43:57

    Yeah, and then if I reveal in plain text [laughs]

  359. 44:00

    Whoa. [laughs]

  360. 44:03

    Um, so I, I've configured this in my environment, so now when I say dagger,

  361. 44:08

    um, 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, 'cause if you are following along, we're gonna push this to GitHub in a second, and r- it's gonna run in GitHub, and it's gonna be on GitHub's

  362. 44:22

    network, so we don't have to be, uh, beholden to that. But now-

  363. 44:25

    Can you run LLM in-

  364. 44:26

    Yeah, exactly. So now if I say llm | model, for example, uh, where you see my little one password prompt.

  365. 44:34

    Nice.

  366. 44:35

    So it's got my key. It's gonna take a second to think about it. Uh, and so with each model provider, we have a default model, but you can also specify one, and we can also specify one in code.

  367. 44:45

    But right now by default, it's gonna use Claude 3.5. Uh, so maybe we're not gonna get the best results, but we'll see.

  368. 44:50

    It's OG.

  369. 44:50

    Yes.

  370. 44:51

    Classic. Yeah.

  371. 44:51

    A classic. Yes.

  372. 44:53

    Yeah.

  373. 44:53

    Um, cool. So now I have that, and I can say -help, and we have that new develop function, right? So I can say -help develop, and so this is the thing we just made where-

  374. 45:05

    Can you bump that up a little bit?

  375. 45:07

    Bigger? For sure, yeah.

  376. 45:08

    Perfect. Thank you.

  377. 45:09

    Uh, so we have that required argument of assignment, and that was our assignment's complete. We have an optional argument source, which again, is just gonna be my repo, and this is gonna give us back a directory.

  378. 45:20

    Uh, so here's how I use it. I just say develop and then do the assignment. 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.

  379. 45:32

    So let's ask it to-

  380. 45:34

    Super basic

  381. 45:34

    ... I think in here we say, um,

  382. 45:39

    the example thing is to make the main page blue, and I'll say, "Make the main page say, 'Hello workshop people.'"

  383. 45:48

    Whoa. Doesn't say that right now.

  384. 45:49

    Um, and I've never run this, so I don't... Uh, maybe it'll s-succeed. And so now we can see this happening. We see our prompt's getting passed in. We see the little, uh, person face.

  385. 45:58

    That's the prompting and the little robot head of the model, which is Claude 3.5 Sonnet saying, "Cool, let me do these things." And it... We can s- actually see it calling tools, right?

  386. 46:08

    So it's, it's, uh, looking at the functions available. We see the workspace list files.

  387. 46:13

    Oh, it's the tools you said. Yeah, list files.

  388. 46:14

    Yeah, the ones that we made.

  389. 46:15

    Yeah.

  390. 46:16

    Um, 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, it now sees the contents of this, and while this is running, let me just open up Claude, and hopefully this'll load.

  391. 46:32

    Oh, yeah.

  392. 46:32

    Um, so we can actually see, like, the, the Claude visualization of this, 'cause it's maybe a bit easier to see 'cause we... Where it's... Oh. Gotta sign in. [laughs]

  393. 46:44

    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. We'll-

  394. 46:51

    It's the same, it's the same OpenTelemetry in both places, so that-

  395. 46:55

    Yeah

  396. 46:55

    ... you're getting streaming to your terminal UI and the web UI. People say-

  397. 46:58

    So we, we see it 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 [laughs] that really might fail on this Wi-Fi 'cause it's install...

  398. 47:09

    It's doing an NPM install and downloading a bunch of NPM modules or node modules. But it's, uh... It should pass in a second. Uh, we'll just let it go, and we'll talk through it.

  399. 47:18

    But we, we can see that our agent is actually... It wrote the files, and then it's writing... It's running the tests, which is really awesome. Uh, cool. So this opened up over here.

  400. 47:28

    And-

  401. 47:28

    So the, the with NPM install-

  402. 47:30

    Yeah

  403. 47:30

    ... that was part of the tool that you gave it or it's-

  404. 47:33

    Um, so this is... Oh yeah, so it's... So we see it's saying, like, with exec NPM install, with exec NPM run test unit. If we go back to our workspace

  405. 47:46

    and our test function-

  406. 47:48

    That was you

  407. 47:48

    ... that was part of it. So this is like i- the agent just had to call test-

  408. 47:52

    Yeah

  409. 47:52

    ... and we've defined what happens when you call test. And so-

  410. 47:55

    It's not like the random ones, like, you know, sometimes you're like, "You know, make sure testing," and it's like, "I'll, I'm gonna try PyTest with these crazy options."

  411. 48:02

    Right.

  412. 48:02

    And you're like, "Why did you think that was gonna work?" [laughs] So instead you just give it, you know, exactly what it should be.

  413. 48:07

    We, 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.

  414. 48:14

    So we just give it a test func- Like, that's probably the biggest thing in, like, creating reliable agents with Dagger is, like,

  415. 48:22

    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, uh, so it doesn't need the freedom to just run any command in a container.

  416. 48:34

    We know, okay, all you need to do is modify files and run this test function. Um, 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.

  417. 48:47

    Can we, can we, like, open another, uh-

  418. 48:51

    Well, hold on. So we got Claude.

  419. 48:52

    Oh, okay, okay. We got Claude, so-

  420. 48:53

    Yeah

  421. 48:54

    ... we'll, we'll get back to my pipe dream in a second.

  422. 48:56

    All right. So let me see if I can expand this. Uh, and so this is, like, the visibility that we wanna 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."

  423. 49:09

    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 w- what objects we have, and check out the workspace, make the changes, and then run the tests."

  424. 49:20

    Sounds good. It runs list objects, which lets it see, uh, what it has in its environment, which is like this, this workspace tool, right? Cool, and then it's gonna say list methods, so it's gonna see what it can do with a workspace.

  425. 49:34

    Like what the heck is a workspace? It says it has tools to edit and test code, and then we e- 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.

  426. 49:50

    Oh, you mean so we didn't have to write any of the JSON kind of, you know, description of tools. It just gets generated from the functions.

  427. 49:57

    Yeah. So we just gave it that, 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."

  428. 50:09

    So it's gonna call workspace list files, and remember the, the way that it does that in our workspace code was it creates like an Alpine container and runs tree.

  429. 50:17

    And so we can see the tracing of that too, which is like the underlying, uh, 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.

  430. 50:30

    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.

  431. 50:40

    We can see it read the file, and that's, uh, it's gonna see this whole file of, um, the word Hello World.view. And it says, "Okay, I don't think that was it.

  432. 50:52

    Let's see-" [laughs] "... the app.view." And then it reads that file, and then eventually it says, "I see that that wor- that app.view uses the Hello World component and passes a message to it."

  433. 51:04

    So now it's gonna write the file... It's gonna change app.view to pass a different message to it. Um, and let's see. We can expand this to see the whole thing.

  434. 51:13

    Yes. Awesome.

  435. 51:14

    Nice.

  436. 51:14

    So hopefully if this ever f- if it doesn't finish, it's fine, because we're gonna push it to GitHub in a second. Um, and then GitHub can run it for us.

  437. 51:23

    But now it's running those tests. So this is the part that it's currently at in my shell, um, where it's been running for like five minutes. Um, so yeah, that- that's the, the visibility part I'm talking about where y- we can see exactly what the agent sees and what's happening under the hood.

  438. 51:36

    Um-

  439. 51:36

    So then this is-

  440. 51:37

    Yes.

  441. 51:37

    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-

  442. 51:48

    Exactly

  443. 51:48

    ... from your laptop.

  444. 51:49

    So this 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.

  445. 51:56

    Well, right. And th- and this is like because of the connection we have, and because of, you know, whatever, the, the load we're putting on it. But it's... The, the other thing to think about is it could be like, uh, we're using Python here, we're using Node, right?

  446. 52:10

    We're using a bunch of different tools. So like the app is Node, but the, the, uh, 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.

  447. 52:28

    So that's why the environments... Environments is not just for the agent and developer. I mean, it's, 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.

  448. 52:43

    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 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.

  449. 52:59

    And that, again, it's all just n- nested inside of there, and, and cached and everything else automatically. So you can, you could kind of just do this with a very bare bones machine setup, and everything will just work.

  450. 53:13

    Yeah. So w- well, we can see that we probably won't get to run this part locally, just 'cause, um, I don't... We'll, we'll come back to it if it finishes.

  451. 53:21

    But anyway, I'll just describe this flow here where we say, "Okay, we're in shell. That happened." Like we, we ran that Develop thing, and it, it gave us back something.

  452. 53:30

    But now in Dagger, like I keep saying, we're in shell. Dagger... When you type Dagger and get into that, um, this view, it is a shell, just like Bash, right?

  453. 53:42

    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, the output of this thing," because remember it returns a directory.

  454. 53:55

    Save that to a variable called completed, and then we could pass that to our other functions, because remember they, they default to using our Git source from our machine.

  455. 54:04

    But we could, 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, uh, as like a lo- like I could see the results of this before even saving it to my machine.

  456. 54:18

    So let me just go over here. I don't know why I keep ending up in this folder, but we'll go, uh, to the correct directory.

  457. 54:29

    And we'll open another shell here, and I'll just type in part of this command. Um, because what, what I can do is I can run the output from the agent as like I can run the whole site.

  458. 54:41

    I can build it and serve it to my machine. Uh, 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."

  459. 54:49

    Um, so once we, uh, get this connection here...

  460. 54:54

    Just waiting on pipes to connect to each other. Um,

  461. 55:00

    and we'll, we'll let that run for a second. But, uh, the main thing is we, we can pass this around. We can run all of our functions with that completed directory, and then finally say, "All right."

  462. 55:09

    We say export. That saves it back to your disk, and we're done So the next step is, all right, we're, we're good with that. We, we know how to use this agent locally to ask it to make cool tasks.

  463. 55:20

    That's fine. But my, my people are requesting features on my site. They don't have this installed. They don't have Docker and Dagger installed on their machine. They don't wanna use Dagger Shell.

  464. 55:31

    They just wanna go to GitHub and say, "Make this new feature." So that's the next step here and, and it sounds ambitious, but it's really quick. Um, so we've got plenty of time to, to look at the solution here, and we'll look at it in Python once again.

  465. 55:44

    And so the first thing we're gonna do is actually install anoth- another dependency from the Daggerverse, and this is my module called GitHub Issue. And it's basically if we go to Daggerverse-

  466. 55:56

    But we saw it installed earlier when you showed us that Dagger JSON with the dependencies.

  467. 55:59

    Exactly. But that's 'cause I skipped ahead.

  468. 56:01

    Oh, I see.

  469. 56:02

    Yeah.

  470. 56:02

    Nice.

  471. 56:05

    Um, so if we search for that, and we have this module called GitHub Issue, uh, it's got a bunch of functions that let us do things with GitHub issues.

  472. 56:14

    Like, um, we can list GitHub issues in a repo. We can list the comments on a particular issue. We can write comments. Uh, we can create pull request comments.

  473. 56:26

    Um, all kinds of things with GitHub issues and GitHub pull requests. So with this module where I've just basically used the,

  474. 56:34

    uh, GitHub Go SDK in this Go module to connect my Dagger functions to the API calls, I can install this on my Python project, and now I, I can have the ability to work with GitHub issues.

  475. 56:48

    And so all it needs is a GitHub token. And so we create... We add another function to our code, um, called develop issue. So remember, we would create develop.

  476. 56:57

    Now it's develop issue. And all this is gonna do is say we have a GitHub issue out there with our feature request. We wanna read that GitHub issue, give it to our agent.

  477. 57:07

    The agent's gonna do all its things, then give us back a directory. We're gonna take that directory and make a pull request. And-

  478. 57:12

    Oh, so, like, really similar to, like, the assignment that we gave it. Instead, it's gonna be reading the GitHub issue. And instead of just getting the directory back ourselves, we put the directory into a PR.

  479. 57:22

    Yep. So we can see the code here.

  480. 57:23

    Yeah. Yeah.

  481. 57:23

    Um, 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, we're wrapping it with some other pieces to say, "Go here to get the assignment.

  482. 57:35

    Once it's done, put that completed work over here." Uh, which is the from here was, like, read a GitHub issue, uh, and then we get that assignment. And I can open the editor so it's probably easier to see.

  483. 57:49

    Um, okay, so we, we get that, uh, GitHub issue. From that issue, we get the assignment from the issue body. Uh, we pass that to our develop function 'cause this is our agent and say, "Here's your assignment.

  484. 58:02

    Here's the source," uh, which came from that same defaulted, uh, input argument. Uh, and then we, uh, get the issue title and URL, uh, which is gonna be really cool because then we actually in GitHub automatically have the new pull request linked to the GitHub issue, uh, just by having this...

  485. 58:24

    The body say, "Closes this issue." Uh, and that's gonna create a, a pull request. And so this whole thing, like, you can run this part locally too. You don't, you don't have to run this part in GitHub.

  486. 58:34

    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

  487. 58:43

    does that whole flow. But we actually want, want that to run in GitHub, and that's super easy. Um, so we've made that thing. We just saw the code. Uh, now we create a GitHub Actions workflow.

  488. 58:53

    Uh, 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 is optional.

  489. 59:03

    Um, but if you wanna 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, uh, I used locally, is gonna be in that repo secret.

  490. 59:14

    So if I go over here in my repo and I say... Uh, and I zoom out a bit so I get all the buttons. I say Settings.

  491. 59:24

    We wait for the page to load. And then down here under Secrets and Variables, Actions,

  492. 59:34

    I have two repo secrets here that we just saw from that screenshot. Um-

  493. 59:38

    Make it big again.

  494. 59:39

    Sure. Um, and then there's one more thing which is, uh... Let's see. That's how we get our Dagger Cloud token to paste in there. Um, there's a little checkbox we have to press over here to let GitHub Actions create PRs, uh, 'cause that's disabled by default.

  495. 59:57

    Uh, so if I go under, um, okay, uh, under Actions, General,

  496. 1:00:06

    and then at the very bottom-

  497. 1:00:08

    Right there

  498. 1:00:08

    ... there's this checkbox, "Allow GitHub Actions to create and approve pull requests." So I've done that. Uh, now I just need to create a workflow, and the workflow is super short.

  499. 1:00:19

    Um, this is a thing you can copy-paste, and I'll open it up over here.

  500. 1:00:24

    Um, under GitHub Workflows, we have Develop. And so now we have... This is GitHub Actions. If you ever haven't used GitHub Actions, I'll explain this real quick. But it's basically, uh, a CI platform, and we have...

  501. 1:00:37

    With this configuration, we tell it, uh, when thi- when events happen, uh, 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.

  502. 1:00:52

    And this command is the Dagger called Develop Issue with those arguments like GitHub token, the issue ID, and the repo. And these things are all coming from GitHub Actions automatically.

  503. 1:01:02

    So, like, the environment's GitHub token is created here where we say this, uh, this command needs a GitHub token with permissions to write contents. Contents are, like, commits to your project.

  504. 1:01:17

    Uh, read the issues and write pull requests. Uh, and so we've put that in the environments. We've given it, given it the API key for our LLM and the cloud token.

  505. 1:01:28

    Um, and so now just by running this Dagger call, that connects the dots where GitHub Actions, whenever we create that label, is gonna run that Dagger function, and that Dagger function has all the capabilities to run the agents and open a PR.

  506. 1:01:40

    So that's like us in the Dagger shell when we call... When we are running, like, the develop function or, uh, some other build function or whatever. This is just having GitHub Actions run the develop issue function for us.

  507. 1:01:52

    Yep.

  508. 1:01:53

    Why, why are you having GitHub Actions do it? So that it does it into the issues?

  509. 1:01:57

    Um, 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 in-

  510. 1:02:06

    It doesn't matter. As long as you-

  511. 1:02:07

    It doesn't matter where.

  512. 1:02:07

    It doesn't matter where it runs.

  513. 1:02:07

    Yep. Uh, this just happens to be GitHub a- GitHub Actions because we're already in a GitHub repo. It's free 'cause this is, like, uh, uh... 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 anyways.

  514. 1:02:22

    And they have better internet connection at GitHub than we do today.

  515. 1:02:24

    Exactly. [laughs] So let's say-

  516. 1:02:26

    Yeah.

  517. 1:02:27

    Let, let's create a new issue, and we'll say change the greeting. And we want to... What, what did we ask for before? We asked for, like, make-

  518. 1:02:37

    NYT

  519. 1:02:37

    ... the main page say hello-

  520. 1:02:40

    Uh, workshop, something like that

  521. 1:02:41

    ... hello workshop people.

  522. 1:02:44

    Yes.

  523. 1:02:45

    Okay, so we'll create this GitHub issue. And remember, this, this whole thing kicks off when I add the label Develop. Uh, and so I've already run this on this repo, and obviously made a typo as well at one point.

  524. 1:02:57

    Um, 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, uh, Develop. So we wanna call it Develop.

  525. 1:03:07

    Um, 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.

  526. 1:03:21

    And it says change the greeting, and we can watch this run over here. We can also pull it up in cloud, 'cause remember I put that cloud token in there, 'cause this stuff is all too hard to see, uh, flying by my screen in real time.

  527. 1:03:34

    So let's go back here and do that.

  528. 1:03:36

    And this is GitHub Actions, right? But it could be any kind of, you know, orchestration, CI orchestration. Could be Jenkins, could be GitLab CI. It could be anything. Azure DevOps, you know, whatever.

  529. 1:03:46

    Whatever you got. Yeah, question.

  530. 1:03:48

    Um, how much, if any, like, prompts modification do you guys do? It literally just puts in that one markdown file? Or do you add... Like, is it aware that it's in Dagger or anything?

  531. 1:03:59

    It is, yeah. So we have... The question is, like, how much prompt modification does the agent have? Uh, Dagger has its own system prompt that adds-

  532. 1:04:06

    Right

  533. 1:04:07

    ... that kind of guides it towards, like, how you use, uh, tools within Dagger, so it knows, like, call the s- the select methods and s- list functions and those, those things we saw it doing.

  534. 1:04:17

    You can add more to the system prompts. You can get rid of that system prompt if you want to. But yeah, there is a default one. Yeah.

  535. 1:04:24

    If, uh, we had to make further edits because the agent is not able to develop the right code or logic-

  536. 1:04:31

    Yeah

  537. 1:04:31

    ... how, how do we correct after the development before the rest of the system comes up?

  538. 1:04:35

    Yeah, so if, if the agent does some... I- if it, it calls develop and it runs, and it produces something that we say, "Okay, that's not right," how do we go back and say, "Make these changes"?

  539. 1:04:45

    Um-

  540. 1:04:45

    Can we just edit the completed source?

  541. 1:04:50

    Oh, yeah. So yeah. So you, 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."

  542. 1:04:57

    Or I can show you another function where we say, uh, we have a, an ability to give it more feedback to say, "Okay, you've done this so far. Here's some more changes to make 'cause you didn't get it quite right."

  543. 1:05:08

    Um, and so we'll see that happening.

  544. 1:05:12

    More questions.

  545. 1:05:12

    Uh, yeah, go ahead.

  546. 1:05:13

    Also the possibility you didn't give Dagger, the Dagger agent access to the test directory. So is that on purpose so it doesn't write, or it doesn't write, like, junk tests just so that the tests pass?

  547. 1:05:23

    Uh, the test directory.

  548. 1:05:25

    Or does it have access to it?

  549. 1:05:26

    It's... I think it should. Um, yeah, so I... The question was giving, uh, 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-

  550. 1:05:40

    We give it, like, the whole-

  551. 1:05:41

    Full source

  552. 1:05:42

    ... full source of the repo.

  553. 1:05:43

    And then-

  554. 1:05:43

    So it could get down in there if it wanted to.

  555. 1:05:45

    Yeah, I think it, it's kind of a, 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.

  556. 1:05:56

    Yeah.

  557. 1:05:56

    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 tests," or, or how, uh...

  558. 1:06:10

    It, it's kind of tough to decide, like, whether that's correct or not. Yeah.

  559. 1:06:14

    I noticed that there wasn't a Dagger install step, but done behind the scenes by the action.

  560. 1:06:19

    Hmm. So in-

  561. 1:06:21

    Just a one-liner. It's-

  562. 1:06:22

    Yeah, yeah. So in, uh, our workflow we installed Dagger, but it's, it's really just... There's a, a Dagger for GitHub Action, and so we just said-

  563. 1:06:33

    Oh, a three-liner in this case.

  564. 1:06:34

    Three-liner, yeah.

  565. 1:06:34

    Wow.

  566. 1:06:34

    So we said this version of Dagger, but this installs Dagger in your, in your, um, GitHub Actions runtime basically. Uh, so we used checkout to check out a repo and then this to ru- to install Dagger.

  567. 1:06:46

    The dependencies. Like, do you install the dependencies? Like, external dependencies? W- wasn't there, like, a GitHub issue one that you-

  568. 1:06:54

    Oh, yeah.

  569. 1:06:55

    Does that happen automatically?

  570. 1:06:57

    Yeah, exactly. So this is, um... I- in our Dagger JSON we have all, all of our dependencies listed. And so you don't have to say, like, Dagger install or anything.

  571. 1:07:08

    When we say Dagger install it adds it to this, and then we just run it.

  572. 1:07:12

    Got it. Yeah.

  573. 1:07:12

    Um, we don't have to do anything like NPM install like that. It just... It, it knows to make sure your client's generated.

  574. 1:07:19

    But that's a... That is the nice thing about having those dependencies m- m- you know, uh, in the a- in a, in a file saved in Git, you know, alongside the project.

  575. 1:07:29

    So 'cause like what we've done, e- essentially like if when we first got this project, this Vue app project, it didn't have any Dagger.

  576. 1:07:37

    Yeah.

  577. 1:07:37

    Didn't have anything, right? It was just like a- an app that you could run. And then we said, "Oh, well let's Dagger init in this thing." And then we got that little .dagger where we started developing our build and test functions, right?

  578. 1:07:49

    Kinda like our tools for development or for CI just alongside. And then in there is where we've been installing more modules like the, the workspace, the GiH- the GitHub issues module, like anything else you would need.

  579. 1:08:03

    So now... And that's all in Git. So the thing's now like this fully loaded, like Daggerized project. So it's kinda 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.

  580. 1:08:20

    Yeah. We're just like waiting for things to load here. Um, yeah, go ahead.

  581. 1:08:24

    Have you gotten anything, uh, like Dagger in Dagger where you have it spinning up like agent fleets and like different roles or-

  582. 1:08:31

    Yeah. Yeah. Yeah, so that's, um, I- I mean, myself as someone that builds a lot of Dagger code, I have agents that need to write Dagger code. And so to, um, reliably, uh, validate those things, they need basically Dagger inside of Dagger.

  583. 1:08:46

    So that's exactly like a thing that you can do, and I can even, uh, pull up if we go to... I know we're a bit short on time, but we're basically done with that guide-

  584. 1:08:56

    Yeah, 11 minutes

  585. 1:08:56

    ... and just waiting for it to run, yeah. Um, but we have,

  586. 1:09:00

    uh, 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-

  587. 1:09:09

    Oh

  588. 1:09:10

    ... is-

  589. 1:09:11

    I thought you were gonna show mine, but that's fine.

  590. 1:09:12

    Let's see.

  591. 1:09:12

    No, it's fine.

  592. 1:09:12

    Uh, the-

  593. 1:09:16

    It's fine.

  594. 1:09:17

    Oh, it's not... Okay.

  595. 1:09:18

    Oh.

  596. 1:09:19

    We're gonna add to the list of examples.

  597. 1:09:20

    We're gonna add to the list. It'll be re-

  598. 1:09:21

    Uh-

  599. 1:09:21

    ... even cooler list soon.

  600. 1:09:22

    So we have, um-

  601. 1:09:23

    We'll get to your question next

  602. 1:09:24

    ... yeah, there, there's this repo under my GitHub, [REDACTED:username]/[REDACTED:username], and this thing is something I use to, uh, like in the docs we saw those tabs on, of all the different languages.

  603. 1:09:35

    And so every, whenever I write a new guide, I have to have it in five languages. And so this agent can take it w- in one language and produce all the languages.

  604. 1:09:44

    Uh, 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, in addition to be able to like run Dagger in Dagger.

  605. 1:09:52

    So if we look at the, the code for that, it's just like-

  606. 1:09:57

    This one's in TypeScript.

  607. 1:09:58

    Yeah, this is a TypeScript one. Um, and when it runs tests, it runs the Dagger thing, and there's this flag privileged nesting so that the inner container can talk to the engine.

  608. 1:10:10

    Um, and this, this is writing Dagger code basically.

  609. 1:10:14

    Yeah. Question here.

  610. 1:10:15

    I'm curious, how does this relate to, um, 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 ma- multiple MCPs, um, in, as a different mechanism?

  611. 1:10:29

    Yeah, absolutely. So one way to think about it is, um, we were, we were kinda 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."

  612. 1:10:45

    Um, and so you can today even take a Dagger module and you can say dagger -m, the name of the module, mcp. And so you can expose a Dagger module as an MP- MCP server, for example.

  613. 1:10:58

    And yeah, and we've got some more things that we'll be probably sharing soon about that kind of stuff. But yes, uh, we think it's, uh, the vision is compatible in that way, and uh, yeah, you can use, you can use the MCP ecosystem as well.

  614. 1:11:12

    Yeah. So there's a few different layers here, right?

  615. 1:11:14

    Yeah.

  616. 1:11:14

    There's, there's, um, within our agent that we just built, we installed modules, and that uses, uh, 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, um, in, I don't know, the near future, next week or something you can-

  617. 1:11:34

    Yeah

  618. 1:11:34

    ... connect to external MCP servers to bring them into Dagger as well.

  619. 1:11:38

    Yeah. I mean, it's, I wanted to be, speak clearly, like the internal, the internal implementation, it's, it's pr- before MCP, so it's not MCP per se. But it, it very much logically you can think of it in a similar way.

  620. 1:11:50

    Yeah. And because you can expose everything as MCP servers, it ends up being practically, you know, very, very much the same for users.

  621. 1:11:59

    Check it out. We got our PR.

  622. 1:12:01

    What?

  623. 1:12:01

    Finally.

  624. 1:12:02

    Oh, we got a PR?

  625. 1:12:03

    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-

  626. 1:12:14

    What's the recommendation?

  627. 1:12:15

    ... the welcome.vue a change from documentation to... So maybe that's right. Oh, it deleted this other thing too 'cause it-

  628. 1:12:23

    Who needed it?

  629. 1:12:23

    ... decided that's not needed.

  630. 1:12:24

    Yeah.

  631. 1:12:24

    Um, cool. [laughs] So we have a really cool agent. [laughs] Yeah, it needs lots of-

  632. 1:12:28

    It's just vibing back there

  633. 1:12:29

    ... lots of prompting. Yeah.

  634. 1:12:29

    You know? The agent's just like-

  635. 1:12:31

    Um-

  636. 1:12:31

    Yeah

  637. 1:12:31

    ... but yeah, so 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.

  638. 1:12:38

    And now-

  639. 1:12:39

    Can it give feedback to things if it doesn't need it or-

  640. 1:12:41

    Yeah, exactly. So right now we, we only built in the one thing where it says we create an issue. That's a feature request. Um, but if we look at, I think on this examples list, um, we have, uh, this one, this greetings API, which is my main like demo project, and it has a ton of stuff in...

  641. 1:12:59

    There's like five different agents in here, and one of them is, I wanna give feedback on a PR. And so we can probably open one of these, uh, and I say, I give it, I give it some feedback.

  642. 1:13:12

    I say /agent. Uh, a- add this other fee- 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.

  643. 1:13:23

    The endpoint should be authenticated." And then it picks up again, pushes some new changes. And then I have another agent where I say /review, and that will create a, a review for my PR with any other changes that I need.

  644. 1:13:35

    And then I can say, "Okay, make those changes," and then also, "Please don't delete all the tests." [laughing]

  645. 1:13:40

    Very important to add. Um- [laughs] And that could be, like, you don't have to be inserting yourself at every one of those points, right?

  646. 1:13:46

    Yeah.

  647. 1:13:46

    But in this case, it, it's great for when we're-

  648. 1:13:48

    But yeah

  649. 1:13:49

    ... showing people-

  650. 1:13:49

    If you want an example of how you could 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, 'cause it has all of these different agents doing tons of things.

  651. 1:14:02

    It even has one where if we look at, uh, if I as a human push up a broken thing, 'cause we still have humans developing stuff sometimes, right? Uh, so I pushed a broken thing, and the test failed, which is super annoying 'cause I, you know, I skipped running tests 'cause I didn't have a good prompt that

  652. 1:14:20

    told me to run tests three times. [laughs] Uh, this agent can actually look at the test failure automatically and propose a, a s- a fix for that, that I can just click on it and fix that, uh, test change, right?

  653. 1:14:32

    So this is all stuff in this demo repo, uh, where you can see, like, how to build all these things yourself.

  654. 1:14:38

    So question over here.

  655. 1:14:40

    There's a lot I really love here. Um, I just had a question almost getting at the motivation for some of this stuff.

  656. 1:14:45

    Yes.

  657. 1:14:45

    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?

  658. 1:14:56

    I think there, there's a lot of levels to it, right? Like, if you're already really baked into, like, Pydantic or OpenAI Agent SDK, you can still use those container workflows in that, and I'll show it.

  659. 1:15:06

    Maybe I shouldn't, but-

  660. 1:15:07

    Yeah

  661. 1:15:07

    ... um, but I have-

  662. 1:15:09

    Go crazy.

  663. 1:15:10

    Uh, if y- if you've done the OpenAI Agents quick start, um, if it loads here.

  664. 1:15:17

    Uh, or sorry, this is the, the agent quick start we have, but with the agent SDK, where I've used the OpenAI Agent SDK that says, like, um, "Here's my completions model.

  665. 1:15:26

    This is actually using Ollama." Uh, this is what their SDK looks like. Uh, but in that SDK, I'm actually still using Dagger. So I actually recreated that same workspace where we have read file, write file, and build.

  666. 1:15:40

    Um, but I've created that with Dagger inside of the OpenAI Agents SDK. So I'm, I'm using their agents, but using Dagger code for the containers.

  667. 1:15:50

    But it's great you came to, like, what... Like, why use Dagger I guess is the like-

  668. 1:15:54

    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 verse of modules.

  669. 1:16:03

    I can just plug one in.

  670. 1:16:04

    Yeah.

  671. 1:16:04

    And that's just given to the agent, right?

  672. 1:16:06

    Yeah, your, your whole, your whole method signature is instantly translated into the right 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.

  673. 1:16:19

    They're, like, with Pydantic and other things where they're just like, they want the sandbox capability 'cause they're like, "Oh, I don't wanna, you know, maybe I don't wanna use another, you know, cloud sandbox vendor or whatever.

  674. 1:16:30

    I wanna 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 they're... So yeah. But I think, yeah, the sweet spot is kind of doing it all because it just harmonizes really well.

  675. 1:16:42

    Yeah.

  676. 1:16:42

    Question there.

  677. 1:16:43

    Hi. Thanks for the great demo. Uh, so I had a question. Let's say if I want to build a, a agent for programming HTML games-

  678. 1:16:51

    Yes

  679. 1:16:51

    ... which run in browser. So for that game building agent, I would need the testing envi- so the running and testing environment to be browser.

  680. 1:16:59

    Yes.

  681. 1:16:59

    So does Dagger has tho- 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.

  682. 1:17:10

    Yeah, I mean, you certainly can.

  683. 1:17:11

    Yeah.

  684. 1:17:11

    I mean, I've done, I've done some headless browser stuff. I've also done some browser stuff in a connect over VNC and if it... or different... Yeah, you can do a lot of, you know, you can do, uh, you can do a lot of stuff, uh, with, with Linux containers.

  685. 1:17:26

    Um, so yeah, I-- We should talk about it. You should come, come in the community. Let's, like, do it.

  686. 1:17:32

    Yeah.

  687. 1:17:32

    Yeah.

  688. 1:17:33

    Thank you.

  689. 1:17:34

    First of all, great demo, and, uh, thanks for compressing a lot of information. Uh, so is my understanding that you build CI/CD infra and all these things once and then let Dagger do the asynchronous job, uh, with guardrails and, you know, uh, all the things in place?

  690. 1:17:49

    Like, i- is, is my understanding that Dagger is sort of this asynchronous AI agent that does things on its own but with guardrails, not just leaving, uh, Claude code or something, uh, in a trust all mode and then let it do its thing?

  691. 1:18:03

    Is, is that right?

  692. 1:18:05

    I think, uh, yeah.

  693. 1:18:05

    Yeah.

  694. 1:18:05

    So the question was like, yeah, is, is what is Dagger in a certain sense too?

  695. 1:18:09

    Yeah.

  696. 1:18:09

    But Dagger gives you this platform to create the 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.

  697. 1:18:19

    And then you can use them, uh, 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-

  698. 1:18:31

    Yeah

  699. 1:18:31

    ... and to create those guardrails like you say. Um, you can. The one thing I wanted you to show, and you got one minute.

  700. 1:18:37

    Oh, yeah.

  701. 1:18:37

    Can you just show your terminal, and just let's, let's get vibey for just one second. So you're connected to an LLM right now, right? So, um, go ahead. Just, like, let's talk to this LLM.

  702. 1:18:48

    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.

  703. 1:19:00

    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, "All right.

  704. 1:19:14

    I'm just gonna create this container," and I'm gonna say, "Hey, LLM, you see that container? Why don't you write some software in it?" So you can get that kind of, that kind of workflow going too.

  705. 1:19:24

    So he's... There he goes. 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.

  706. 1:19:35

    And it's, "Oh, there's this container method in the API," which we were using earlier. And then it's gonna like, you know, decide, "Oh, I'm gonna use container, maybe from container, from container with exec to execute."

  707. 1:19:46

    So these are just-- It's exploring the Dagger API right now.

  708. 1:19:49

    Got it.

  709. 1:19:50

    And now it's gonna like, it's actually pulling a Python 3.11 container. Then it can d- do things with that. So y- you know, it's actually using containers, like, kinda like computer use or something like that.

  710. 1:20:01

    But, um, so yeah. So you can get-- You can go... We didn't even show that side of it-

  711. 1:20:06

    Mm-hmm

  712. 1:20:06

    ... 'cause, you know, we're trying to show the ver- show the guardrails, but you can also use it in this kind of a style too.

  713. 1:20:12

    Got it. Uh, and one, one follow-up question. Uh, typically LLMs are good at small to medium tasks, and that's what we have seen, like a small to medium task here.

  714. 1:20:21

    How, uh, good is Dagger at orchest- orchestrating, uh, like a large task which ne- wh- which needs design or some user input or, you know, multi-turn prompt? Uh, like, you know, not a small, medium task, but a large task.

  715. 1:20:34

    How good is-

  716. 1:20:34

    Oh, yeah

  717. 1:20:34

    ... Dagger with that?

  718. 1:20:35

    Yeah. The question is like, uh, size of tasks that Dagger is good for. I think if you make it d- if you com- decompose things down and you can architect things right, it can handle a lot of different sizes.

  719. 1:20:45

    Mm-hmm.

  720. 1:20:45

    And we should... I know we're at time now, so we're gonna like, we're gonna end here.

  721. 1:20:48

    We'll, we'll take some more questions outside the room.

  722. 1:20:50

    But in the hall for sure.

  723. 1:20:51

    Yeah.

  724. 1:20:51

    And thank you so much for everybody that attended.

  725. 1:20:52

    Yeah. Thank you, guys. [audience applauding] [upbeat music]