Skip to content
AgentEnsemble AgentEnsemble
Get Started

Coding Agents

AgentEnsemble can orchestrate agents that write, debug, and refactor code. The agentensemble-coding module provides a high-level factory that auto-detects project type, assembles the right tools, and generates coding-specific agent instructions.


EnsembleOutput result = CodingEnsemble.run(model, Path.of("/my/project"),
CodingTask.fix("NullPointerException in UserService.getById()"));

That single call:

  1. Detects the project type (Java/Gradle, npm, Python, etc.)
  2. Assembles coding tools (file read, plus optional search/edit/git/test tools)
  3. Generates a system prompt with build/test commands and source roots
  4. Runs the agent with a higher iteration limit (75 vs the default 25)

ProjectDetector.analyze(Path) scans the project root for build-file markers:

Marker fileLanguageBuild systemBuild commandTest command
build.gradle.kts / build.gradleJavaGradle./gradlew build./gradlew test
pom.xmlJavaMavenmvn compilemvn test
package.json + tsconfig.jsonTypeScriptnpmnpm run buildnpm test
package.jsonJavaScriptnpmnpm run buildnpm test
pyproject.toml / requirements.txtPythonpippython -m buildpython -m pytest
go.modGogogo build ./...go test ./...
Cargo.tomlRustCargocargo buildcargo test

Source roots are detected automatically (e.g., src/main/java, src/test/java for Java/Gradle projects).


For full control over agent construction:

Agent agent = CodingAgent.builder()
.llm(model)
.workingDirectory(Path.of("/my/project"))
.toolBackend(ToolBackend.AUTO) // or JAVA, MCP, MINIMAL
.requireApproval(true) // for destructive operations
.maxIterations(75) // higher default for coding
.additionalTools(myCustomTool) // extra tools
.build();

The builder returns a standard Agent — no subclassing. You can use it with Task, Ensemble, or any other framework feature.

Either workingDirectory(Path) or workspace(Workspace) is required (not both):

  • workingDirectory: Tools operate directly in this directory. Changes are in-place.
  • workspace: Tools operate in the workspace path (typically a git worktree). Use CodingEnsemble.runIsolated() to create the workspace automatically.

BackendDescriptionRequirements
AUTO (default)Detect best available backendNone
JAVAJava coding tools (glob, search, edit, shell, git, build, test)agentensemble-tools-coding on classpath
MCPMCP reference servers for filesystem + gitagentensemble-mcp on classpath + Node.js
MINIMALFileReadTool onlyAlways available

AUTO resolves in order: MCP > JAVA > MINIMAL. If neither optional module is on the classpath, the agent works with file-read only.

You can also start MCP servers manually and pass their tools to any agent via Agent.builder().tools(...). This gives you full control over server lifecycle:

try (McpServerLifecycle fs = McpToolFactory.filesystem(projectDir);
McpServerLifecycle git = McpToolFactory.git(projectDir)) {
fs.start();
git.start();
List<Object> mcpTools = new ArrayList<>();
mcpTools.addAll(fs.tools());
mcpTools.addAll(git.tools());
Agent agent = Agent.builder()
.role("Senior Software Engineer")
.goal("Implement, debug, and refactor code with precision")
.tools(mcpTools)
.llm(model)
.maxIterations(75)
.build();
Task task = CodingTask.fix("Fix the login timeout bug")
.toBuilder().agent(agent).build();
EnsembleOutput output = Ensemble.run(model, task);
}

See the MCP Coding Example for a complete walkthrough.


Pre-configured tasks for common coding workflows:

// Bug fix
Task task = CodingTask.fix("NullPointerException in handler");
// Feature implementation
Task task = CodingTask.implement("Add pagination to /api/users");
// Refactoring
Task task = CodingTask.refactor("Extract UserRepository interface");

Each returns a standard Task that can be further customized:

Task task = CodingTask.fix("Some bug")
.toBuilder()
.expectedOutput("Custom expected output")
.build();

Changes are made directly in the working directory:

EnsembleOutput result = CodingEnsemble.run(model, workingDir,
CodingTask.fix("Fix the login timeout bug"));

Changes are made in a git worktree. The worktree is preserved on success (for review) and cleaned up on failure:

EnsembleOutput result = CodingEnsemble.runIsolated(model, repoRoot,
CodingTask.implement("Add user profile endpoint"));

After a successful isolated run, you can review changes in the worktree directory and merge them manually (e.g., git merge from the worktree branch).


// Full coding agent experience
implementation("net.agentensemble:agentensemble-coding:$version")
// Optional: Java coding tools (GlobTool, CodeEditTool, ShellTool, etc.)
// implementation("net.agentensemble:agentensemble-tools-coding:$version")
// Optional: MCP bridge (filesystem + git via MCP servers)
// implementation("net.agentensemble:agentensemble-mcp:$version")

The workspace module (agentensemble-workspace) is included transitively.