Skip to main content

Why Coding Agent

The Coding Agent page is the easiest one to write as an empty slogan:

"It is an Agent for code tasks."

That sentence is not wrong, but it carries almost no technical information. From the AI4J source, the reason Coding Agent deserves its own chapter is not that it changed a name, but that it stacks 5 additional layers of local-delivery semantics on top of a generic Agent:

  • workspace semantics
  • coding tools and process governance
  • multi-turn coding loop
  • session / compact / restore
  • CLI / TUI / ACP host integration

Stacked together, these layers form the real boundary between it and a plain Agent.

1. Start with the key wiring entry point

If you only want to find "where Coding Agent and a plain Agent actually diverge", the first thing to read is:

  • ai4j-coding/.../CodingAgentBuilder.java

This builder does not simply wrap AgentBuilder. During the build phase it additionally performs:

  • WorkspaceContext resolution
  • CodingSkillDiscovery.enrich(...)
  • built-in coding tool registry wiring
  • built-in tool executor routing
  • DefaultCodingRuntime wiring
  • sub-agent / handoff merging
  • workspace system prompt injection

Only then does it sink these results into:

new AgentBuilder().build()

In other words, Coding Agent is not "flip a few switches while calling AgentBuilder", but rather:

Wire up the local code repository runtime first, then embed the generic Agent into it.

2. It solves workspace semantics, not "one more shell tool"

A plain Agent typically only knows about:

  • model
  • memory
  • tools
  • runtime

Coding Agent, by contrast, first introduces:

  • WorkspaceContext

This object currently carries at least:

  • rootPath
  • excludedPaths
  • allowOutsideWorkspace
  • skillDirectories
  • allowedReadRoots
  • availableSkills

It is not just "giving the tools a cwd"; it defines:

  • which paths are treated as the workspace
  • which paths are out-of-bounds by default
  • which directories are read-only
  • how skill discovery results enter the prompt

This is why a coding scenario cannot be muddled through with generic tool calling alone. A repository task is, first and foremost, a workspace boundary problem.

3. The prompt is not the "just stuff a system prompt" style of a plain Agent

CodingContextPromptAssembler.mergeSystemPrompt(...) actually merges workspace information into the system prompt, including:

  • workspace root
  • workspace description
  • the built-in tools list
  • calling rules for bash/read_file/write_file/apply_patch/glob/grep/edit/update_agents_md
  • shell usage guidance
  • access restrictions outside the workspace
  • a summary of available skills

This shows that the Coding Agent prompt is not pure role setting, but a host environment declaration.

Precisely because of this injection layer, what the model sees in a coding scenario is not an abstract "tool capability", but:

  • which repository it is currently in
  • what the read/write rules are
  • how tool-call payloads should be constructed

This is clearly a different responsibility from the system prompt of a plain Agent.

4. Its built-in tools are not "just expose a few more functions" either

CodingToolRegistryFactory.createBuiltInRegistry() currently exposes directly:

  • bash
  • read_file
  • write_file
  • apply_patch
  • glob
  • grep
  • edit
  • update_agents_md

But what really matters is not the tool names, but the execution routing inside CodingAgentBuilder.createBuiltInToolExecutor(...).

It wires each of these tools to:

  • ReadFileToolExecutor
  • WriteFileToolExecutor
  • ApplyPatchToolExecutor
  • BashToolExecutor
  • GlobToolExecutor
  • GrepToolExecutor
  • EditToolExecutor
  • UpdateAgentsMdToolExecutor

and routes to the concrete implementations via RoutingToolExecutor.

In other words, the tool system inside Coding Agent is not as lightweight as "the model calls a function, Java runs it"; it already has:

  • a workspace-aware file executor
  • a patch-specific executor
  • a bash process-lifecycle executor
  • glob / grep content and filename search executors
  • a precise-string edit executor
  • an AGENTS.md project-memory executor

This is exactly the essential difference between local repository tasks and generic function calling.

5. Why bash here is a system capability, not an ordinary tool

BashToolExecutor is not a one-shot command toy. Behind it sit:

  • SessionProcessRegistry
  • CodingSession

And CodingSession itself supports:

  • listProcesses()
  • processStatus(...)
  • processLogs(...)
  • writeProcess(...)
  • stopProcess(...)

This shows that under Coding Agent semantics, a shell is not a "one exec and done" call, but a continuously manageable session process surface.

This matters enormously, because local development tasks frequently need to:

  • start a service
  • watch logs
  • continuously write to stdin
  • stop a background process

The tool-call model of a plain Agent usually does not elevate these to first-class concepts.

6. Why it needs a dedicated CodingSession

A single AgentSession is not enough to support a coding scenario.

CodingSession additionally provides:

  • snapshot()
  • exportState()
  • restore(...)
  • compact()
  • process snapshots
  • auto-compact state
  • checkpoint
  • loop decision records

This shows that a coding scenario cares not only about "what the model replied", but also about:

  • how the current work progress is saved
  • whether process state can be recovered
  • how to compact when the context grows too long
  • why the next turn continues or stops

So CodingSession is a recoverable work-session container, not an ordinary chat session.

7. Why it must have compaction, rather than just raising max tokens

CodingSession builds in directly:

  • CodingSessionCompactor
  • CodingToolResultMicroCompactor
  • an auto-compact circuit breaker

In implementation it supports:

  • manual compact
  • auto compact
  • tool-result micro-compact
  • automatic circuit-breaking after consecutive failures

This shows AI4J's judgment about coding scenarios is unambiguous:

Long tasks will always hit context bloat; you cannot brute-force it with the model window alone.

Plain Agents hit context problems too, but a coding scenario is worse because it accumulates:

  • command output
  • patch results
  • file diffs
  • intermediate summaries
  • process state

So compact here is not a nice-to-have, but a basic survival capability.

8. Why it needs a dedicated loop controller

CodingAgentLoopController is the other core divergence point.

It does not simply "call Agent.run() once"; it loops according to policy:

  • aggregating tool calls and tool results
  • deciding whether auto-continue is needed
  • recognizing approval rejection / tool error / explicit question
  • generating continuation prompts
  • counting total turns and auto-follow-ups

The stop reasons are also modeled explicitly:

  • COMPLETED
  • NEEDS_USER_INPUT
  • BLOCKED_BY_APPROVAL
  • BLOCKED_BY_TOOL_ERROR
  • MAX_AUTO_FOLLOWUPS_REACHED
  • MAX_TOTAL_TURNS_REACHED

This matters, because a coding task is rarely "one Q&A round and done"; it is:

  • do a step
  • look at the result
  • decide the next step

So the Coding Agent loop is not auxiliary logic for a chat UX, but a workflow controller.

9. Its delegation is not plain sub-agent shell wrapping either

What DefaultCodingRuntime.delegate(...) does is noticeably heavier than a plain handoff:

  • creating a CodingTask
  • persisting task progress
  • generating a parent/child CodingSessionLink
  • deciding seed state based on CodingSessionMode
  • creating a child coding session
  • resolving allowed tools by definition
  • supporting background tasks

The accompanying CodingToolPolicyResolver also, based on the agent definition:

  • filters the tool registry
  • wraps the executor with an allowlist check

This means the point of coding delegation is not "toss a sentence to another agent", but:

Spawning sub-work under a controllable tool surface, trackable task state, and optional session-inheritance mode.

This is closer to real engineering collaboration than a generic handoff.

10. Why approvals sit in the host layer, instead of being hardcoded into the runtime

This point is worth spelling out.

The CliToolApprovalDecorator in the CLI wraps the executor with an approval layer; the current default behavior includes:

  • apply_patch always requires approval (in non-auto mode)
  • bash actions such as exec/start/stop/write can require approval
  • a rejected approval returns an [approval-rejected] semantic

Then CodingAgentLoopController recognizes that result as:

  • BLOCKED_BY_APPROVAL

This layering is excellent, because it shows that:

  • "whether to approve" is a host-interaction strategy
  • "how the loop stops after an approval rejection" is a runtime strategy

In other words, AI4J does not hard-couple approval with tool execution; it splits it into:

  • a tool-executor decorator
  • a loop-level stop reason

This lets CLI, TUI, and ACP share the runtime while each implementing a different approval experience.

11. Why it also needs a CLI-side session event store

FileSessionEventStore currently writes session events as:

  • per-sessionId jsonl files

This shows that the CLI/TUI layer is not "just print to terminal and done"; it treats the coding session as a replayable, listable, recoverable event stream.

For repository tasks, this kind of event log is valuable, because you often need to:

  • review how a given turn was done
  • replay a key operation
  • trace the approval / tool call / output chain

A plain Agent that only does short-chat sessions usually does not need this layer built so heavily.

12. Why skill is also a first-class capability here

CodingSkillDiscovery.enrich(...) does two things during the build phase:

  • discovers default skills
  • writes allowedReadRoots and availableSkills back into WorkspaceContext

Then CodingContextPromptAssembler merges the skill summary into the system prompt.

This means Coding Agent's use of skills is not merely "an optional document attachment", but something that:

  • affects the readable root directories
  • affects the capability surface in the system prompt

This is more systematic than "temporarily stuff a paragraph of explanation" in a plain Agent.

13. So why it deserves to be called Coding Agent on its own

If you assemble all of the above, you find it is no longer "Agent + shell":

  • it has workspace boundaries
  • it has dedicated file / patch / bash executors
  • it has process registration and IO management
  • it has a multi-turn coding loop
  • it has session snapshot / restore / compact
  • it has delegation task/link/runtime
  • it has host approval and event storage
  • it has skill discovery and workspace prompt injection

This is in effect a local code-delivery runtime, not just a model-call wrapper layer.

14. When to use it, and when not to

Scenarios suited to Coding Agent:

  • local repository changes
  • review / debug / patch / refactor
  • interaction that needs shell, files, patch, and long-task sessions
  • needs approval, recovery, compaction, and spawning subtasks

Scenarios where you should not force Coding Agent:

  • single-turn Q&A
  • ordinary business Agent orchestration
  • tasks that do not touch a local workspace or code assets

This is not because Coding Agent is more "advanced", but because its runtime surface is clearly heavier.

15. The conclusion this page most wants you to remember

The reason AI4J's current Coding Agent is not an alias for a generic Agent is that it adds a whole layer of local code-delivery semantics on top of a generic Agent:

  • workspace constraints
  • dedicated coding tools
  • a continuous process surface
  • a multi-turn loop
  • session compaction / restore
  • task-based delegation
  • host approval and an event ledger

It is more accurate to understand it as "a runtime product layer for repository tasks" than as "an Agent that is better at writing code".

  1. Runtime Architecture
  2. Session Runtime
  3. Tools and Approvals
  4. Compact and Checkpoint
  5. CLI and TUI
  6. MCP and ACP

To keep following this main line on the next page, go straight to Runtime Architecture.