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.
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.
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.mdto 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.
- Resolve filesystem
AGENTS.mddocuments 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.mdfrom aString,InputStream, or SpringResourceas 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
AgentsMdSystemAdvisorfor Spring AI 2.x synchronous and streamingChatClientcalls. - 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.
| 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.
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<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.
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.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.
| 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.
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.
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.
Use the Maven Wrapper from the repository root:
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.
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.
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 testAll commits must be signed. The main branch requires pull requests, a passing build,
and linear history.
Report suspected vulnerabilities privately as described in SECURITY.md. Do not disclose security issues in a public GitHub issue.
Spring AI AGENTS.md is available under the Apache License 2.0.