Build a Coding AI Agent
Estimated time: 5 minutes
In this guide you will create your first coding agent!
The agent will use an LLM of your choosing to solve a coding prompt. The agent will have access to tools to write code and validate it.
Installation and configuration
Follow the LLM endpoint configuration instructions to configure an LLM for use with Dagger.
Create a Dagger module
In an empty directory, create a new Dagger module
First, you will create a Dagger module. This module will be the place where you write your agent functions.
You can write your module in Go, Python, Typescript, PHP, or Java. Choose the SDK you are most comfortable with.
- Go
- Python
- Typescript
- PHP
- Java
dagger init --sdk go --name coding-agent
dagger init --sdk python --name coding-agent
dagger init --sdk typescript --name coding-agent
dagger init --sdk php --name coding-agent
dagger init --sdk java --name coding-agent
This will generate a bunch of files that make up the Dagger module, including some boilerplate functions as examples.
To see the generated functions, run:
dagger functions
You should see information about the generated container-echo
and grep-dir
functions.
Install a module dependency
Before you write the agent's function, this agent has a dependency that needs to be installed. This dependency provides the environment the LLM you use to solve the coding prompt.
Learn more about agent environments.
dagger install github.com/shykes/toy-programmer/toy-workspace
Toy-workspace is a Dagger module that provides a simple environment for the agent. It has a Container
as its state and functions to read, write, and build the code.
Write your agent fuction
Edit the agent file
- Go
- Python
- Typescript
- PHP
- Java
Edit the agent (main.go
) and replace the generated code with this code:
package main
import (
"dagger/coding-agent/internal/dagger"
)
type CodingAgent struct{}
// Write a Go program
func (m *CodingAgent) GoProgram(
// The programming assignment, e.g. "write me a curl clone"
assignment string,
) *dagger.Container {
result := dag.LLM().
WithToyWorkspace(dag.ToyWorkspace()).
WithPromptVar("assignment", assignment).
WithPrompt(`
You are an expert go programmer. You have access to a workspace.
Use the default directory in the workspace.
Do not stop until the code builds.
Do not use the container.
Complete the assignment: $assignment
`).
ToyWorkspace().
Container()
return result
}
Edit the agent (src/coding_agent/main.py
) and replace the generated code with this code:
import dagger
from dagger import dag, function, object_type
@object_type
class CodingAgent:
@function
def go_program(self, assignment: str) -> dagger.Container:
"""Write a Go program"""
result = (
dag.llm()
.with_toy_workspace(dag.toy_workspace())
.with_prompt_var("assignment", assignment)
.with_prompt("""
You are an expert go programmer. You have access to a workspace.
Use the default directory in the workspace.
Do not stop until the code builds.
Do not use the container.
Complete the assignment: $assignment
""")
.toy_workspace()
.container()
)
return result
Edit the agent (src/index.ts
) and replace the generated code with this code:
import { dag, Container, object, func } from "@dagger.io/dagger"
@object()
export class CodingAgent {
/**
* Write a Go program
*/
@func()
goProgram(
/**
* The programming assignment, e.g. "write me a curl clone"
*/
assignment: string,
): Container {
const result = dag
.llm()
.withToyWorkspace(dag.toyWorkspace())
.withPromptVar("assignment", assignment)
.withPrompt(
`
You are an expert go programmer. You have access to a workspace.
Use the default directory in the workspace.
Do not stop until the code builds.
Do not use the container.
Complete the assignment: $assignment
`,
)
.toyWorkspace()
.container()
return result
}
}
Edit the agent (src/CodingAgent.php
) and replace the generated code with this code:
<?php
declare(strict_types=1);
namespace DaggerModule;
use Dagger\Attribute\DaggerFunction;
use Dagger\Attribute\DaggerObject;
use Dagger\Attribute\Doc;
use Dagger\Container;
use function Dagger\dag;
#[DaggerObject]
#[Doc('A generated module for CodingAgent functions')]
class CodingAgent
{
#[DaggerFunction]
#[Doc('Write a Go program')]
public function goProgram(string $assignment): Container
{
return dag()
->llm()
->withToyWorkspace(dag()->toyWorkspace())
->withPromptVar("assignment", $assignment)
->withPrompt("
You are an expert go programmer. You have access to a workspace.
Use the default directory in the workspace.
Do not stop until the code builds.
Do not use the container.
Complete the assignment: $assignment")
->toyWorkspace()
->container();
}
}
Edit the agent (src/main/java/io/dagger/modules/codingagent/CodingAgent.java
) and replace the generated code with this code:
package io.dagger.modules.codingagent;
import static io.dagger.client.Dagger.dag;
import io.dagger.client.Container;
import io.dagger.client.DaggerQueryException;
import io.dagger.module.annotation.Function;
import io.dagger.module.annotation.Object;
import java.util.concurrent.ExecutionException;
/** CodingAgent main object */
@Object
public class CodingAgent {
/** Write a Go program */
@Function
public Container goProgram(String assignment) {
return dag()
.llm()
.withToyWorkspace(dag.toyWorkspace())
.withPromptVar("assignment", assignment)
.withPrompt("""
You are an expert go programmer. You have access to a workspace.
Use the default directory in the workspace.
Do not stop until the code builds.
Do not use the container.
Complete the assignment: $assignment
""")
.toyWorkspace()
.container();
}
}
In this code you created a function called go-program
that takes in an assignment and returns a Container.
- The instance of
ToyWorkspace
is given to the LLM to provide it tools to write and validate code. - The prompt is passed to the LLM to solve.
- The LLM will use the tools in the environment to write code, validate it, and loop until the code passes validation.
- You return a container by chaining
llm -> toy-workspace -> container
. This works because you gave the LLM theToyWorkspace
earlier in the chain.
Now run your new function in the Dagger shell
Run dagger
to enter the shell.
Check out the help text for your new function:
.help
.help go-program
This should show how to use the go-program
function.
Make sure your LLM provider has been properly configured:
llm | model
This should show the model you've configured to use with your provider.
Now run the function:
go-program "write a curl clone"
You'll see the agent receive the prompt, write code, validate it, and return the container. If the LLM fails to write code that passes validation, try adding more helpful guidance to the prompt in your function.
Once it has successfully written code, you can get a terminal in the container:
go-program "write a curl clone" | terminal
Run the program. This will look slightly different depending on how the LLM wrote the code:
> ls
# should see a main.go and a go.mod, maybe other files
> go run main.go https://dagger.io
Next steps
Congratulations! You've created your first coding agent. You can now use this agent to solve coding prompts using an LLM.
Now that you've grasped the basics of building an agent, look at the Dagger AI Agent examples for more examples and ideas for your next agent.