Skip to content

Repository files navigation

Spring AI AGENTS.md

CI License Java Spring Boot Spring AI

Spring Boot auto-configuration for bringing instructions from AGENTS.md into Spring AI ChatClient requests.

AGENTS.md is a simple, open format for guiding coding agents. It is stewarded by the Agentic AI Foundation (AAIF) under the Linux Foundation.

Important

This project is under active development and has not published a release to Maven Central. Its APIs may change before the first stable release.

Overview

An AGENTS.md file gives an agent a predictable place to find repository-specific context and instructions. This project resolves applicable documents relative to the request's target file, preserves their Markdown without imposing a schema, and adds them to the chat request's system message through a Spring AI advisor.

The integration is model-provider neutral and uses Spring AI's ChatClient advisor API.

Specification Alignment

The AGENTS.md format is standard Markdown:

  • It has no required fields or headings.
  • Authors may organize instructions with any headings that fit their project.
  • Instructions can cover build steps, tests, code style, pull-request expectations, or any other information useful to an agent.
  • In a repository hierarchy, the closest AGENTS.md to the file being changed takes precedence, while explicit user instructions override file-based instructions.

The library does not assign special meaning to heading names or rewrite the document into a project-specific schema. Each complete Markdown document is preserved unchanged inside a small framework-owned context envelope that declares user and hierarchical precedence. The injected block is delimited by <!-- spring-ai-agents-md:start --> and <!-- spring-ai-agents-md:end --> HTML comments so the advisor can replace it reliably when the active target changes, even when other advisors append to the system message.

Current Functionality

  • Resolve filesystem AGENTS.md documents relative to a request target path.
  • Walk toward the repository root and order applicable documents broadest-to-closest.
  • Fall back to a classpath document when no filesystem document applies.
  • Allow Spring AI filesystem tools to propagate their active path through ToolContext.
  • Read an AGENTS.md from a String, InputStream, or Spring Resource as UTF-8.
  • Preserve headings, prose, lists, tables, code blocks, whitespace, and line endings.
  • Represent the complete document with an immutable Java 17 record.
  • Provide an AgentsMdSystemAdvisor for Spring AI 2.x synchronous and streaming ChatClient calls.
  • Build advisors with a fluent builder or a single-document factory.
  • Automatically attach the advisor to Spring AI's auto-configured ChatClient.Builder.
  • Auto-configure the reader, document, advisor, builder customizer, and configuration properties.
  • Optionally cache resolved documents with a configurable TTL.
  • Use JSpecify nullness annotations with non-null defaults across the public API.
  • Use Jackson 3 through Spring Boot 4.1 dependency management.

Requirements

Technology Supported version
Java 17 or later
Spring Boot 4.1.x
Spring AI 2.x
Maven Maven Wrapper included

Spring Boot 3.x is not a supported target for this project.

Getting Started

Build the Snapshot Locally

Until artifacts are published, clone and install the snapshot with the included Maven Wrapper:

git clone https://github.com/dashaun/spring-ai-agents-md.git
cd spring-ai-agents-md
./mvnw clean install

Add the Dependency

<dependency>
    <groupId>io.github.spring-ai-community</groupId>
    <artifactId>spring-ai-starter-agents-md</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

The starter brings in the focused spring-ai-autoconfigure-agents-md module and the Spring dependencies needed to activate it.

Add AGENTS.md

Place AGENTS.md at the repository root. No property is required. For nested projects, add another AGENTS.md in the subproject; applicable documents are supplied from broadest scope to closest scope, and the closest instructions take precedence when they conflict.

This hierarchical behavior follows the accumulation, directory jurisdiction, and closest-scope precedence semantics described by the proposed AGENTS.md v1.1 clarification. The clarification is currently a proposal rather than part of the adopted specification. Instructions in sibling directories do not apply, and discovery does not traverse above the repository boundary. When no repository boundary is present, discovery is confined to the configured working directory.

If no filesystem document applies, the starter uses classpath:AGENTS.md as a fallback.

AGENTS.md accepts ordinary Markdown and does not require particular sections. For example:

# Sample AGENTS.md

## Dev environment tips

- Use Java 17 or later.
- Use the Maven Wrapper instead of a system Maven installation.

## Testing instructions

- Run `./mvnw clean test` before submitting changes.
- Add or update tests for changed behavior.

## PR instructions

- Keep pull requests focused.
- Sign every commit.

Build a ChatClient

The starter automatically attaches AgentsMdSystemAdvisor to Spring AI's auto-configured ChatClient.Builder. Build the client normally; no advisor registration is required:

@Configuration
class AiConfiguration {

    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder.build();
    }

}

To create the advisor programmatically instead of relying on auto-configuration, use the fluent builder or the single-document factory:

AgentsMdSystemAdvisor advisor = AgentsMdSystemAdvisor.builder()
    .resolver(resolver)
    .targetPathResolver(targetPathResolver)
    .observationRegistry(observationRegistry)
    .build();

AgentsMdSystemAdvisor single = AgentsMdSystemAdvisor.of(new AgentsMdDocument(markdown));

Application code can then use the normal Spring AI API:

@Service
class AssistantService {

    private final ChatClient chatClient;

    AssistantService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    String ask(String request) {
        return this.chatClient.prompt()
            .user(request)
            .call()
            .content();
    }

}

When the target is known before a request, provide it explicitly:

chatClient.prompt()
    .advisors(AgentsMdAdvisorParams.target(
        Path.of("src/main/java/com/example/Example.java")))
    .user(request)
    .call();

Filesystem tools can propagate the path they accessed for subsequent resolution:

@Tool
String readFile(String path, ToolContext toolContext) {
    Path target = Path.of(path);
    AgentsMdAdvisorParams.propagateActivePath(toolContext, target);
    return Files.readString(target);
}

An explicit request target takes priority over a tool-propagated path. If neither is present, the starter resolves from the JVM working directory.

Tool-propagated state belongs to the ChatClient built from that builder. The active path is shared mutable state across every request on that ChatClient; it is designed for sequential tool loops, not for concurrent or cross-thread requests. Applications issuing concurrent requests for different workspaces must pass an explicit target on each request instead of relying on mutable active-path state:

chatClient.prompt()
    .advisors(AgentsMdAdvisorParams.target(Path.of("workspace-a/src/Example.java")))
    .user(request)
    .call();

When the active path is accessed from a different thread than the previous access, the starter logs a warning once so the misuse is visible instead of silent. The warning is informational; it does not change resolution behavior.

Each advisor invocation resolves one active target. For operations spanning unrelated subtrees, filesystem tools should propagate the path for each operation, or the caller should issue separate requests with an explicit target for each subtree. The starter does not merge instructions from unrelated target paths into one request.

Configuration

Property Default Description
spring.ai.agents-md.enabled true Enables AGENTS.md auto-configuration.
spring.ai.agents-md.location unset Explicit Spring resource that replaces target-aware discovery completely.
spring.ai.agents-md.fallback-location classpath:AGENTS.md Fallback consulted only when no filesystem document applies.
spring.ai.agents-md.inject-into-system-prompt true Creates and automatically attaches the AgentsMdSystemAdvisor.
spring.ai.agents-md.max-depth 32 Maximum number of directories inspected from the active target toward its boundary.
spring.ai.agents-md.max-documents 16 Maximum number of documents composed for one target.
spring.ai.agents-md.max-document-size 64KB Maximum UTF-8 byte size of one document.
spring.ai.agents-md.max-total-size 256KB Maximum UTF-8 byte size of the composed prompt context, including hierarchy headings.
spring.ai.agents-md.cache-ttl 0 TTL for cached resolution results; 0 disables caching and keeps live reload.

If neither an applicable filesystem document nor the fallback resource exists, prompt augmentation is a no-op.

Setting spring.ai.agents-md.location disables filesystem traversal and classpath fallback selection. The configured resource must exist and be readable.

Safety limits apply to filesystem documents, the classpath fallback, and an explicitly configured location. Oversized documents are skipped whole rather than truncated. Once the aggregate or document-count limit is reached, composition stops while preserving the broadest-to-closest order of accepted documents. Invalid non-positive limits fail during configuration binding.

Live Reload

By default, resolution happens for every Advisor invocation without caching document content. Changes to filesystem AGENTS.md files therefore apply to the next request or tool-loop pass; no application restart or file watcher is required. When a filesystem tool propagates a new active path, the advisor replaces its previously injected context with the newly applicable documents.

For high-throughput deployments, set spring.ai.agents-md.cache-ttl to a positive duration (for example 5s) to cache each resolved target for that period. Caching trades live-reload immediacy for reduced filesystem I/O: changes to AGENTS.md files are picked up only after the TTL expires. The cache is bounded and thread-safe; a zero TTL (the default) disables it entirely.

Automatic attachment applies to Spring AI's auto-configured ChatClient.Builder. Clients created directly with ChatClient.builder(chatModel) or ChatClient.create(chatModel) bypass Spring Boot builder customizers and observability.

Logging and Observability

The library uses SLF4J and Spring Boot's standard logging configuration. Document loading is logged at DEBUG under:

org.springframework.ai.autoconfigure.agents

Debug messages include only the selected resource location and character count. The contents of AGENTS.md are never written to logs.

When an ObservationRegistry is available, the advisor emits this Micrometer observation around prompt augmentation:

Observation Low-cardinality key Values
spring.ai.agents.md.advisor spring.ai.agents.md.document.state present, empty
spring.ai.agents.md.advisor spring.ai.agents.md.document.count zero, one, multiple
spring.ai.agents.md.advisor spring.ai.agents.md.resolution.outcome complete, depth-limit, document-limit, size-limit

When a MeterRegistry is available, the spring.ai.agents.md.context.size distribution summary records the number of characters added to the system prompt. It exposes aggregate count, total, and maximum values without using context size or resource paths as tags.

When a safety limit is reached, the advisor also publishes one AgentsMdLimitReachedEvent for that resolution. Interactive applications can listen for the event and render an immediate warning without coupling the starter to a particular terminal or user interface:

@EventListener
void warnAboutAgentsMdLimit(AgentsMdLimitReachedEvent event) {
    System.err.printf(
        "AGENTS.md %s reached for %s; %d documents were applied.%n",
        event.outcome(), event.target(), event.acceptedDocumentCount());
}

The event contains the normalized target, resolution outcome, accepted document count, injected UTF-8 context size, and configured limit. It never contains document contents. Spring application events are synchronous by default, so listeners should return quickly and must not throw exceptions. CLI listeners can rate-limit repeated notifications from tool loops if needed.

The contextual name is agents-md advisor. The observation covers only the local prompt augmentation step; it does not wrap the downstream model call or duplicate Spring AI's model observations. No document contents or resource paths are added as observation tags. If no registry is configured, instrumentation uses Micrometer's no-op registry.

Building and Testing

Use the Maven Wrapper from the repository root:

Project Structure

spring-ai-agents-md/
├── examples/
│   ├── spring-ai-agents-md-example/          # Runnable Ollama web application
│   └── spring-ai-agents-md-coding-agent/     # Spring Shell repository steward
├── spring-ai-autoconfigure-agents-md/  # Auto-configuration, public API, and tests
├── spring-ai-starter-agents-md/        # Dependency-only starter for applications
└── pom.xml                             # Parent and reactor build
Task Command
Compile ./mvnw clean compile
Run all tests ./mvnw clean test
Run document reader tests ./mvnw -pl spring-ai-autoconfigure-agents-md test -Dtest=AgentsMdReaderTests
Apply formatting ./mvnw spring-javaformat:apply
Analyze dependencies ./mvnw dependency:analyze

Spring Java Format validation runs during Maven's validate phase. JaCoCo runs during verify and requires at least 85% line coverage independently for the reader, advisor, and discovery packages.

Example Applications

The repository steward is the Phase 2 foundation for an AGENTS.md-aware coding agent built with Spring AI and Spring Shell 4.0.3. It explicitly includes Spring Shell's JLine module for the richer interactive experience. Bounded filesystem tools let the agent inspect a repository and create reviewable change proposals; only explicit shell commands can apply or discard them.

The Ollama example is a real Spring Boot application that depends on the starter through its public API. It demonstrates advisor registration, a /chat endpoint, Actuator metrics, and zero-configuration filesystem discovery of its project-level AGENTS.md.

Its normal test replaces the model with a mock. Pull-request CI uses a pinned WireMock Testcontainer to validate the real Ollama HTTP request deterministically, including the injected system message. A separate opt-in integration profile uses the pinned pre-warmed ghcr.io/dashaun/testcontainer-ollama-smollm2-135m:0.33.2 image from dashaun/testcontainer-ollama-images. See the example README for launch commands, architecture requirements, and the real-model integration test.

Contributing

Contributions are welcome. Read CONTRIBUTING.md before opening a pull request and follow the Spring AI Community Code of Conduct.

Before submitting changes:

./mvnw spring-javaformat:apply
./mvnw clean test

All commits must be signed. The main branch requires pull requests, a passing build, and linear history.

Security

Report suspected vulnerabilities privately as described in SECURITY.md. Do not disclose security issues in a public GitHub issue.

License

Spring AI AGENTS.md is available under the Apache License 2.0.

Links

About

Spring Boot support for AGENTS.md in Spring AI applications

Topics

Resources

Contributing

Security policy

Stars

19 stars

Watchers

1 watching

Forks

Contributors

Languages