Foundations
Four ideas worth five minutes before you touch the agent. Everything else today is these ideas applied.
Context beats prompting
A model predicts the next token using only what's in its context window — training data, plus whatever you've fed it this conversation. It doesn't know your codebase, your BC version, or your customer's brief unless you put it there.
That's why "write a better prompt" only goes so far: a beautifully worded request over missing context still produces a confident guess. The lever that actually moves output quality is what you put in front of the model — the brief, the tech design, the real BC source — not the cleverness of the ask.
Context, model, harness
An agent is an LLM wired into a loop: it reads context, decides on a tool call, gets a result back, and reads that into its next turn — repeatedly, until it decides it's done.
Three things shape what it can do: the context you give it (specs, source code, MCP servers), the model itself (Opus reasons more carefully, Sonnet moves faster), and the harness — the tools it's actually allowed to call. It has no memory between sessions; the harness resends context every single turn. You're not pairing with a colleague who remembers yesterday — you're the architect deciding what walks into the room each time.
Plan first, then direct
Vibe coding is the loop most people start with: describe what you want in a message, the agent writes something, you look at it, you ask for changes. It doesn't scale — as the conversation lengthens, the agent loses track of earlier decisions because of context limits, and you end up re-explaining things you already said.
Agentic coding front-loads the planning instead: written specs that persist independent of chat history, so the agent works in a bounded scope — one feature at a time — and can verify its own work through testing rather than relying on you to catch every regression by eye.
Write it down first
The discipline that keeps agentic projects coherent. A constitution — brief, tech design, roadmap, coding rules — gets agreed once, before any feature code, so every later prompt has something authoritative to read instead of re-litigating decisions each session.
Then every feature runs the same loop: spec, implement, test, document, finalise. The specs aren't paperwork for its own sake — they're what lets you close a chat, open a fresh one tomorrow, and have the agent pick up exactly where you left off.
Kickoff
By the end of today you'll have a small, real Business Central extension — built end to end with an AI coding agent — and a loop you can run on every feature after this one.
- An AL project open, AL Language extension v18+ installed, with a BC sandbox (SaaS or local container) you can compile and run against
- Your coding agent running — Claude Code, Cursor, or Copilot — with access to Claude Opus 5 / Sonnet 5 or GPT-5.6; the model matters more than the tool
- Microsoft Learn MCP connected, so the agent can cite official docs instead of guessing — it's a remote server, no install:
https://learn.microsoft.com/api/mcp - AL MCP (
altool) connected, so the agent can build, read diagnostics, and run tests itself instead of you relaying compiler errors by hand - The Business Central base source added as a git submodule under
external/— the agent should read real BC code, not guess at it - An empty
specs/folder ready to hold today's documents
git clone --depth 1 https://github.com/microsoft/BCApps external/BCApps git submodule add --force https://github.com/microsoft/BCApps external/BCApps git config -f .gitmodules submodule.external/BCApps.branch main git config -f .gitmodules submodule.external/BCApps.shallow true git add .gitmodules external/BCApps git commit -m "Add BCApps submodule (main, shallow)"
/plugin install microsoft-docs@claude-plugins-official
{"microsoft-learn": {"type": "http", "url": "https://learn.microsoft.com/api/mcp"}}. For the AL MCP, install altool via dotnet and register it with your agent — see your agent's MCP settings for the exact syntax.
One thing before we start
Everything below is a workflow, not a tool. Swap in whichever agent you use — the discipline is what compounds: spec before code, review before merge, tests before you call it done.
The brief
Our customer rents out equipment — power tools, AV gear, event kit — to business customers by the day. Three capabilities, in build order:
Equipment register
What we own, its daily rate, and whether it's available, out on rent, or in maintenance.
Rental agreements
A customer rents one or more items for a date range. Catch double-bookings; record checkout and checkin.
Pricing & posting
Charge is days × daily rate. Closing an agreement posts it as a ledger transaction.
specs/brief.md in your repo and paste the three rows above into it, in your own words if you like. This file is the anchor document — every prompt from here on tells the agent to read it, so it needs to exist before Constitution starts.
Constitution
Before any feature code, agree the shape of the whole extension with your agent, and write down how you expect AL code to look. Three documents plus one gut-check, about twenty-five minutes.
specs/tech-design.md
Read specs/brief.md carefully. You have access to the full Business Central source code in external/BCApps and to Microsoft Learn via MCP. Use both. Produce specs/tech-design.md with the following structure: for each requirement in the brief, write a section with: 1. What standard Business Central already provides to cover this requirement — cite specific BC source files or Microsoft Learn URLs as evidence. 2. What gaps remain that standard BC cannot cover without custom code. 3. A brief implementation decision: how we will implement this feature, favouring standard BC features, configuration, and extension points over custom development. Do not write AL code. Describe the approach in plain language. Ground rules: - Exhaust standard BC options before proposing custom tables, documents, or posting logic. - Where standard BC covers a requirement, cite evidence — don't propose a custom alternative anyway. - Keep custom code thin; prefer extending existing objects over creating new ones. - Don't guess — say what you researched if you're not sure.
A second opinion on tech-design.md → iterate until no new issues surface
The agent that wrote the design is anchored to its own reasoning. A second, independent pass — reading only the brief and the design, not the conversation that produced it — catches unaddressed requirements, custom work where standard BC already does the job, and claims about BC behaviour that were never actually verified.
- Install BC Code Intelligence MCP from github.com/JeremyVyska/bc-code-intelligence-mcp — follow the install instructions in the repo README
- Choose your approach: continue the current chat (recommended), fork it, or open a new one
- Select Opus 5 and activate the BC Code Intelligence MCP
- Paste the critique prompt below
- Take the critique seriously — revise specs/tech-design.md based on what it finds. If Alex Architect flags something, ask Opus to revise specs/tech-design.md accordingly. Repeat until no new issues surface.
Take a fresh look at the suggested @specs/tech-design.md using subagent. Use the Alex Architect persona from BC Code Intelligence (bc-knowledge mcp). Read specs/brief.md and specs/tech-design.md. Your job is to critique the tech design — not to be polite about it. Look for: 1. Requirements from the brief that are not addressed in the design. 2. Proposals for custom development where standard BC functionality already exists. 3. Over-engineered solutions where a simpler standard approach would work. 4. Any design decision that lacks justification or evidence from the BC source or Microsoft documentation. 5. Hallucinations — for every claim that a standard BC feature covers a requirement, verify it against the actual BC source in external/BCApps. If the feature does not exist, does not work the way the design describes, or is missing key capabilities needed to fulfil the requirement, call it out explicitly. For each issue you find, state: what the problem is, what a better approach would be, and where in the BC source or Microsoft Learn you found evidence for your recommendation. Do not summarise what the design does well. Focus only on what should change.
specs/roadmap.md
Read specs/tech-design.md and specs/brief.md. Produce specs/roadmap.md — an ordered list of implementation features. Rules: - Features build sequentially, with no forward dependencies. - Each entry includes: name, user benefit, status, implementation summary, and done-criteria. - No implementation detail, AL object references, or field names — that belongs in the feature spec, not here. - Keep it a queue, not a detailed specification.
AGENTS.md, via a reusable skill
Without shared rules, quality drifts — every new agent session is a fresh start. AGENTS.md is the contract: "this is how we write AL here, always." It's small enough to matter every time and boring enough that no one wants to write it by hand — which is exactly what makes it worth automating once.
1. Create the folders
In your workspace, create two empty folders: .copilot/rules/ and .copilot/skills/.
2. Create the skill file
Create .copilot/skills/setup-al-agentic-rules.md and paste in this definition:
--- name: setup-al-agentic-rules description: Bootstrap an AL project with the official Microsoft AL agentic rules from the alguidelines GitHub repo. Downloads all rule files to .copilot/rules/, adds .copilot/ to the workspace file, and writes or updates AGENTS.md with a standard three-section scaffold. Use when starting a new AL project, onboarding a new developer, or refreshing stale rule files. disable-model-invocation: true --- # Setup AL Agentic Rules Fetches the official Microsoft AL coding rules from GitHub and wires them into the project so every future agent session follows them automatically. ## Step 1 — Discover files in the GitHub folder Call the GitHub Contents API to get the current file list (never hard-code filenames): GET https://api.github.com/repos/microsoft/alguidelines/contents/content/docs/agentic-coding/vibe-coding-rules Parse the JSON response and collect every entry where "type": "file". Extract the name and download_url of each file. ## Step 2 — Download each file directly into .copilot/rules/ Ensure the .copilot/rules/ directory exists, then download every file from its download_url into .copilot/rules/<filename>. Do NOT use WebFetch and then Write — download straight to disk. On Windows (PowerShell): ```powershell New-Item -ItemType Directory -Force -Path ".copilot/rules" | Out-Null Invoke-WebRequest -Uri "<download_url>" -OutFile ".copilot/rules/<filename>" ``` Run all downloads in one shell call by chaining them with ; so every file is saved in a single round-trip. ## Step 3 — Add .copilot/ to the workspace file The .code-workspace file sits at the repo root — the same directory that contains app/, specs/, test/, and AGENTS.md. Do not assume the current working directory is the repo root when inside a workspace. Locate the workspace file explicitly: ```powershell $repoRoot = (Get-Item (Resolve-Path "specs/brief.md")).Directory.FullName $workspaceFile = Get-ChildItem -Path $repoRoot -Filter "*.code-workspace" | Select-Object -First 1 -ExpandProperty FullName ``` Then read the JSON, add { "path": ".copilot" } to the folders array if not already present, and write it back. The path .copilot is relative to the workspace file location (i.e. the repo root), so no absolute path is needed. ## Step 4 — Write AGENTS.md Write (or overwrite) AGENTS.md in the repo root with exactly this structure and wording: # <Project Name> — Project Rules ## What this project is <One sentence describing the BC extension and its business domain.> Read `specs/brief.md` for the full customer brief. ## SDD process This project uses Spec-Driven Development. Before implementing anything: 1. Read `specs/tech-design.md` and `specs/roadmap.md` 2. Every feature lives on branch `spec/YYYY-MM-DD-feature-name` 3. Create `specs/YYYY-MM-DD-feature-name/requirements.md` + `plan.md` + `acceptance.md` before writing any code 4. Loop: Spec → Implement → Test → Docs → Merge ## AL coding standards See `.copilot/rules/` for detailed rules. --- Fill in the project name and the one-sentence description from specs/brief.md. Do not add extra sections. Do not expand the SDD process list. Write it exactly as shown. ## Verification After completing all steps, confirm: - .copilot/rules/ contains all files from the GitHub folder - .code-workspace has { "path": ".copilot" } in folders - AGENTS.md exists at the repo root with all three sections ## Notes - Always fetch from GitHub — never generate or paraphrase rule content. - AGENTS.md should be kept short; detailed rules live in .copilot/rules/.
3. Invoke it
Setup AL agentic rules
- Every official AL rule file in
.copilot/rules/ .copilot/wired into the workspace file- A short, three-section
AGENTS.md: what this project is, the SDD process, and where the AL standards live
The feature loop
Once the constitution is in place, every feature follows the same short loop:
- Spec — produce requirements.md, plan.md, and acceptance.md for this feature on a dedicated branch
- Implement — the agent builds from the spec; it can compile, test, and fix autonomously
- Test — confirm the feature works in the actual product; all automated tests pass
- Docs — write the user documentation and update the CHANGELOG
- Finalise — merge the feature branch, update the roadmap, replan if anything shifted
The loop is the same for every feature. Small features take one session. Large features take several. The structure doesn't change.
Feature 1 — Equipment Register
~40 minRegister what we own: item, type, daily rate, status. This feature runs the loop by hand once — and packages every step into a skill so Feature 2 and 3 don't have to.
Ask the agent first: Please, create the branch for the next feature.
Requirements, plan, acceptance
Read AGENTS.md, specs/tech-design.md, and specs/roadmap.md. We are starting Feature 1 — Equipment Register (roadmap row 1). Create a feature spec in a specs/ folder named after the feature branch, with three documents: requirements.md (what it does, and what it explicitly doesn't), plan.md (AL objects, table/page names, key fields — no new tables beyond what this feature needs), and acceptance.md (testable scenarios). Follow specs/tech-design.md exactly. Do not write any AL code yet.
- Every acceptance scenario has a concrete before/after — not "works correctly"
- plan.md reuses existing BC fields where they fit, instead of inventing new ones
- Status values match what tech-design.md named
Table, list, card
Implement the feature spec.
- Every changed file, in the diff panel — accept consciously, you're responsible for the code, not the agent
- Ask for fixes conversationally instead of hand-editing — e.g. "extract this trigger logic into local functions with early exits" to match AGENTS.md
Publish, smoke test, automate
Publish the app (Ctrl+F5) and check it by hand first: create an equipment card, set its type and daily rate, confirm status defaults to Available.
Write an AL test codeunit covering every scenario in acceptance.md. Run it and paste the results.
docs/user-guide.md
Read specs/brief.md, specs/roadmap.md, and this feature's spec. Update docs/user-guide.md: add a section for Equipment Register covering what it does, setup, and how to use it — plain language, for the end user, not the developer.
This file is a living document — it grows one section per feature, all day.
Turn what you learned into a skill
When you close this chat and open a new one for the next feature, the agent starts fresh. Everything it learned — how you structured the docs, how to review them — is gone. Skills fix this: instead of re-explaining the same things in every chat, you package the learning once and invoke it by name.
/create-skill Based on what we produced in this feature — the user-guide.md structure, the review process, and the corrections made — create a skill file at .copilot/skills/generate-docs.md that automates the same documentation workflow for the next feature.
The agent produces a skill that carries the workflow — and the lessons — into every future feature session automatically.
Changelog, roadmap, merge
Add a dated entry to CHANGELOG.md, sync any implementation decisions back into specs/tech-design.md, and mark row 1 done in specs/roadmap.md.
git checkout main git merge <the feature branch>
Two skills to create before moving on
You'll use both in every feature from here.
Spec skill
You just ran the spec process by hand. Package it once so the next feature can invoke it by name:
/create-skill Based on the spec process we used for this feature — reading the constitution, identifying the next planned feature from the roadmap, creating the feature branch, and generating requirements.md, plan.md, and acceptance.md — create a skill at .copilot/skills/create-feature-spec.md that automates this workflow for future features.
Finalise skill
The same finalise steps will repeat for every feature:
/create-skill Based on what we just did — updating CHANGELOG, syncing tech-design, marking the roadmap, merging, and replanning — create a skill at .copilot/skills/finalise-feature.md that automates this workflow for future features.
Feature 2 — Rental Agreements
~18 minA customer rents one or more items for a date range. Catch double-bookings; record checkout and checkin.
create-feature-spec
/create-feature-spec
Reads AGENTS.md, tech-design.md, and roadmap.md, finds the next unstarted row (Feature 2 — Rental Agreements), creates the branch, and writes requirements.md, plan.md, and acceptance.md.
- An explicit overlap-detection rule, not "the system prevents conflicts"
- plan.md references Feature 1's status field rather than adding a parallel one
Agreement document
Implement the feature spec.
- The Equipment table from Feature 1 is reused, not duplicated
Including the conflict case
Publish (Ctrl+F5) and try it by hand: book the same item for two overlapping date ranges and confirm the second one is blocked.
Write an AL test codeunit covering every scenario in acceptance.md, including: booking two overlapping agreements for the same item is blocked. Run it and paste the results.
generate-docs
/generate-docs
Runs the same documentation workflow you packaged in Feature 1 — reads the spec, updates docs/user-guide.md, same structure, same review process.
finalise-feature
/finalise-feature
Updates CHANGELOG.md, syncs tech-design.md, marks row 2 done, merges to main, and replans — the whole checklist from Feature 1, in one line. Read its summary before it merges.
Feature 3 — Pricing & Posting
~17 minCharge is days × daily rate. Closing an agreement posts it as a ledger transaction.
create-feature-spec
/create-feature-spec
Finds Feature 3 — Pricing & Posting (roadmap row 3), creates the branch, writes requirements.md, plan.md, acceptance.md — following tech-design.md's posting strategy and Feature 2's checkout/checkin dates.
Charge calculation and posting
Implement the feature spec.
Including the money case
Publish (Ctrl+F5) and try it by hand: close a 3-day agreement and check the posted amount equals 3 × the item's daily rate.
Write an AL test codeunit covering every scenario in acceptance.md, including: closing a 3-day agreement at the item's daily rate posts the correct amount. Run it and paste the results.
generate-docs
/generate-docs
finalise-feature
/finalise-feature
Marks row 3 done — that's the workshop scope complete.
Wrap-up
Feature 1 took 45 minutes and built four things at once: the feature, and three reusable skills. Feature 2 and 3 took a third of that each, because spec, docs, and finalise stopped being prompts you wrote and became commands you ran. That's the whole method — you stopped typing and started directing, and the agent wrote the code.
Keep specs/roadmap.md as the map, and keep .copilot/skills/ as the toolbox. The next session starts at the first unstarted row, with every skill you built today already in reach.