Coding agents can accelerate Jmix application development, but teams still need a reliable way to guide and verify the resulting changes. This article explains what Jmix provides as a foundation for coding-agent development and how teams can build on it with application-specific architecture, project knowledge, and automated feedback. Together, these mechanisms create bounded autonomy and make agent-generated changes more consistent, reviewable, and trustworthy.
1. Delivering on the Promise of Coding Agents
The real promise of coding agents is not faster code generation on its own. It is reliable delegation: a team can hand over substantial work, let an agent operate autonomously for longer, and still receive results at a consistent level of quality.
With the current generation of frontier models in 2026, this promise is realistic — but it does not come out of the box simply by choosing the most capable model. It requires engineering around the model: teams have to help the agent help itself by shaping the environment in which it receives work, makes decisions, and verifies the result (a practice now commonly called “harness engineering”) — so that a human reviewer has concrete reasons to trust it.
Reliable delegation requires three conditions:
- A good description of the desired outcome. The prompt or Jira task describes the problem, the relevant context and constraints, and what a successful result should look like. It does not need to prescribe every implementation step or eliminate all ambiguity. During the planning phase, an AI agent can inspect the existing source code, act as a sparring partner for the team, challenge assumptions, and help turn the discussion into a shared understanding of what should be achieved.
- Relevant guidance. The agent needs to understand how the solution should fit the existing application. Depending on the task, this includes architectural boundaries, framework and project conventions, and established implementation procedures.
- Autonomous verification. The agent needs feedback it can act on during the implementation loop. Compilation, tests, analysis, and focused reviews allow problems to be detected and corrected before the result reaches a person.
The first condition sits before the implementation loop and is not the primary focus of this article. It can nevertheless benefit from many of the same mechanisms. When a planning agent researches the repository, explicit architecture and externalized project knowledge help it understand the existing system, identify affected areas, and produce a better description of the desired outcome.
The second and third conditions determine what happens after that outcome is handed to an implementation agent. Without relevant guidance, the agent has to infer architectural intent and local conventions from incomplete signals. Without autonomous verification, routine deviations remain for a person to discover during review. As agent-driven implementation accelerates, these gaps accumulate faster than human reviewers can compensate for them. The result is the trust and review problem described next.
2. The Trust and Review Problem
A coding agent can turn one feature request into changes across the data model, services, views, migrations, security, and tests. A team can run several agents at the same time and produce more code than its developers could have written manually. Implementation capacity increases immediately; the capacity to understand, review, and accept those changes does not.
This creates a trust problem and a code-review bottleneck. An agent can produce plausible code that compiles and still place business logic in the wrong module, expose a persistence model across a business boundary, or leave migrations and security policies incomplete. The reviewer then has to reconstruct the intended architecture before judging the business change. Without stronger guardrails, some of the time saved during implementation may therefore shift into review.
Parallel agents make the problem structural: ten agents can grow a monolith and reproduce a weak pattern faster than reviewers can correct it. Modularity is therefore not an ivory-tower exercise here — it keeps concurrent changes local and makes architectural deviations visible as the application grows. The practices that address this are not new: human-led teams often compensate for weak boundaries or slow feedback through shared context and careful review. They become prerequisites once agents work independently or in parallel, because the person holding architectural intent is no longer the one making the change, human compensation no longer scales, and the engineering environment must carry that intent to the agent and verify the result at machine speed.
The central question is how a team can trust agent-generated changes without turning human review into the new delivery bottleneck. This article calls the answer bounded autonomy: the agent can implement, verify, and correct a substantial change inside explicit limits. People remain responsible for requirements and architecture, but repeatable questions about placement, dependencies, completeness, and basic behavior move into the repository's structure and checks.
The following sections trace this approach through the jmix-insurance project, where a connected insurance flow crosses several explicit business boundaries. It provides a concrete setting for examining how the three guardrail mechanisms — architecture in the code, externalized knowledge, and automated feedback — work together.
3. The Case Study: Guardrails in a Connected Jmix Application
jmix-insurance models a familiar insurance process: a partner receives a quote for an insurance product, accepting the quote creates a policy, and policy creation produces the account and payment documents for the coverage period. The flow is small enough to trace end to end and interconnected enough to exercise meaningful architectural boundaries.
The repository applies all three guardrail mechanisms to this flow.
- The source structure makes ownership within each business area explicit,
- The documentation and Agent Skills externalize project knowledge,
- Compiler checks, tests, architecture rules, and CI provide fast feedback.
Together, these mechanisms constrain and verify changes that cross those boundaries.
Although compact, the flow crosses distinct business responsibilities. jmix-insurance assigns each responsibility to a bounded context: a Domain-Driven Design boundary within which one domain model and vocabulary apply. The Partners context owns policyholder data, the Quotes context owns the offer and its state transitions, the Policies context owns the insurance contract, and the Accounts context owns the financial records. The Products context provides the insurance products and payment frequencies used by the flow, while the Security context provides users and access control.

This is enough interaction to create the architectural pressure found in a larger enterprise application. The Quotes context needs data from the Partners context without taking ownership of it. The Policies context must create a policy from a quote without making the Quote entity part of its model. The Accounts context needs policy identifiers and commercial values without depending on the Policy entity through JPA.
jmix-insurance is a modular monolith: one Jmix application running in one Spring Boot process and using one database. That keeps the complete flow straightforward to run while its source structure, externalized knowledge, and automated checks make the internal boundaries explicit.
4. A Guardrail System Creates Bounded Autonomy
Giving a coding agent more autonomy is an engineering challenge, not a permission setting. A team can let an agent work longer, make broader changes, or run alongside other agents only when the surrounding system keeps that work inside understood limits. The goal is bounded autonomy: the agent completes more work independently, while responsibility for requirements and architecture stays with the team rather than shifting to the agent.
The established Levels of Driving Automation provide a useful analogy: moving from driver assistance toward conditional or high automation is not a single switch. Each level defines which tasks can be delegated, under which conditions, and when a person must take control again. Coding-agent autonomy develops in a similar way. A team can move closer to “hands off” only when a guardrail system guides the available paths, provides relevant context, detects deviations, and returns control when judgment is required. For a coding agent, much of that system lives in the engineering environment rather than in the model itself.
This guardrail system's mechanisms fall into three areas. Source architecture shapes the choices available during implementation. Externalized knowledge transports decisions that cannot be inferred from code alone. Automated feedback challenges the result before a reviewer has to rediscover routine violations.
Together they form the guardrail system: complementary controls to address different failure modes while serving the same goal of bounded autonomy.

Architecture in the code narrows the implementation paths available to the agent. Module boundaries, dependency direction, and ownership rules make some choices natural and others visibly exceptional. Their effect is to make the intended path easier to follow and deviations more visible as the agent translates instructions into code.
Externalized knowledge captures decisions that source structure cannot express on its own. Documentation, ADRs, and skills turn knowledge previously carried by experienced implementers into context the agent can use while planning and executing a change.
Automated feedback supplies evidence that those decisions were followed. Compilers, behavior tests, and architecture rules remove repeatable questions from human review and return failures while the agent can still correct them.
The guardrail system does not make agent output deterministic or remove the need for review. It gives a team reasons to trust the engineering process around the model and a path for increasing autonomy as the guardrails improve. The following chapters examine the three mechanisms in jmix-insurance, beginning with how its architecture shapes the choices available to an agent.
5. Architecture in the Code
To see how architecture in the code works as a guardrail, consider how jmix-insurance implements its bounded contexts and module dependencies. When a coding agent implements a change in this application, it works within the dependencies, package boundaries, and examples available in the repository. Those structures influence which solutions appear local and convenient, while externalized knowledge explains their rationale. In a flat codebase, the shortest implementation often crosses business boundaries because nothing makes that shortcut unusual. Here, the normal path follows bounded-context ownership, while a deviation requires an explicit and reviewable change.
Three design choices make this effect visible: module boundaries limit available dependencies, the quote-acceptance flow establishes collaboration direction, and local data ownership prevents persistence models from spanning contexts.
5.1 Module Boundaries Remove Easy Shortcuts
Each bounded context has a corresponding boundary in the source code. Public services, DTOs, and events define collaboration across those boundaries; persistence models and business behavior remain within the owning context.
These source boundaries shape the agent's implementation choices. When changing quote acceptance, the agent works in the Quotes context, where the Quote entity and related domain types are available to the module. Persistence types owned by the Policies context are not on the Quotes module's declared classpath. The agent can use the public contract exposed by the Policies context. Importing a Policy entity, by contrast, would require adding a direct build-time dependency from the Quotes module to the Policies persistence module. The boundary does not make a violation impossible, but it turns a convenient shortcut into a visible architectural decision.
Within one bounded context, the UI can bind directly to its local Jmix entities. Across context boundaries, it uses public contracts. This asymmetry preserves Jmix features such as entity-based loading and filtering without opening every persistent model to every module. The same ownership extends to migrations and security policies.
Readers who want the complete artifact map can follow the repository's architecture documentation. For the agent workflow, the central point is simpler: source structure narrows the set of plausible implementations, while the prompt and accessible project knowledge help the agent select the path intended for the task.
5.2 The Business Flow Makes Dependency Direction Visible
Quote acceptance provides one example that an agent can follow when implementing another cross-context change:

In this collaboration, the Quotes context asks the Policies context to create a contract through a public API. The Policies context publishes an event containing the values the Accounts context needs. The Accounts context creates its own financial records, and none of the three bounded contexts passes a persistent entity to another.
This pattern gives the agent both a restriction and an example. A new cross-context feature should exchange contract data rather than load a foreign entity, and an event can reverse dependency direction when the initiating bounded context should not know its downstream consumer.
The event is synchronous in this sample, so policy and account creation participate in the transaction opened for quote acceptance. If account creation fails, the complete operation can roll back. Moving that work after commit or into asynchronous processing would be a valid business choice, but guaranteed completion would then require durable delivery, retries, idempotency, and an explicit failure model.
5.3 Local Data Ownership Trades Convenience for Decoupling
The same bounded-context separation extends to persistence. The Accounts context stores the policy identifier, number, and other values it needs as local data rather than as a JPA relationship to the Policy entity owned by the Policies context. That prevents queries, fetch plans, and UI code in the Accounts context from navigating into another context's model.
In a conventional monolithic data model, a direct @ManyToOne from Account to Policy would be a natural solution. Without project-specific context, a coding agent is therefore likely to choose this familiar mapping as well. In jmix-insurance, however, that relationship would couple the persistence models of two bounded contexts and work against the option of extracting them later. The local-reference pattern makes this project-specific decision visible in the code.
This independence requires deliberate data duplication. The consuming bounded context must decide whether each copied value is a stable reference, a historical snapshot, or something that needs an update flow. Jmix filters and row-level constraints cannot transparently traverse a relationship that does not exist; requirements for current foreign data need an API query, local read model, or custom authorization logic.
In return, the persistence models remain decoupled, preserving the option to extract a bounded context later without first untangling a cross-context JPA graph. For a coding agent working in Accounts, that architectural goal becomes a concrete implementation path: extend the local representation and the contract or event that supplies it, rather than introduce an association to the Policy entity.
These boundaries give an agent constraints and precedents, but they do not explain every rationale, exception, or completion procedure. That is the role of externalized project knowledge. The next section examines how jmix-insurance makes that knowledge available to coding agents.
6. Externalized Knowledge
The second guardrail mechanism addresses knowledge that source code cannot convey on its own. In software teams, much of that shared understanding develops in planning sessions, reviews, pair programming, and everyday conversations. A developer learns why the team rejected an apparently simple shortcut, which exceptions are intentional, and what “done” means beyond compiling code. Over time, those decisions feel like common knowledge even when they were never written down.
A coding agent does not participate in that social context. It does not attend the conversations in which the team develops its architecture, testing practices, security conventions, and definition of done, nor does it absorb those conventions gradually through months of collaboration. For each task, it can use only the context made available through the prompt, the repository, and its tools. Repeating the team's accumulated knowledge in every prompt does not scale, especially when several agents work in parallel.
Operational knowledge therefore has to be externalized: recurring decisions, best practices, and completion expectations move out of individual memories and team rituals into accessible knowledge sources that an agent can discover when they are relevant. Otherwise the missing context reappears as corrections and explanations in code review.
jmix-insurance makes this knowledge available in two complementary forms. Repository instructions and architecture documents describe the current system, while ADRs preserve the reasoning behind its decisions. Skills then turn recurring decisions into focused implementation procedures. The agent can use both forms while working instead of forcing a reviewer to explain the same conventions after the code has been generated.
6.1 Repository Context and ADRs Explain the Local Architecture
In jmix-insurance, the project's agent instructions provide the broadest project context. They orient the agent before it starts a task and direct it to more detailed knowledge when needed.
jmix-insurance keeps its architecture documentation as Markdown alongside the source code, making it directly available to the agent during a working session. The documentation gives the agent a map of the system and directs it to the architectural context relevant to the task, so that context does not have to be reconstructed from implementation details each time. The same knowledge could live in Confluence or another system, provided the coding agent can access and load it when the task requires it.
The implementation shows what was built, but not why a particular choice was made. AccountPolicyReference shows that the Accounts context stores its own representation of Policy data, but not why a direct JPA relation was rejected or why the loss of cross-context entity-graph features is accepted. The repository's ADRs preserve that context, the alternatives, and the consequences. ADR-0004, for example, explains why an architecture rule exists; the rule itself reports the violation.
When a decision changes, the implementation, current-state documentation, corresponding ADR, and executable rule should change together, wherever those knowledge sources are stored.
6.2 Framework and Application Skills Serve Different Roles
The skills used with jmix-insurance come from two distinct levels. Framework skills contain knowledge that applies across applications and can therefore be provided by the framework vendor or its community. The Jmix Agent Toolkit provides this kind of reusable procedure. jmix-create-entity, for example, explains from the framework's perspective what constitutes a Jmix entity and how an agent should create or change one across the relevant parts of an application. It does not assume the architecture of a particular project.
Application-specific skills have a different owner and purpose. Only the application team can define which bounded context owns a concept, how modules may collaborate, which local infrastructure a change should use, and what the team considers complete. Architecture documentation can describe those decisions, and ADRs can explain their rationale. A skill adds the operational procedure: it tells the agent how to apply the decision consistently when performing a recurring type of change.
For example, the insurance-create-cross-module-reference skill turns the project's decision about cross-context data ownership into a repeatable procedure. The insurance-testing skill helps an agent reproduce the application's established testing approach instead of inventing a new setup for each change.
“Model the reference as a consumer-owned embedded value object in the consuming module… Do not add @ManyToOne / @OneToOne to a foreign module entity or persist a DTO, entity, or reference class from another module.”
Writing application skills is therefore part of externalizing application knowledge. When a decision should be reproduced across future changes, the team should capture not only what was decided and why, but also how an agent is expected to execute it. This prevents each task prompt or code review from becoming another manual explanation of the same procedure. For example, the cross-module-reference skill spells out execution steps, not just the rule:
“Extend the source module's API event or command with the minimal snapshot values the consumer needs. Do not pass foreign entities” and “Populate the reference in the consuming service/listener from the event/command. Do not call a foreign service from UI rendering just to display the reference.”
Skills can make agent-generated changes more consistent, but they remain guidance rather than deterministic automation. There is no guarantee that an agent will discover the relevant skill, invoke it, or follow every instruction correctly.
This makes independent feedback essential. The team has to evaluate the resulting change instead of assuming that the documented procedure was followed. Compilation, behavior tests, and architecture rules can turn selected expectations into executable failures, while semantic review can examine questions that are harder to encode. The next section follows that verification loop.
7. Automated Feedback
Automated feedback closes the gap between guidance and the actual result. It addresses the repeatable part of the review bottleneck: it cannot decide whether a requirement is correct or an architectural exception is justified, but it can reject misplaced dependencies, incomplete changes, and broken behavior before a person reviews the result.
Bounded autonomy depends on how much of that feedback the agent can use to verify and correct its own work. In jmix-insurance, all checks described in Sections 7.1 through 7.4 are available locally. Their focused variants return results quickly enough to become part of the implementation loop: run a check, receive the failure, correct the change, and repeat within the same session without human intervention.
CI then repeats the deterministic checks independently and broadens their scope. After they succeed, the pipeline adds the fresh-context agent reviews described in Section 7.5 before a person makes the final decision.
This separation is deliberate. It may seem simpler to ask one LLM-based reviewer to inspect the complete change against every project rule. On a large pull request — for example, 800 added and 200 removed lines — hundreds of rules and review questions compete for attention in the same context, making coverage less consistent. It is also wasteful to incur model cost and latency for conditions that a compiler, static analyzer, or architecture test can evaluate deterministically. The effective approach combines both: executable checks handle encoded rules quickly and consistently, while LLM-based review is used where semantic judgment adds value.

The sequence represents increasing scope, not a claim that every later check is stronger than every earlier one. The local loop keeps feedback close to the change so the implementing agent can act on it immediately. CI provides independent repetition and adds the broader checks that precede semantic and human review.
7.1 Compilation
Compilation is usually the fastest deterministic feedback available after an edit. It catches missing types, incompatible contracts, and unavailable dependencies without asking a reviewer to inspect the change. Because the result is unambiguous and close to the source of the problem, an agent can often correct the failure immediately and continue its task.
In jmix-insurance, the separate Gradle modules make this feedback more useful. An agent can first compile only the affected part of the application and later widen the check across the complete build. The module classpaths also reveal when code tries to use an implementation that the architecture has not made available.
Compilation proves structural consistency, not architectural correctness. A changed build dependency can make an unwanted import legal, and framework references stored in queries or XML may not appear as Java dependencies at all. Other checks must cover those decisions.
7.2 Behavior Tests
Code that compiles can still implement the wrong behavior. Behavior tests give the agent evidence about business outcomes: whether a state transition is valid, collaborating domains receive the right information, or a failed operation leaves the system consistent. Their purpose in the feedback loop is not only to protect against regressions, but to give the agent a concrete definition of success it can check before requesting review.
In jmix-insurance, focused tests provide fast feedback within one bounded context, while assembled integration tests verify behavior across context boundaries. This lets the agent check a change locally first and then validate its effect on the broader application flow, including transactional consistency. The tests focus on observable outcomes and collaboration contracts rather than the internal shape of individual classes.
Tests are source code too, so agent-generated tests need the same kind of project guidance as production code. In jmix-insurance, the application-specific insurance-testing skill and shared test infrastructure direct the agent to the appropriate test level and established setup. This keeps new tests homogeneous and focused on the intended boundary instead of introducing a parallel testing style. Coverage can highlight behavior that was never exercised, but it cannot establish that the assertions represent the right requirement.
7.3 Architecture Tests
Some dependencies are valid to the language and still wrong for the application. Architecture tests translate selected design decisions into executable rules, allowing the build to distinguish “this code compiles” from “this code follows our architecture.” This is especially valuable for coding agents because a violation returns as a direct failure instead of becoming a discussion late in human review.
In jmix-insurance, we use ArchUnit architecture tests to enforce the intended direction between modules and prevent persistent models from leaking across bounded-context boundaries. They also check framework-specific references that can appear in configuration or metadata rather than in ordinary Java imports. The exact rules belong to this case study; the broader pattern is to automate recurring architectural review questions wherever they can be expressed reliably.
Executable architecture covers only decisions that the team has encoded. It cannot decide whether a new boundary is sensible or whether an exception is worth its cost. Those remain human decisions. Once made, however, a rule can prevent future agents from accidentally introducing a second architecture.
7.4 Static Analysis and IDE Inspections
Static analysis covers repeatable quality problems that are neither business behavior nor architecture: formatting, suspicious code patterns, and common implementation defects. IDE inspections can provide additional framework-aware feedback while the agent is still working. Their value comes from returning a focused signal early, before a broader build obscures it among unrelated output.
jmix-insurance combines formatting checks from Spotless, static analysis from PMD and SpotBugs, and Jmix Studio code inspections exposed through the JetBrains MCP server. These tools are examples of the principle rather than required components of the approach: give the agent the narrowest useful feedback first, then verify the result at broader levels.
7.5 Focused Agent Reviews in Fresh Contexts
Starting a separate agent session creates a fresh review context: it sees the resulting diff as a reviewer rather than continuing the implementation conversation. That matters because an implementation agent can inspect its own work, but that inspection still happens inside the context window in which the change was produced. That accumulated context contains the assumptions, decisions, and discussion that led to the current solution. When the same agent reviews the result, this history can bias the evaluation toward accepting those choices and make the review less critical, whether that inspection happens while still coding or later in a pipeline.
A fresh context should also have a narrow review mandate. A general instruction to “review this change” leaves the agent to decide whether to prioritize architecture, security, user experience, tests, or another concern. The resulting coverage can be inconsistent, while asking one context to examine every concern makes the review diffuse. Focused reviews make the expected coverage explicit and allow each context to spend its attention on one coherent set of questions.
In CI, jmix-insurance applies both ideas concretely: CI first repeats the deterministic feedback outside the implementation session, so acceptance does not depend on what the implementing agent happened to run. Compilation and static analysis run before the complete test and coverage checks. Once those stages succeed, CI adds its own independent, narrowly focused reviews in fresh contexts.
For pull requests, jmix-insurance therefore runs several independent agent reviews after the deterministic CI jobs succeed. One focuses on domain design and module boundaries, another on semantic correctness and tests, and another on security and UI policies. Each starts with its own context, a specific prompt, and access to the relevant application skills and architecture knowledge. This prevents the reviewer from choosing its focus arbitrarily and makes the review responsibilities visible to the team.
These reviewers do not repeat compiler, test, or static-analysis failures. They compare the change with the project's documented decisions and inspect meaning that is difficult to encode as a stable rule: whether a local representation contains the right information, a transaction boundary matches the requirement, or a test demonstrates what its name claims.
This semantic verification step addresses the original review bottleneck from another direction. By the time a developer reviews the pull request, the change has passed deterministic checks and has been challenged by focused reviewers that did not share the implementation context. Their results are still probabilistic, and they can also miss or misinterpret an issue. They do not replace human review. They reduce the time people spend finding routine inconsistencies so they can focus on requirements, justified exceptions, architectural trade-offs, and final acceptance.
8. Conclusion: Bounded Autonomy for Coding Agents
When code generation scales beyond human speed, review and architectural coordination become the bottleneck. The three guardrail mechanisms address that gap from different directions: source architecture narrows the solution space, externalized knowledge transports architectural intent to the coding agent, and automated feedback produces evidence before the change reaches human review.
None of these practices is new. What changes is their status. In a human-led workflow, they may be treated as quality improvements because experienced developers compensate for what is missing. For partial or extensive implementation autonomy, they become essential operating conditions. Explicit module boundaries keep parallel growth local, externalized knowledge makes team decisions available to the agent, and automated checks absorb repeatable review questions.
The goal is not to make the agent responsible for architecture or to remove human review. It is to catch syntax errors, routine rule violations, and low-level inconsistencies earlier, so human reviewers can focus their attention on requirements, business behavior, and architectural trade-offs instead of being distracted by implementation details.
Teams do not need to adopt the complete setup at once. A practical starting point is the weakest part of the current workflow: an architecture that exists only in people's heads, a recurring procedure that is not documented, or a review rule that could return an automated failure. Clone the jmix-insurance repository, inspect one domain module, and run its executable architecture suite to see how the mechanisms reinforce one another.






