What Is Disciplined Guardrail-Based Development?
In AI-assisted software development, approaches like Vibe Coding—which prioritize momentum and intuition—often fail to ensure code quality and maintainability. To address this, Disciplined Guardrail-Based Development introduces structured rules ("guardrails") that guide AI systems during coding and maintenance tasks, ensuring consistent quality and reliability.
To get AI (LLMs) to generate appropriate code, developers must provide clear and specific instructions. Two key elements are essential:
- What to build – Clarifying requirements and breaking down tasks
- How to build it – Defining the application architecture
The way these two elements are handled depends on the development methodology or process being used. Here are examples as follows.
How to Set Up Disciplined Guardrails in GitHub Copilot
To implement disciplined guardrail-based development with GitHub Copilot, two key configuration features are used:
1. Custom Instructions (.github/copilot-instructions.md): This file allows you to define persistent instructions that GitHub Copilot will always refer to when generating code.
- Purpose: Establish coding standards, architectural rules, naming conventions, and other quality guidelines.
- Best Practice: Instead of placing all instructions in a single file, split them into multiple modular files and reference them accordingly. This improves maintainability and clarity.
- Example Use: You might define rules like using camelCase for variables, enforcing error boundaries in React, or requiring TypeScript for all new code.
- https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions
2. Chat Modes (.github/chatmodes/*.chatmode.md): These files define specialized chat modes tailored to specific tasks or workflows.
- Purpose: Customize Copilot’s behavior for different development contexts (e.g., debugging, writing tests, refactoring).
- Structure: Each .chatmode.md file includes metadata and instructions that guide Copilot’s responses in that mode.
- Example Use: A debug.chatmode.md might instruct Copilot to focus on identifying and resolving runtime errors, while a test.chatmode.md could prioritize generating unit tests with specific frameworks.
- https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes
The files to be created and their relationships are as follows.
Next, there are introductions for the specific creation method.
#1: Custom Instructions
With custom instructions, you can define commands that are always provided to GitHub Copilot. The prepared files are always referenced during chat sessions and passed to the LLM (this can also be confirmed from the chat history). An important note is to split the content into several files and include links to those files within the .github/copilot-instructions.md file. Because it can become too long if everything is written in a single file.
There are mainly two types of content that should be described in custom instructions:
A: Development Process (≒ outcome + Creation Method)
- What documents or code will be created: requirements specification, design documents, task breakdown tables, implementation code, etc.
- In what order and by whom they will be created: for example, proceed in the order of requirements definition → design → task breakdown → coding.
B: Application Architecture
- How will the outcome be defined in A be created?
- What technology stack and component structure will be used?
A concrete example of copilot-instructions.md is shown below.
# Development Rules
## Architecture
- When performing design and coding tasks, always refer to the following architecture documents and strictly follow them as rules.
### Product Overview
- Document the product overview in `.github/architecture/product.md`
### Technology Stack
- Document the technologies used in `.github/architecture/techstack.md`
### Coding Standards
- Document coding standards in `.github/architecture/codingrule.md`
### Project Structure
- Document the project directory structure in `.github/architecture/structure.md`
### Glossary (Japanese-English)
- Document the list of terms used in the project in `.github/architecture/dictionary.md`
## Development Flow
- Follow a disciplined development flow and execute the following four stages in order (proceed to the next stage only after completing the current one):
1. Requirement Definition
2. Design
3. Task Breakdown
4. Coding
### 1. Requirement Definition
- Document requirements in `docs/[subsystem_name]/[business_name]/requirement.md`
- Use `requirement.chatmode.md` to define requirements
- Focus on clarifying objectives, understanding the current situation, and setting success criteria
- Once requirements are defined, obtain user confirmation before proceeding to the next stage
### 2. Design
- Document design in `docs/[subsystem_name]/[business_name]/design.md`
- Use `design.chatmode.md` to define the design
- Define UI, module structure, and interface design
- Once the design is complete, obtain user confirmation before proceeding to the next stage
### 3. Task Breakdown
- Document tasks in `docs/[subsystem_name]/[business_name]/tasks.md`
- Use `tasks.chatmode.md` to define tasks
- Break down tasks into executable units and set priorities
- Once task breakdown is complete, obtain user confirmation before proceeding to the next stage
### 4. Coding
- Implement code under `src/[subsystem_name]/[business_name]/`
- Perform coding task by task
- Update progress in `docs/[subsystem_name]/[business_name]/tasks.md`
- Report to the user upon completion of each task
Note: The only file that is always sent to the LLM is `copilot-instructions.md`. Documents linked from there (such as `product.md` or `techstack.md`) are not guaranteed to be read by the LLM. That said, a reasonably capable LLM will usually review these files before proceeding with the work.
If the LLM does not properly reference each file, you may explicitly add these architecture documents to the context. Another approach is to instruct the LLM to review these files in the **chat mode settings**, which will be described later.
There are various “schools of thought” regarding application architecture, and it is still an ongoing challenge to determine exactly what should be defined and what documents should be created. The choice of architecture depends on factors such as the business context, development scale, and team structure, so it is difficult to prescribe a one-size-fits-all approach. That said, as a general guideline, it is desirable to summarize the following:
- Product Overview: Overview of the product, service, or business, including its overall characteristics
- Technology Stack: What technologies will be used to develop the application?
- Project Structure: How will folders and directories be organized during development?
- Module Structure: How will the application be divided into modules?
- Coding Rules: Rules for handling exceptions, naming conventions, and other coding practices
Writing all of this from scratch can be challenging. A practical approach is to create template information with the help of Copilot and then refine it. Specifically, you can:
- Use tools like M365 Copilot Researcher to create content based on general principles
- Analyze a prototype application and have the architecture information summarized (using Ask mode or Edit mode, feed the solution files to a capable LLM for analysis)
However, in most cases, the output cannot be used as-is.
- The structure may not be analyzed correctly (hallucinations may occur)
- Project-specific practices and rules may not be captured
Use the generated content as a starting point, and then refine it to create architecture documentation tailored to your own project.
When creating architecture documents for enterprise-scale application development, a useful approach is to distinguish between the foundational parts and the individual application parts. Discipline-based guardrail development is particularly effective when building multiple applications in a “cookie-cutter” style on top of a common foundation. A cler example of this is Data-Oriented Architecture (DOA). In DOA, individual business applications are built on top of a shared database that serves as the overall common foundation.
In this case, the foundational parts (the database layer) should not be modified arbitrarily by individual developers. Instead, focus on how to standardize the development of the individual application parts (the blue-framed sections) while ensuring consistency. Architecture documentation should be organized with this distinction in mind, emphasizing the uniformity of application-level development built upon the stable foundation.
#2 Chat Mode
By default, GitHub Copilot provides three chat modes: Ask, Edit, and Agent. However, by creating files under .github/chatmodes/*.chatmode.md, you can customize the Agent mode to create chat modes tailored for specific tasks.
Specifically, you can configure the following three aspects. Functionally, this allows you to perform a specific task without having to manually change the model or tools, or write detailed instructions each time:
- model: Specify the default LLM to use
(Note: The user can still manually switch to another LLM if desired)
- tools: Restrict which tools can be used
(Note: The user can still manually select other tools if desired)
- custom instructions: Provide custom instructions specific to this chat mode
A concrete example of .github/chatmodes/*.chatmode.md is shown below.
description: This mode is used for requirement definition tasks.
model: Claude Sonnet 4
tools: ['changes', 'codebase', 'editFiles', 'fetch', 'findTestFiles', 'githubRepo', 'new', 'openSimpleBrowser', 'runCommands', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'usages', 'vscodeAPI', 'mssql_connect', 'mssql_disconnect', 'mssql_list_servers', 'mssql_show_schema']
---
# Requirement Definition Mode
In this mode, requirement definition tasks are performed. Specifically, the project requirements are clarified, and necessary functions and specifications are defined. Based on instructions or interviews with the user, document the requirements according to the format below. If any specifications are ambiguous or unclear, Copilot should ask the user questions to clarify them.
## File Storage Location
Save the requirement definition file in the following location:
- Save as `requirement.md` under the directory `docs/[subsystem_name]/[business_name]/`
## Requirement Definition Format
While interviewing the user, document the following items in the Markdown file:
- **Subsystem Name**: The name of the subsystem to which this business belongs
- **Business Name**: The name of the business
- **Overview**: A summary of the business
- **Use Cases**: Clarify who uses this business, when/under what circumstances, and for what purpose, using the following structure:
- **Who (Persona)**: User or system roles
- **When/Under What Circumstances (Scenario)**: Timing when the business is executed
- **Purpose (Goal)**: Objectives or expected outcomes of the business
- **Importance**: The importance of the business (e.g., High, Medium, Low)
- **Acceptance Criteria**: Conditions that must be satisfied for the requirement to be considered met
- **Status**: Current state of the requirement (e.g., In Progress, Completed)
## After Completion
- Once requirement definition is complete, obtain user confirmation and proceed to the next stage (Design).
Tips for Creating Chat Modes
Here are some tips for creating custom chat modes:
- Align with the development process: Create chat modes based on the workflow and the deliverables.
- Instruct the LLM to ask the user when unsure: Direct the LLM to request clarification from the user if any information is missing.
- Clarify what deliverables to create and where to save them: Make it explicit which outputs are expected and their storage locations.
The second point is particularly important. Many AI (LLMs) tend to respond to user prompts in a sycophantic manner (known as sycophancy).
As a result, they may fill in unspecified requirements or perform tasks that were not requested, often with the intention of being helpful.
The key difference between Ask/Edit modes and Agent mode is that Agent mode allows the LLM to proactively ask questions and engage in dialogue with the user. However, unless the user explicitly includes a prompt such as “ask if you don’t know,” the AI rarely initiates questions on its own.
By creating a custom chat mode and instructing the LLM to “ask the user when unsure,” you can fully leverage the benefits of Agent mode.
About Tools
You can easily check tool names from the list of available tools in the command palette.
Alternatively, as shown in the diagram below, it can be convenient to open the custom chat mode file and specify the tool configuration.
You can specify not only the MCP server functionality but also built-in tools and Copilot Extensions.
Example of Actual Operation
An example interaction when using this chat mode is as follows:
- The LLM behaves according to the custom instructions defined in the chat mode.
- When you answer questions from GHC, the LLM uses that information to reason and proceed with the task.
- However, the output is not guaranteed to be correct (hallucinations may occur) → A human should review the output and make any necessary corrections before committing.
The basic approach to disciplined guardrail-based development has been covered above. In actual business application development, it is also helpful to understand the following two points:
- Referencing the database schema
- Integrated management of design documents and implementation code
(Important) Reading the Database Schema
In business application development, requirements definition and functional design are often based on the schema information of entities.
There are two main ways to allow the system to read schema information:
- Dynamically read the schema from a development/test DB server using MCP or similar tools.
- Include a file containing schema information within the project and read from it.
A development/test database can be prepared, and schema information can be read via the MCP server or Copilot Extensions. For SQL Server or Azure SQL Database, an MCP Server is available, but its setup can be cumbersome. Therefore, using Copilot Extensions is often easier and recommended. This approach is often seen online, but it is not recommended for the following reasons:
- Setting up MCP Server or Copilot Extensions can be cumbersome (installation, connection string management, etc.)
- It is time-consuming (the LLM needs schema information → reads the schema → writes code based on it)
Connecting to a DB server via MCP or similar tools is useful for scenarios such as “querying a database in natural language” for non-engineers performing data analysis. However, if the goal is simply to obtain the schema information of entities needed for business application development, the method described below is much simpler.
Storing Schema Information Within the Project
Place a file containing the schema information inside the project. Any of the following formats is recommended. Write custom instructions so that development refers to this file:
- DDL (full CREATE DATABASE scripts)
- O/R mapper files (e.g., Entity Framework context files)
- Text files documenting schema information, etc.
DDL files are difficult for humans to read, but AI (LLMs) can easily read and accurately understand them. In .NET + SQL development, it is recommended to include both the DDL and EF O/R mapper files. Additionally, if you include links to these files in your architecture documents and chat mode instructions, the LLM can generate code while understanding the schema with high accuracy.
Integrated Management of Design Documents and Implementation Code
Disciplined guardrail-based development with LLMs has made it practical to synchronize and manage design documents and implementation code together—something that was traditionally very difficult. In long-standing systems, it is common for old design documents to become largely useless.
- During maintenance, code changes are often prioritized.
- As a result, updating and maintaining design documents tends to be neglected, leading to a significant divergence between design documents and the actual code.
For these reasons, the following have been considered best practices (though often not followed in reality):
- Limit requirements and external design documents to the minimum necessary.
- Do not create internal design documents; instead, document within the code itself.
- Always update design documents before making changes to the implementation code.
When using LLMs, guardrail-based development makes it easier to enforce a “write the documentation first” workflow. Following the flow of defining specifications, updating the documents, and then writing code also helps the LLM generate appropriate code more reliably. Even if code is written first, LLM-assisted code analysis can significantly reduce the effort required to update the documentation afterward. However, the following points should be noted when doing this:
- Create and manage design documents as text files, not Word, Excel, or PowerPoint.
- Use text-based technologies like Mermaid for diagrams.
- Clearly define how design documents correspond to the code.
The last point is especially important. It is crucial to align the structure of requirements and design documents with the structure of the implementation code. For example:
- Place design documents directly alongside the implementation code.
- Align folder structures, e.g., /doc and /src.
Information about grouping methods and folder mapping should be explicitly included in the custom instructions.
Conclusion of Disciplined Guardrail-Based Development with GHC
Formalizing and Applying Guardrails
- Define the development flow and architecture documents in .github/copilot-instructions.md using split references.
- Prepare .github/chatmodes/* for each development phase, enforcing “ask the AI if anything is unclear.”
Synchronization of Documents and Implementation Code
- Update docs first → use the diff as the basis for implementation (Doc-first).
- Keep docs in text format (Markdown/Mermaid). Fix folder correspondence between /docs and /src.
Handling Schemas
- Store DDL/O-R mapper files (e.g., EF) in the repository and have the LLM reference them.
- Minimize dynamic DB connections, prioritizing speed, reproducibility, and security.
This disciplined guardrail-based development technique is an AI-assisted approach that significantly improves the quality, maintainability, and team efficiency of enterprise business application development. Adapt it appropriately to each project to maximize productivity in application development.