Skip to content

AGENTS md

alf edited this page May 1, 2026 · 2 revisions

AGENTS.md -- Project Instructions

Overview

FreeCAD AI can load project-specific instructions from an AGENTS.md (or FREECAD_AI.md) file and inject them into the LLM system prompt. This lets you define design conventions, material specs, naming rules, or any other guidance that applies to a particular project without repeating yourself every chat session.

The feature supports multi-location search, include directives for splitting instructions across files, and live variable substitution with document-level values.

Source: /freecad_ai/extensions/agents_md.py

Search Order

When FreeCAD AI builds the system prompt (in build_system_prompt() inside core/system_prompt.py), it calls load_agents_md() which searches for instruction files in this order:

  1. Active document's directory -- the folder containing the currently open .FCStd file
  2. Parent directories -- up to 3 levels above the document directory
  3. User config directory -- <FreeCADAI dir>/AGENTS.md

The first file found wins. If neither AGENTS.md nor FREECAD_AI.md exists at any of these locations, no project instructions are included.

Priority

At each directory level, the loader checks filenames in this order:

  1. AGENTS.md
  2. FREECAD_AI.md

If both files exist in the same directory, AGENTS.md takes priority. The constants controlling this are defined in the source:

INSTRUCTION_FILENAMES = ["AGENTS.md", "FREECAD_AI.md"]
MAX_PARENT_LEVELS = 3

Unsaved Documents

If the active document has never been saved (no FileName), the document directory search is skipped entirely and only the user config fallback is checked. This is handled in _get_document_directory():

def _get_document_directory() -> str:
    try:
        import FreeCAD as App
        doc = App.ActiveDocument
        if doc and doc.FileName:
            return os.path.dirname(doc.FileName)
    except ImportError:
        pass
    return ""

Include Directives

You can split instructions across multiple files using include directives:

<!-- include: materials.md -->
<!-- include: conventions.md -->
<!-- include: ../shared/company-standards.md -->

How Includes Work

  • The include path is resolved relative to the directory containing the file with the directive (not relative to the document or working directory).
  • Includes are processed recursively: an included file can itself contain <!-- include: ... --> directives.
  • Maximum nesting depth is 5 levels to prevent infinite recursion.
  • If a referenced file does not exist, a comment is inserted:
    <!-- include not found: filename.md -->
  • If reading fails (permissions, encoding), a different comment appears:
    <!-- include failed: filename.md -->

The regex pattern that matches include directives is:

INCLUDE_RE = re.compile(r"<!--\s*include:\s*(.+?)\s*-->")

This means whitespace around include: and the filename is flexible. All of these are equivalent:

<!-- include: materials.md -->
<!--include:materials.md-->
<!--  include:  materials.md  -->

Variable Substitution

Instruction files can reference live document values using {{variable_name}} placeholders. These are replaced at load time with current values from the active FreeCAD document.

Available Variables

Variable Description Example Value
{{document_name}} Internal name of the active document Enclosure
{{document_path}} Full file path, or (unsaved) /home/user/project/Enclosure.FCStd
{{object_count}} Number of objects in the document 12
{{active_body}} Label of the active PartDesign Body EnclosureBase

Behavior

  • Variables are replaced after include directives are resolved, so included files can also use variables.
  • Unknown variables are preserved as-is -- {{unknown_var}} remains literally {{unknown_var}} in the prompt.
  • If no document is open, all variables resolve to empty strings (or "0" for object_count).

The substitution regex is:

VARIABLE_RE = re.compile(r"\{\{(\w+)\}\}")

Only \w+ (letters, digits, underscore) characters are matched inside the braces.

Complete Example

Here is a full example AGENTS.md file for an electronics enclosure project:

# Project: {{document_name}}

## Design Conventions
- All dimensions in millimeters
- Wall thickness: 2.0mm minimum
- Fillet radius on exterior edges: 1.5mm
- Use PartDesign workflow (Body -> Sketch -> Pad/Pocket) for all features
- Label bodies descriptively: "EnclosureBase", "EnclosureLid"

## Material
- ABS plastic (injection molding target)
- Draft angle: 1 degree on vertical walls
- Minimum feature size: 0.8mm

## Hardware
<!-- include: hardware-specs.md -->

## PCB Mounting
- PCB dimensions: 80mm x 50mm
- Mounting holes: M3, 4 corners, 3mm from edges
- Standoff height: 5mm

## Shared Standards
<!-- include: ../company/naming-conventions.md -->
<!-- include: ../company/tolerance-rules.md -->

## Status
Document path: {{document_path}}
Objects so far: {{object_count}}
Active body: {{active_body}}

Processing Pipeline

The full processing order when load_agents_md() is called:

  1. Search -- find the first matching file in the directory chain or user config
  2. Load -- read the raw file content
  3. Resolve includes -- recursively expand <!-- include: ... --> directives (up to 5 levels deep)
  4. Substitute variables -- replace {{variable}} placeholders with live values
  5. Inject -- the processed text is appended to the system prompt under the heading ## Project Instructions (from AGENTS.md)

Best Practices

  • Keep instructions focused and specific. The entire AGENTS.md content is included in every LLM request, so long files increase token usage.
  • Use includes for shared standards. If multiple projects share the same material specs or naming conventions, put those in separate files and include them.
  • Put general defaults in the user config. Place <FreeCADAI dir>/AGENTS.md with defaults that apply to all your projects.
  • Put project-specific instructions next to your .FCStd file. This ensures the instructions travel with the project if you move or share it.
  • Leverage parent directory search. For a workspace with multiple related FreeCAD files, put a shared AGENTS.md one level up and project-specific overrides in each subdirectory.
  • Use variables for dynamic context. {{object_count}} and {{active_body}} help the LLM understand the current state without you describing it manually.

Clone this wiki locally