Spring AI / LangChain4J Skill
Detect the framework in use, then apply the correct patterns.
Step 1 — Detect framework and version
Check pom.xml or build.gradle:
spring-ai-*dependency → Spring AI (note version: 1.0.x GA or 0.8.x milestone)langchain4j-*dependency → LangChain4J (note version: 0.x or 1.x)- Neither present → offer to add one (recommend Spring AI for Spring Boot 3.x, LangChain4J for Boot 2.x)
Check Spring Boot version:
- Boot 3.x → Spring AI 1.x preferred, LangChain4J 0.35+
- Boot 2.x → LangChain4J 0.30.x (Spring AI requires Boot 3.x)
Mode: review
User asks to review existing AI code. Check for:
Spring AI:
-
ChatClientbuilt viaChatClient.Builder(not rawChatModel) for fluent API - Prompt templates use
PromptTemplatewith variables — no string concatenation - Streaming uses
stream().content()orFlux<String>— not blocking.call()for real-time responses -
@Retryableor Spring AI retry config on ChatClient calls — LLMs are flaky - Secrets (
spring.ai.openai.api-key) come from env vars or Vault, never hardcoded -
VectorStorequeries useSearchRequest.query(text).withTopK(n)— not raw SQL - RAG advisor (
QuestionAnswerAdvisor) attached to ChatClient — not manual context injection - Token usage logged at DEBUG, not INFO (avoid log noise)
LangChain4J:
- AI services use
@AiServiceinterface — notChatLanguageModel.generate()directly - System prompts in
@SystemMessageannotation — not hardcoded strings - Memory uses
MessageWindowChatMemoryorTokenWindowChatMemory— not unlimited history - Streaming via
StreamingChatLanguageModelwithTokenStream— not blocking - Embeddings via
EmbeddingModel+EmbeddingStorefor RAG — not in-memory list search - Tools annotated with
@Toolon service methods — not manual function dispatch - API key from
@Value("${langchain4j.openai.api-key}")— never literal
Mode: chat
User asks to add a basic chatbot or chat endpoint.
Spring AI
- Add dependency (see
references/patterns.md→ Spring AI Setup) - Inject
ChatClient.Builder, build aChatClientbean - Create
ChatControllerwith@PostMapping("/chat") - Use
chatClient.prompt().user(message).call().content()for simple response - For streaming: return
Flux<String>withchatClient.prompt().user(message).stream().content() - Add
ANTHROPIC_API_KEY/OPENAI_API_KEYtoapplication.ymlvia${env-var}
LangChain4J
- Add
langchain4j-spring-boot-starter+ provider dependency - Define
@AiServiceinterface with@SystemMessage - Register as Spring bean via
AiServices.builder(MyAssistant.class).chatLanguageModel(model).build() - Expose via
@RestController
Mode: rag
User asks to implement RAG (chat over documents, knowledge base, semantic search).
Spring AI RAG
- Choose vector store: PgVector (PostgreSQL), Chroma, Redis, Weaviate, Qdrant (see
references/patterns.md) - Add
spring-ai-{store}-store-spring-boot-starter - Ingest pipeline:
DocumentReader(PDF, text, web) →TokenTextSplitter→VectorStore.add()- Run at startup via
ApplicationRunneror dedicated@PostMapping("/ingest")
- Query pipeline:
- Attach
QuestionAnswerAdvisor(vectorStore)toChatClient - Spring AI auto-retrieves context and injects into prompt
- Attach
- Tune:
SearchRequest.withTopK(5).withSimilarityThreshold(0.7)
LangChain4J RAG
- Add
EmbeddingStore(Chroma, Qdrant, in-memory for dev) EmbeddingStoreIngestorwithDocumentSplitterandEmbeddingModelEmbeddingStoreContentRetriever→RetrievalAugmentor→AiServicesbuilder
Mode: tools
User asks to give the AI the ability to call Java methods (function/tool calling).
Spring AI
- Define a
@Beanof typeFunction<Input, Output>— Spring AI auto-registers it - Or use
@Descriptionon arecordparameter for rich schema - Pass function names to
ChatClient:.options(OpenAiChatOptions.builder().withFunction("myFunction").build()) - Spring AI handles the tool call loop automatically
LangChain4J
- Annotate service methods with
@Tool("description of what this tool does") - Register the service as a tool:
AiServices.builder(...).tools(myToolService).build() - The model decides when to call — no manual dispatch needed
Mode: memory
User asks to add conversation memory / chat history.
Spring AI
MessageChatMemoryAdvisorwithInMemoryChatMemoryfor single-instance appsJdbcChatMemoryfor persistent / multi-instance memory (requiresspring-ai-jdbcstore)- Key: pass
conversationId(e.g., session ID or user ID) to scope memory per user
LangChain4J
MessageWindowChatMemory.withMaxMessages(20)— keeps last N messagesTokenWindowChatMemory— keeps messages within token budget- For persistence: implement
ChatMemoryStorebacked by Redis or JDBC
Output format
For review mode: list findings as [CRITICAL] / [HIGH] / [MEDIUM] / [LOW] with file:line references.
For implementation modes (chat, rag, tools, memory):
- Show exact Maven/Gradle dependencies with versions
- Show full working code snippets (not pseudocode)
- Show
application.ymlconfiguration - Note: state the minimum Spring Boot and Java version required
Always note version-specific differences:
- Spring AI 1.0.x (GA) vs 0.8.x (milestone) — API changes between these
- LangChain4J 1.x vs 0.x —
AiServicesAPI changed in 1.x - Spring Boot 3.x required for Spring AI; Boot 2.x → use LangChain4J