Neo from The Matrix announces downloading a new skill: 'I know kung fu!'

I build alternate versions of my developer documentation, specially for consumption by LLM-backed coding agents.

These documents begin life as AsciiDoc files oriented toward human users, but I selectively transclude content into AI-specific documentation files. Then the files are converted to Markdown (via HTML) for better compatibility with LLMs.

I then use a tool that lets me sync those agent-oriented docs from a central source into all my code repositories. This way any LLM agents have ready access to a library of specific skills or protocols they may be called upon to use, without overwhelming them with entire sets of remote, HTML-laden documents in every session.

If this sounds convoluted, hear me out.

Source Content

The source content for my AI-agent-oriented docs lives in the same AsciiDoc files I use for human developer documentation.

In my experience, LLMs are more adept at consuming examples and bulleted lists, and they prefer these in Markdown format with some HTML tags.

However, complex tech docs are best authored in a structured format like AsciiDoc, reStructuredText, DITA, or MadCap Flare. For me, this means authoring in AsciiDoc, converting to HTML, and then reverting to Markdown.

Why not just write the AI docs in Markdown?

If all your docs are already sourced in pure Markdown of one flavor or another, you have a head start in this process. You can basically just show the source files to your LLM agent…​ so long as your docs do not need to be assembled.

But for structured authoring with strict single sourcing and transclusion, source files are incomplete until they are rendered to another format.

Assuming you wish to source your AI-agent docs along with people docs, you will probably want to render each document, and you further want to slim down your docs.

Most advanced static-site generators (SSGs) and doc generators can render complex docs from Markdown-like sources, but conditional transclusion usually requires mixing in preprocessor templates. Whereas formats like AsciiDoc, reStructuredText, DITA, and Flare support this feature natively.

And because we love AsciiDoc at DocOps Lab, we’re usually going to find a way to avoid actually having to author in (or even read) Markdown.

Assuming you want to selectively include content for AI agents, use AsciiDoc tagging to indicate sections or blocks to include or exclude.

For example, my original, people-focused documentation on how to interact with Git does not assume much prior knowledge of Git commands. Whereas LLMs definitely know how to use Git; they are basically experts. So all I need to convey is the specific procedures preferred for DocOps Lab projects.

Here is how I tag the relevant content in my AsciiDoc source files:

Original AsciiDoc source snippet
// tag::repo-state[]
[[repo-state]]
== Repository State

Development is done on development _trunk_ branches named like `dev/x.y`, where `x` is the major version and `y` is the minor.

To start development on a new release version:

....
git checkout main
git pull origin main
git checkout -b dev/1.2
git checkout -b chore/bump-version-1.2.0
git commit -am "Bumped version attributes in README"
git checkout dev/1.2
git merge chore/bump-version-1.2.0
git push -u origin dev/1.2
....
// end::repo-state[]

From there it is just a matter of creating a set of AsciiDoc files that use the include:: directive to pull in the tagged content. This way I can skip verbose introductory or beginner-oriented content that is unnecessary for LLMs.

Using include directive to embed single-sourced content
[[basics]]
== The Basics

. Follow proper branching procedures as outlined in <<repo-state>>.

. Commit messages should be concise and easy for users to edit. +
See <<commit-messages>> for guidance.

. Always prompt user to approve commits before pushing.

. Use `gh` for interacting with GitHub whenever possible. +
See <<gh-cli>> for more information.

include::../task/development.adoc[tag=repo-state]

Generating AI-Agent Docs

The best way to get Markdown from AsciiDoc files is to perform an HTML conversion and then downgrade to Markdown.

There are numerous tools for carrying this latter step, not the least of them the beloved Pandoc. I have modified a Ruby library called ReverseMarkdown to accommodate AsciiDoc’s richer semantics. My extension is available as scripts/mark_down_grade.rb in this very repo.

Here I include a window into the current state of one such document (source, rendered), which may change over time as I refine the AI-agent docs:

# AI Agent Instructions for Git Operations

This document is intended for AI agents operating within a DocOps Lab environment.

You are an AI agent that helps with git operations.

This document describes protocols for committing and pushing changes to a git DocOps Lab Git repository and interacting with GitHub on behalf of a DocOps Lab contributor.

Table of Contents

- The Basics
- Repository State
- Development Procedures
- Commit Message Conventions
      - Merging Changes
- Dev Branch Rules
- Commit Messages
- General Style (Conventional Commits)
      - Commit Description
      - Commit Types
      - Commit Body Conventions
- Use `gh` the GitHub CLI Tool

## The Basics

1. Follow proper branching procedures as outlined in Repository State.
2. Commit messages should be concise and easy for users to edit.  
See Commit Messages for guidance.
3. Always prompt user to approve commits before pushing.
4. Use `gh` for interacting with GitHub whenever possible.  
See Use `gh` the GitHub CLI Tool for more information.

## Repository State

Development is done on development _trunk_ branches named like `dev/x.y`, where `x` is the major version and `y` is the minor.

To start development on a new release version:

```
git checkout main
git pull origin main
git checkout -b dev/1.2
git checkout -b chore/bump-version-1.2.0
git commit -am "Bumped version attributes in README"
git checkout dev/1.2
git merge chore/bump-version-1.2.0
git push -u origin dev/1.2
```

## Development Procedures

Work on feature or fix branches off the corresponding `dev/x.y` trunk.

```
git checkout dev/1.2
git checkout -b feat/add-widget
… implement …
git add .
git commit -m "feat: add widget"
git push -u origin feat/add-widget
gh pr create --base dev/1.2 --title "feat: add widget" --body "Adds a new widget to the dashboard."
```

**Branch naming conventions** :
   - `feat/…​` for new features OR improvements
   - `fix/…​` for bugfixes
   - `chore/…​` for version bumps and sundry tasks with no product impact
   - `epic/…​` for large features or changes that span releases

### Commit Message Conventions

**Description (first line) conventions**:
   - Use present-tense descriptive verbs (“adds widget”, not “added” or “add”)
   - `feat: …​` for new features OR improvements
   - `fix: …​` for bugfixes
   - `chore: …​` for version bumps and sundry tasks with no product impact
   - `docs: …​` for documentation changes
   - `test: …​` for test code changes
   - `refactor: …​` for code restructuring with no functional changes
   - `style: …​` for formatting, missing semi-colons, etc; no functional changes
   - `perf: …​` for performance improvements
   - `auto: …​` for changes to CI/CD pipelines and build system

**Body conventions** :
   - Use the body to explain what and why vs. how.
   - Reference issues and pull requests as needed.
   - Use bullet points (`- text`) and paragraphs as needed for clarity.
   - Do not hard-wrap lines, but _do_:

      - use 1-sentence per line
      - keep sentences short

### Merging Changes

Squash-merge branches back into `dev/x.y`:

```
git checkout dev/1.2
git checkout -b feat/add-widget
… implement …
git add .
git commit -m "feat: add widget"
git merge --squash feat/add-widget
git commit -m "feat: add widget"
git push origin dev/1.2
```

Delete merged branches.

## Dev Branch Rules

- Always branch from `dev/x.y`.
- Always squash-merge into `dev/x.y`.
- Never merge directly into `main`.

## Commit Messages

This document outlines the protocols for authoring Git commit messages in DocOps Lab projects.

### General Style (Conventional Commits)

DocOps Lab _loosely_ follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification for Git commit messages.

Enforcement is not strict, but using Conventional Commits style is encouraged for consistency and clarity.

> **NOTE:** Most DocOps Lab projects do not base Changelog/Release Notes generation on commit messages.

The basic outline for a Conventional Commit message is:

```
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
```

### Commit Description

The commit description should be concise and to the point, summarizing the change in 50 characters or less.

Use the _past tense_ rather than imperative mood (e.g., "Added feature X" instead of "Add feature X").

### Commit Types

- Use present-tense descriptive verbs (“adds widget”, not “added” or “add”)
- `feat: …​` for new features OR improvements
- `fix: …​` for bugfixes
- `chore: …​` for version bumps and sundry tasks with no product impact
- `docs: …​` for documentation changes
- `test: …​` for test code changes
- `refactor: …​` for code restructuring with no functional changes
- `style: …​` for formatting, missing semi-colons, etc; no functional changes
- `perf: …​` for performance improvements
- `auto: …​` for changes to CI/CD pipelines and build system

### Commit Body Conventions

- Use the body to explain what and why vs. how.
- Reference issues and pull requests as needed.
- Use bullet points (`- text`) and paragraphs as needed for clarity.
- Do not hard-wrap lines, but _do_:

   - use 1-sentence per line
   - keep sentences short

## Use `gh` the GitHub CLI Tool

For interacting with GitHub, always prefer using the [GitHub CLI (`gh`)](https://cli.github.com/) tool for issues, PRs, and other GH operations.

I am quite happy with the twice-converted Markdown output. Having spent a decade publishing AsciiDoc to HTML and PDF, this experience of publishing to Markdown has been fun.

Distribution

This is the extra-credit section of the blog entry. It only pertains to organizations or projects that maintain multiple repos or authors who need to lint textual content across multiple projects with a single voice.

This matter of AI-oriented docs came about as a side effect of my need to centrally maintain a series of helper utilities like code and text linters backed by customizable libraries.

In order to make sure all of my many concurrent projects have access to the latest customizations and configurations of the tools they all depend on, I built a common dependency across all my repos, just for managing these shared assets.

The specifics of this tool are not all that important; I will leave them for a separate post. The trick is to use whatever resources are available to you to ensure your docs and helper tooling are consistent across your team and accessible to all AI agents.

Once you have a library of topical documents for your AI agents to use, make sure they are aware of them by indicating their location in your project’s AGENTS.md or CLAUDE.md file.