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:
WorkspaceContextresolutionCodingSkillDiscovery.enrich(...)- built-in coding tool registry wiring
- built-in tool executor routing
DefaultCodingRuntimewiring- 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:
rootPathexcludedPathsallowOutsideWorkspaceskillDirectoriesallowedReadRootsavailableSkills
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:
bashread_filewrite_fileapply_patchglobgrepeditupdate_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:
ReadFileToolExecutorWriteFileToolExecutorApplyPatchToolExecutorBashToolExecutorGlobToolExecutorGrepToolExecutorEditToolExecutorUpdateAgentsMdToolExecutor
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:
SessionProcessRegistryCodingSession
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:
CodingSessionCompactorCodingToolResultMicroCompactor- 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:
COMPLETEDNEEDS_USER_INPUTBLOCKED_BY_APPROVALBLOCKED_BY_TOOL_ERRORMAX_AUTO_FOLLOWUPS_REACHEDMAX_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_patchalways requires approval (in non-auto mode)bashactions such asexec/start/stop/writecan 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
jsonlfiles
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
allowedReadRootsandavailableSkillsback intoWorkspaceContext
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".
16. Recommended reading order
- Runtime Architecture
- Session Runtime
- Tools and Approvals
- Compact and Checkpoint
- CLI and TUI
- MCP and ACP
To keep following this main line on the next page, go straight to Runtime Architecture.