Tuesday

A Simple Agentic Coding Workflow for Java

AI coding agents can already write classes, add tests, refactor code, and fix bugs. But using an AI agent for coding is not the same as having an agentic development workflow.

If one agent receives a large task and does everything inside the same context, it is still mostly:

prompt → generate code → hope it is correct

A more structured approach is to separate planning, implementation, review, and verification.

This is the approach I tried in ModelMatrix4J , a Java project used to experiment with agent-first development.

The basic workflow looks like this:

Architect + Test Planner
        ↓
    Orchestrator
        ↓
    Implementer
        ↓
Reviewer + Adversarial Reviewer
        ↓
    mvnw verify

The important point is that these are not just role names written inside one prompt. They are separate Codex agents with different responsibilities and permissions.


What Does Agent-First Mean?

Agent-first means the repository is prepared for agents to work inside it safely.

A fresh coding agent should be able to answer a few basic questions:

What am I allowed to change?

What should I not change?

What must happen before my task starts?

Who reviews my work?

How is completion verified?

If these answers only exist inside a developer's head, every new agent session needs another large prompt.

A better approach is to keep the important boundaries inside the repository.


Separate Agents for Separate Jobs

ModelMatrix4J defines project-level Codex agents under:

.codex/agents/

The current setup contains:

architect
test-planner
implementer
reviewer
adversarial-reviewer

Each agent has one clear responsibility.

Architect

The architect looks at design, module boundaries, dependency direction, and public API pressure.

It is read-only. It can recommend a design, but it cannot start changing production code.

Test Planner

The test planner looks at acceptance criteria, deterministic tests, failure cases, and isolation.

It is also read-only.

Implementer

The implementer receives a specific writable scope and makes the actual changes.

Reviewer

The reviewer checks correctness, architecture, scope, and test coverage after implementation.

Adversarial Reviewer

The adversarial reviewer looks for things that are easier to miss:

edge cases
failure paths
bad assumptions
scope leaks
missing negative tests
false completion claims

Review agents stay read-only and independent from the implementer.


Permissions Are Part of the Design

Different responsibilities should also have different permissions.

A simplified architect configuration looks like this:

name = "architect"
sandbox_mode = "read-only"
approval_policy = "never"

The implementer is different:

name = "implementer"
sandbox_mode = "workspace-write"

This is useful because planning and reviewing do not automatically come with permission to edit the repository.

The agent role is not only a prompt. It also defines what kind of work the agent is allowed to perform.


Keep AGENTS.md Small

Repository instructions can easily become another large documentation system. That should be avoided.

The root AGENTS.md should mainly contain the rules every agent needs.

For example:

Work only inside the approved milestone.

Change only the assigned files or paths.

Do not silently change public/shared APIs.

Do not implement future functionality early.

Read the nearest module-level AGENTS.md before editing a module.

Run the canonical verification command before completion.

More specific rules can live closer to the module.

For example:

modelmatrix-core/AGENTS.md
modelmatrix-junit/AGENTS.md

The core module can say:

Keep production code JDK-only.

Do not introduce Spring, Spring AI, or JUnit into production core code.

Keep default tests deterministic and offline.

The JUnit module can define its own dependency and isolation rules.

This keeps instructions local instead of turning the root file into a large manual.


Use Skills for Repeated Workflows

Agent roles answer:

Who should do this?

Skills answer:

How should this type of work be done?

The project keeps a small set of repository skills:

.agents/skills/
  modelmatrix-milestone/
  modelmatrix-review/
  modelmatrix-verify/

The milestone skill defines the normal development flow.

  1. Architect and test planner inspect the task.
  2. The orchestrator reconciles their recommendations.
  3. An implementer receives a bounded writable task.
  4. Independent reviewers inspect the integrated changes.
  5. The repository is verified.

The important point is not the exact skill names.

The useful part is making repeated engineering workflows reusable instead of explaining them again in every large prompt.


Give Implementers a Bounded Task

A coding agent should not receive an instruction like:

Implement the next milestone.

That leaves too much room for interpretation.

A better delegation is closer to this:

Objective:
Implement the minimal scenario contract.

Allowed files:
modelmatrix-core/src/main/java/.../Scenario.java
modelmatrix-core/src/test/java/.../ScenarioTest.java

Forbidden:
pom.xml
modelmatrix-junit/**
unrelated public contracts

Prerequisites:
architecture review completed

Acceptance:
focused tests pass
full Maven verification passes

Now the agent knows both sides of the task:

what to do
and
where to stop

This is one of the most useful ideas in agentic coding.

Good delegation is not only about giving agents enough context. It is also about giving them a clear boundary.


Parallel Agents Without Conflicts

Multiple agents can work in parallel, but parallel writing needs more control than parallel reading.

The rule is:

Parallel writable tasks
    → separate Git worktrees
    → non-overlapping writable scopes

Overlapping writable tasks
    → run sequentially

Separate worktrees give filesystem isolation.

But filesystem isolation is not architectural permission.

An agent working in another worktree still cannot decide to change a shared API, another module, or a common contract unless that change is part of its delegated scope.

Shared contract changes go back through the orchestrator.

This keeps parallelism useful without allowing several agents to independently redesign the same part of the system.


Independent Review Comes Before Done

The implementer does not decide alone that the work is complete.

After implementation, separate read-only reviewers inspect the integrated diff.

The normal reviewer checks things like:

correctness
architecture boundaries
scope
public API changes
test coverage
dependency direction

The adversarial reviewer asks different questions:

What happens on failure?

What assumption is not tested?

Can this bypass a repository rule?

Is the result deterministic?

Could this accidentally affect another module?

Are we calling something complete only because the happy path passes?

Using two different review perspectives gives better feedback than asking the implementation agent to review its own work.


Keep Different Sources of Truth Separate

One common problem in AI-assisted projects is duplicated documentation. The same rule appears in several files, and eventually they disagree.

A simpler structure is:

.codex/agents/
    → who does the work

.agents/skills/
    → how repeated workflows run

AGENTS.md
    → repository rules

docs/PRODUCT_SPEC.md
    → what the product should do

docs/ARCHITECTURE.md
    → architecture and dependency boundaries

docs/ROADMAP.md
    → what is allowed to be implemented now

Each file has a different job.

This also makes it easier for an agent to find the correct information without loading every document in the repository.


Use One Clear Verification Command

An agentic workflow needs an executable definition of done.

For this project, the canonical command is:

./mvnw -B verify

The same command is used as the main local and CI verification path.

Important architecture rules can also become build rules when they can be checked mechanically.

For example, the core module prevents dependencies such as Spring, Spring AI, and provider SDKs from entering the core dependency graph.

This creates an important distinction:

Documentation:
"This dependency should not be here."

Build rule:
"This dependency cannot be here without failing verification."

For agentic coding, executable boundaries become more valuable as the codebase grows.


A Small Setup Is Enough

Agentic coding does not require ten agents, a workflow engine, or a large amount of AI-specific infrastructure.

A useful starting point can be:

Architect
    ↓
Implementer
    ↓
Reviewer
    ↓
Build + Tests

More specialization can be added when there is a real reason for it.

The important parts are:

  • clear agent responsibilities
  • read-only planning and review where possible
  • bounded writable scopes
  • small repository instructions
  • safe parallel work
  • independent review
  • executable verification

The Main Idea

The goal of agentic coding is not to run as many agents as possible.

The goal is controlled delegation.

A good agent should be able to enter the repository, understand its task, respect the boundaries, make a focused change, hand the result to another agent for review, and finish with real verification.

In simple form:

plan
  ↓
delegate
  ↓
implement
  ↓
review
  ↓
verify

That is the agent-first development approach used in ModelMatrix4J .

No comments:

Post a Comment