danielhuber.dev@proton.me Wednesday, April 8, 2026

Requirements as Code: Git-Native Business Documents for Agentic Workflows

Exploring the idea of putting business requirements, architecture diagrams, and domain models in Git — and how this could enable agentic pipelines from requirement change to deployed code.


February 26, 2026

A coding agent sees code. An orchestrator agent sees tasks. But neither sees the business intent behind what they build — unless you give them a way to access it. Today that intent often lives in wiki pages, Word documents, issue trackers, and design tools. These are largely opaque to agents. They cannot be easily diffed, they cannot trigger pipelines, and they cannot be traced back to a specific code change.

One idea worth exploring: put your business documents in Git.

Not as an afterthought. Not as a mirror of the “real” documents somewhere else. The idea is that Git could serve as the single source of truth for requirements, domain models, architecture decisions, and business rules. Similar to how infrastructure-as-code brought ops into version control, requirements-as-code could bring business intent into the developer workflow — and potentially into the context window of coding agents.

The Core Principle

If an agent cannot read it, diff it, and act on it programmatically, it is effectively invisible in an agentic workflow. Business documents locked in rich-text editors or SaaS tools are hard to consume automatically. Structured files in a repository are much more accessible.

Why Business Documents Matter More Now

For most of software history, requirements were written to be consumed once and never looked at again. You wrote a spec so a developer could translate it into code — once the code existed, the document drifted, went stale, and nobody updated it. This worked because the bottleneck was always the coding. Requirements could be vague, incomplete, even contradictory, and a skilled developer would fill in the gaps.

Coding agents are starting to change this equation.

When an agent writes the code, the quality of the output tends to be bounded by the quality of the input. A vague requirement can produce vague code. An incomplete schema may produce an incomplete data model. Agents generally do not fill in gaps with experience and intuition the way a senior developer might — they may fill them with assumptions or hallucinations. There is an argument that in an increasingly agentic world, the specification becomes the bottleneck, not the implementation.

This could expand what engineering work looks like. Writing precise specifications — domain models with clear constraints, business rules with unambiguous conditions, architecture decisions with explicit rationale — becomes as important an engineering task as the implementation itself.

This might also have implications for governance. If code is largely derived from approved specifications, the requirement approval could become a primary control point. The PR that changes a business rule may be more consequential than the PR that implements it — because the business rule PR is where the decision actually happens.

The loop could also run in both directions. Agents could detect drift between documentation and code — flagging when an implementation no longer matches the documented requirement, or when a schema in docs/ has fields that don’t appear in the data model. Business documents could evolve from static artifacts into living contracts that the system continuously validates against.

Once requirements are structured and machine-readable, they also become reusable beyond their original purpose. Auditors asking “why does this work this way?” can be pointed to the exact versioned, approved spec instead of digging through old tickets. Acceptance criteria in YAML can generate test cases directly — the spec becomes both the input to code generation and the input to test generation.

The Inversion

Traditional workflow: write requirements, then write code to match. Possible agentic workflow: write requirements, and code follows with increasing automation. The better your requirements, the less manual coding may be needed.

Why Git for Business Documents

Git already solves many of the problems that business document management has struggled with for decades:

Versioned history. Every change is a commit. No more “v2_final_FINAL_reviewed.docx”.

Diffs as communication. When someone changes a requirement, the diff shows exactly what changed — a changed field, a new constraint, a removed criterion. Agents and humans alike can read the delta precisely.

Pull requests as approval gates. Changing a requirement becomes a PR. Stakeholders review, approve, and the approval is recorded and immutable.

Blame and traceability. git blame on a requirements file tells you who specified the behavior and when. Bugs can be traced back to the requirement that drove them.

Branching for proposals. Major requirements changes can be proposed on a branch, discussed in PR comments, and merged when ready — the same workflow code already uses.

What Goes in the Repository

Not every business artifact belongs in Git. The key criterion is: does an agent need to read this to do its job? If yes, it belongs in a structured, parseable format in the repository.

Repository Structure with Business Documents
project-root/
├── docs/
│   ├── requirements/
│   │   ├── user-stories/
│   │   │   ├── checkout-flow.md
│   │   │   └── inventory-management.md
│   │   ├── business-rules/
│   │   │   ├── pricing-rules.yaml
│   │   │   └── compliance-constraints.yaml
│   │   └── acceptance-criteria/
│   │       └── checkout-flow.yaml
│   ├── architecture/
│   │   ├── decisions/
│   │   │   ├── 001-use-event-sourcing.md
│   │   │   └── 002-split-payment-service.md
│   │   ├── diagrams/
│   │   │   ├── system-context.mermaid
│   │   │   └── data-flow.mermaid
│   │   └── constraints.yaml
│   ├── domain/
│   │   ├── entities/
│   │   │   ├── order.yaml
│   │   │   ├── customer.yaml
│   │   │   └── product.yaml
│   │   ├── glossary.md
│   │   └── bounded-contexts.yaml
│   └── changelog.md
├── src/
│   └── ...
└── tests/
  └── ...

Single Repo vs. Separate Documentation Repo

Where business documents live depends on your team structure.

Single repo (monorepo or single-team projects): Place documents in a docs/ folder alongside src/ and tests/. This is the simplest approach — agents see both the spec and the code in one checkout, path-based CI triggers handle docs/ changes independently, and CODEOWNERS can assign different reviewers for docs/ vs src/. Exclude docs/ from production deployments the same way you exclude tests/ or .github/ — a line in .dockerignore or your build config is all it takes.

Separate documentation repo (multi-repo setups): When your codebase is already split across repositories — for example, a backend repo and a frontend repo maintained by different teams — a dedicated documentation repo makes more sense. Domain models, business rules, and API contracts are shared concerns that don’t belong exclusively to either codebase. A change merged in the documentation repo can trigger webhooks that notify agents in both code repositories independently. Business stakeholders interact only with the documentation repo and never need access to the code. Each repo maintains its own review process and deployment pipeline.

Multi-Repo Structure with Shared Documentation
project-docs/                  ← Shared documentation repo
├── requirements/
│   ├── user-stories/
│   └── business-rules/
├── architecture/
│   ├── decisions/
│   └── diagrams/
├── domain/
│   ├── entities/
│   └── glossary.md
├── api-contracts/
│   └── openapi.yaml
└── frontend-specs/
  ├── screens/
  │   ├── checkout.yaml
  │   └── product-detail.yaml
  └── design-tokens.json
       │
       │  webhooks / CI triggers on merge
       ├──────────────────────────────┐
       v                              v
project-backend/               project-frontend/
├── src/                       ├── src/
└── tests/                     └── tests/

Format Matters

Agents parse structured text far better than prose. The choice of format directly affects how well an agent can act on the content.

Document Format Comparison for Agent Consumption
FormatHuman ReadableAgent ParseableDiffableBest For
MarkdownExcellentGoodExcellentNarratives, ADRs, user stories
YAMLGoodExcellentGoodSchemas, rules, structured specs
MermaidGood (rendered)GoodGoodArchitecture diagrams, flows
JSON SchemaFairExcellentFairAPI contracts, entity definitions
Word/PDFExcellentPoorNoneExternal stakeholders only

A practical example — an entity schema that both humans and agents can work with:

# docs/domain/entities/order.yaml
entity: Order
description: A customer purchase order
status: approved
last_reviewed: 2026-02-15

fields:
- name: order_id
  type: UUID
  required: true
  description: Unique order identifier

- name: customer_id
  type: UUID
  required: true
  references: Customer
  description: The customer placing the order

- name: line_items
  type: list<LineItem>
  required: true
  min_items: 1
  description: Products being purchased

- name: status
  type: enum
  values: [draft, confirmed, paid, shipped, delivered, cancelled]
  default: draft
  description: Current order lifecycle state

- name: total_amount
  type: decimal
  currency: true
  description: Calculated total including tax

business_rules:
- rule: "Orders cannot be cancelled after shipping"
  constraint: "status != 'shipped' AND status != 'delivered'"
- rule: "Minimum order value is $10"
  constraint: "total_amount >= 10.00"
# docs/requirements/business-rules/pricing-rules.yaml
domain: Pricing
status: approved
last_reviewed: 2026-02-20

rules:
- id: PRICE-001
  name: Volume Discount
  description: >
    Orders with more than 100 units of a single SKU
    receive a 10% discount on that line item.
  condition: line_item.quantity > 100
  action: apply_discount(line_item, 0.10)
  priority: 1
  effective_date: 2026-01-01

- id: PRICE-002
  name: Loyalty Tier Pricing
  description: >
    Gold-tier customers receive 5% off all orders.
    Platinum-tier customers receive 8% off.
  condition: customer.loyalty_tier in [gold, platinum]
  action: |
    if customer.loyalty_tier == gold:
      apply_discount(order, 0.05)
    if customer.loyalty_tier == platinum:
      apply_discount(order, 0.08)
  priority: 2
  effective_date: 2026-01-01

- id: PRICE-003
  name: Free Shipping Threshold
  description: Orders over $75 qualify for free shipping.
  condition: order.subtotal >= 75.00
  action: waive_shipping(order)
  priority: 3
  effective_date: 2026-03-01
# ADR-002: Split Payment Service

## Status
Accepted (2026-02-10)

## Context
The monolithic order service handles payment processing
inline. Payment provider outages cause order creation
to fail entirely. Processing time adds 2-3 seconds to
the checkout flow.

## Decision
Extract payment processing into a dedicated service
that communicates via async events. Orders are created
immediately with status "pending_payment". The payment
service processes charges independently and updates
order status via domain events.

## Consequences
- Order creation no longer blocked by payment processing
- Payment failures can be retried without re-creating orders
- Requires eventual consistency — UI must handle pending states
- Need idempotency keys to prevent duplicate charges

## Implementation Notes
- Use event sourcing for the payment service
- Idempotency key = order_id + attempt_number
- Dead letter queue for failed payment events

The Agentic Pipeline: From Requirement Change to Deployed Code

This is where things get interesting. When business documents live in Git — whether alongside the code or in a dedicated documentation repo — the flow from “requirement changed” to “code deployed” could potentially be automated with agents in the loop. The pipeline below works in both models; the only difference is whether the CI trigger fires within the same repo or across repos via a webhook.

Agentic Requirements-to-Deployment Pipeline
Requirement Author       Git Repository           Agent Pipeline
┌──────────────┐    ┌─────────────────────┐    ┌──────────────────┐
│ Edit business │───>│ Push to branch      │───>│ CI detects change│
│ document      │    │ Open PR for review  │    │ in docs/ path    │
└──────────────┘    └─────────────────────┘    └────────┬─────────┘
                                                        │
                    ┌─────────────────────┐             │
                    │ Stakeholders review  │<────────────┘
                    │ and approve req PR   │
                    └──────────┬──────────┘
                               │ merge
                               v
                    ┌─────────────────────┐
                    │ Agent reads the diff │
                    │ Understands what     │
                    │ changed and why      │
                    └──────────┬──────────┘
                               │
                               v
                    ┌─────────────────────┐
                    │ Agent generates      │
                    │ implementation plan  │
                    │ (scoped code changes)│
                    └──────────┬──────────┘
                               │
                               v
                    ┌─────────────────────┐
                    │ Coding agent(s)      │
                    │ implement changes    │
                    │ Run tests            │
                    └──────────┬──────────┘
                               │
                               v
                    ┌─────────────────────┐
                    │ Open code PR         │
                    │ linked to req commit │
                    │ Human review + merge │
                    └──────────┬──────────┘
                               │
                               v
                    ┌─────────────────────┐
                    │ Deploy               │
                    └─────────────────────┘

Step by Step

1. Someone edits a requirement. They change a field in docs/domain/entities/order.yaml, adding a new discount_code field. They open a PR with a description of why: “Support promotional discount codes at checkout.”

2. Stakeholders review the requirement PR. Product, engineering, and compliance review the change. They approve and merge. This is the governance checkpoint — the moment where the business formally signs off on the change.

3. The merge triggers an agent pipeline. A CI workflow detects that files in docs/ changed. It invokes an orchestrator agent, passing the commit diff as input.

4. The agent reads the diff, plans, and implements. It sees the new discount_code field, reads related business rules for context, produces a scoped plan (data model, API, validation, tests), and coding agents implement the changes on an isolated branch.

5. A code PR is opened, linked to the requirement commit. Reviewers can trace the code change directly back to the business decision. After review, the code merges and deploys — the full chain is traceable and auditable.

Implementation Patterns

Git Hooks for Validation

Enforce structure and consistency before requirements even reach review:

# .github/workflows/validate-requirements.yml
name: Validate Business Documents
on:
pull_request:
  paths:
    - 'docs/requirements/**'
    - 'docs/domain/**'

jobs:
validate:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Validate YAML schemas
      run: |
        pip install yamale
        yamale -s schemas/entity-schema.yaml docs/domain/entities/
        yamale -s schemas/business-rule-schema.yaml docs/requirements/business-rules/

    - name: Check cross-references
      run: |
        python scripts/check-references.py \
          --entities docs/domain/entities/ \
          --rules docs/requirements/business-rules/

    - name: Lint Markdown
      run: npx markdownlint-cli2 "docs/**/*.md"
# .github/workflows/agent-on-requirement-change.yml
name: Agent Implementation Pipeline
on:
push:
  branches: [main]
  paths:
    - 'docs/requirements/**'
    - 'docs/domain/**'

jobs:
implement:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 2

    - name: Get requirement diff
      id: diff
      run: |
        echo "changes<<EOF" >> $GITHUB_OUTPUT
        git diff HEAD~1 -- docs/ >> $GITHUB_OUTPUT
        echo "EOF" >> $GITHUB_OUTPUT

    - name: Run orchestrator agent
      env:
        ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
      run: |
        python scripts/orchestrate.py \
          --diff "${{ steps.diff.outputs.changes }}" \
          --repo . \
          --create-pr
# scripts/orchestrate.py
"""
Reads a requirement diff and generates
an implementation plan for coding agents.
"""
import anthropic
import subprocess
import json

def read_diff(diff_text: str) -> dict:
  """Parse the diff to identify what changed."""
  client = anthropic.Anthropic()

  response = client.messages.create(
      model="claude-opus-4-6",
      max_tokens=4096,
      system="""You are a requirements analyst.
Given a git diff of business documents,
identify: what changed, the business intent,
and what code changes are needed.
Return structured JSON.""",
      messages=[{
          "role": "user",
          "content": f"Analyze this diff:\n{diff_text}"
      }]
  )
  return json.loads(response.content[0].text)

def create_implementation_branch(plan: dict):
  """Create a branch and implement changes."""
  branch = f"auto/implement-{plan['change_id']}"
  subprocess.run(["git", "checkout", "-b", branch])

  # Hand off to coding agent(s)
  for task in plan["tasks"]:
      subprocess.run([
          "claude", "-p", task["prompt"],
          "--allowedTools", "Edit,Read,Bash"
      ])

  subprocess.run(["git", "push", "origin", branch])
  subprocess.run([
      "gh", "pr", "create",
      "--title", plan["pr_title"],
      "--body", plan["pr_body"],
  ])

Linking Requirements to Code

The traceability chain is only valuable if links are maintained. Use commit message conventions:

feat(checkout): add discount code field

Implements requirement change from commit abc123f:
  docs/domain/entities/order.yaml - added discount_code field
  docs/requirements/business-rules/pricing-rules.yaml - added PRICE-004

Refs: req#abc123f

This allows git log --grep="req#abc123f" to find every code change driven by a specific requirement change.

Addressing the Objections

“Non-technical people won’t use Git.” They don’t have to use the CLI. Web-based editors, VS Code with GitLens, or a Markdown editor with Git sync all work. Most stakeholders care about reading requirements, not editing them — and rendered Markdown on any Git hosting platform looks clean. For editors, a guided template lowers the barrier significantly.

“Requirements are too complex for plain text.” If a requirement cannot be expressed in structured text, it is probably too ambiguous to implement. Forcing requirements into parseable formats surfaces ambiguity that hides in prose. Markdown supports images, Mermaid renders diagrams — the 95% case works perfectly in plain text.

Inspiration

This article was inspired by ideas from two other pieces on this site:

  • Coding Agent Swarms — the idea of multiple agents working on implementation tasks raised the question: what if the input to those agents was structured and version-controlled?
  • Git-Based Memory for AI Agents — using Git as a persistent memory layer for agents suggested that Git could serve as a broader interface between human intent and agent action, not just for memory but for requirements too.
Tags: architectureautomationgitopsrequirementscoding-agents