--- name: langchain4j-scaffold description: "Use when generating LangChain4j Java/Kotlin implementation code (AI services, tools, guardrails, memory, MCP client/server wiring, Spring integration). Do not invoke for architecture-only planning (use langchain4j-agent-design), code review (use langchain4j-review/langchain4j-mcp-client), or MCP server implementation-path selection/review (use langchain4j-mcp-server)." allowed-tools: Read, Grep, Glob, Write, Edit, Bash(find * -name "*.java" -o -name "*.kt") --- # LangChain4j Code Scaffold > **Version baseline**: LangChain4j 1.18.1 / 1.18.1-beta28, Spring Boot 3.5+ / 4.0.5+, Java 17+ Generate production-quality, compilable LangChain4j code for the specified component. ## Step 1 — Understand the project Read existing code to match conventions (language, package names, model provider, Spring version): ``` !`find . \( -name "pom.xml" -o -name "build.gradle.kts" \) | head -3` !`find . \( -name "*.java" -o -name "*.kt" \) -path "*ai*" -o -path "*agent*" -o -path "*tool*" 2>/dev/null | head -15 || echo "no existing AI code"` !`find . -name "application.yml" -o -name "application.properties" 2>/dev/null | head -3` ``` ## Step 2 — Identify the component type from `$ARGUMENTS` | Component | Trigger words | What to generate | |-----------|--------------|-----------------| | **AI Service** | "ai service", "assistant", "chat interface", "bot" | `@AiService` interface + Spring config | | **Tool class** | "tool", "function calling", "tool bean" | `@Component` with `@Tool` methods | | **MCP client** | "mcp client", "connect to mcp", "mcp tools" | Transport + `DefaultMcpClient` + `McpToolProvider` | | **MCP server** | "mcp server", "expose as mcp", "stdio server" | `langchain4j-community-mcp-server` fat JAR — see [reference.md](reference.md) §4; for choosing between stdio/CDI-MCP/Quarkus, see `langchain4j-mcp-server` | | **Guardrail** | "guardrail", "input validation", "output validation", "safety" | `InputGuardrail` or `OutputGuardrail` impl | | **Memory store** | "memory store", "persistent memory", "chat history" | `ChatMemoryStore` + DDL migration | | **Agent listener** | "listener", "observability", "logging", "monitoring" | `AgentListener` or `AiServiceListener` impl | | **Streaming agent** | "stream", "token stream", "real-time", "sse" | Streaming `@AiService` + `TokenStream` handler | | **Agent workflow** | "workflow", "pipeline", "multi-agent", "orchestrat" | Full `AgenticServices` workflow | | **Skill** | "skill", "skill definition", "agent skill", "skill.md" | Tool Mode `SKILL.md` + loader + `Skills.from(...).toolProvider()` | ## Step 3 — Generate the code Apply these rules to every generated file: ### AI Service rules - `@AiService` on interface (Spring auto-creates bean) - `@SystemMessage` on interface or method; use multi-line `"""..."""` for long prompts - `@MemoryId` parameter for session isolation; type it as `String` or `UUID` - Include `ChatMemoryAccess` if session eviction is needed - Use `Result` return type when tool execution visibility is needed - Wire `ChatMemoryProvider` with `TokenWindowChatMemory` (not `MessageWindow`) in production - `wiringMode = EXPLICIT` + `chatModel = "beanName"` when multiple models exist - Include `@InputGuardrails` / `@OutputGuardrails` if the service needs validation ### Tool class rules - `@Component` for Spring-managed tools (auto-discovered by `@AiService`) - Constructor injection — no `@Autowired` on fields - `@Tool` description: precise, LLM-readable, includes "when to use" and "required inputs" - `@P` on every parameter: clear description, include format examples - `required = false` or `Optional` for optional parameters - `@ToolMemoryId` parameter when the tool needs per-user context - Catch all domain exceptions; return a descriptive error string — never let raw exceptions reach the LLM - `ReturnBehavior.IMMEDIATE` for deterministic/calculation tools - `ReturnBehavior.IMMEDIATE_IF_LAST` for deterministic terminal tools that should short-circuit only when no later tool synthesis is needed - Use explicit sealed interfaces/classes or concrete records for polymorphic return types and polymorphic tool parameters ### MCP client rules - Always set `.key("...")` on `DefaultMcpClient` — used in filters and name mappers - Use `.toolNameMapper((client, spec) -> client.key() + "_" + spec.name())` for multiple clients - `.failIfOneServerFails(false)` when using multiple MCP clients - Close clients on shutdown (implement `DisposableBean` or `@PreDestroy`) - Production transport: `StreamableHttpMcpTransport`; local/dev: `StdioMcpTransport` - Docker-based MCP server: `DockerMcpTransport` (requires `langchain4j-mcp-docker:1.18.1-beta28`) - `new DockerMcpTransport.Builder().image("docker.io/mcp/fetch").logEvents(true).build()` - No separate process management needed — LangChain4j handles container lifecycle ### MCP server rules - Stdio server: **configure ALL loggers to write to `System.err`** — never `System.out` - HTTP server: expose via Spring Boot `/mcp` endpoint - Same `@Tool` / `@P` annotations as for AI services - `McpImplementation("server-name", "version")` as server info ### Guardrail rules - `InputGuardrail`: `fatal(reason)` for security violations; `successWith(rewritten)` for PII redaction - `OutputGuardrail`: `reprompt(reason, additionalPrompt)` for format errors; `retry(reason)` for transient LLM failures - Always return `success()` on the happy path - Declare via `@InputGuardrails` / `@OutputGuardrails` with explicit `maxRetries` - Mark as `@Component` for Spring injection if guardrail has dependencies ### Memory store rules - Implement all three methods: `getMessages`, `updateMessages`, `deleteMessages` - Use `ChatMessageSerializer.messagesToJson()` / `ChatMessageDeserializer.messagesFromJson()` - Use `JdbcClient` (Spring Boot 3.2+) for database access — not `JdbcTemplate` - Include Flyway migration SQL for the memory table - `@Transactional` on write methods ### Listener rules - `AgentListener`: set `inheritedBySubagents() = true` for multi-agent systems - `AiServiceCompletedListener` + `AiServiceErrorListener`: use for metrics / audit trails - `ChatModelListener`: use only for low-level request/response logging - `MicrometerMetricsChatModelListener` for token usage metrics (always include) ### Streaming rules - Return `TokenStream` from `@AiService` method (requires `StreamingChatModel` bean) - For Spring WebFlux / SSE: return `Flux` from controller, consume `TokenStream` internally - Document that streaming only propagates from the **last** agent in a sequential workflow ### Workflow rules - Use the simplest builder that fits: `sequenceBuilder` → `parallelBuilder` → `loopBuilder` → `conditionalBuilder` → `supervisorBuilder` - `TypedKey` classes for all `AgenticScope` keys — never raw string keys in production - `AgentMonitor` + `MicrometerMetricsChatModelListener` always included - Provide `errorHandler` on every agent - Include `@Observed` on Spring service methods wrapping the workflow - **Persistent workflows (1.13.0+):** configure a `scopeStore` on `AgenticServices` for durable execution state across restarts/resumes; use `JpaAgenticScopeStore` for JPA, or provide a custom `AgenticScopeStore` impl for Redis or other backends; resume a persisted workflow by retrieving the scope via `agenticServices.getAgenticScope("workflow-id")` and writing state with `scope.writeState("key", value)` - **Runtime context (1.14.0+):** use `AgenticScope.executionContext` for per-run metadata and assemble dynamic subagents as a `Collection` when they come from configuration/plugin discovery ### Skill rules - Treat the `langchain4j-skills:1.18.1-beta28` API as experimental; use Tool Mode by default. - `SKILL.md` requires only YAML `name` and `description`; its remaining body is the activated instruction content. - Load a filesystem catalog with `FileSystemSkillLoader.loadSkills(Path.of("skills"))`, or immutable bundled skills with `ClassPathSkillLoader.loadSkills("skills")`. - Create `Skills skills = Skills.from(loaded)`; pass `skills.toolProvider()` to the AI Service and include `skills.formatAvailableSkills()` in its system message. - Attach local `@Tool` objects or a filtered `McpToolProvider` to individual `Skill` builders when tools must become visible only after activation. - Never scaffold `ShellSkills` for production or untrusted input: it executes unsandboxed host commands. ## Step 4 — Output Generate **complete, compilable files**. Each file must include: 1. Package declaration 2. All necessary imports (no wildcards) 3. Class/interface body with all methods implemented 4. Javadoc/KDoc on public API 5. A Flyway migration SQL (if persistence is involved) 6. An `application.yml` snippet for required configuration After generating, list any manual setup steps (environment variables, Azure portal config, Maven dependencies). For detailed examples and patterns, see [reference.md](reference.md).