quarkus-agentic-scaffolding
AGENTS.md27 starsChanged 4 months agoApache-2.0View on GitHub
These conventions apply whenever Codex or Bob writes, reviews, or configures code in a Quarkus + LangChain4j project. They are always-on. Procedural scaffolding steps and starter code live in the scaffold-project skill and its templates, not here. These tools are prerequisites for this project, not suggestions. Do not work around their absence: if a required tool is unavailable, stop and report it rather than falling back to model memory or a generic web search. - Quarkus Agents MCP - required…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository4 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- audit-projectSkill
- scaffold-projectSkill
- setup-agentic-scaffoldingSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
13 rules. About 0 are common, 0 are distinctive, and 13 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
13
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 34
superpowers skills - optional: When the third-party superpowers plugin is installed, use its skill for a task it fits.
- Very specific: line 78
Import the platform BOMs; do not pin versions they manage: Import quarkus-bom and quarkus-langchain4j-bom at the same platform version and …
- Very specific: line 82
CDI-first: Use quarkus-arc and standard CDI (@ApplicationScoped, @Inject, @Produces) for wiring.
- Very specific: line 85
REST and API surface: Use quarkus-rest (Quarkus REST) with quarkus-rest-jackson for JSON (Jackson is the Quarkus default serializer), and …
- Very specific: line 88
Errors leave the REST edge as RFC 9457 problem details: Add quarkus-http-problem (io.quarkiverse.httpproblem) and every exception escaping …
- Very specific: line 102
Observability comes from platform extensions, not code: Add quarkus-micrometer-registry-prometheus (metrics, scraped at /q/metrics) and …
- Very specific: line 115
Build for both JVM and native: Keep a native Maven profile so the project can produce a GraalVM native binary alongside the JVM build, and …
- Very specific: line 145
Every @RegisterAiService declares modelName, even when the project has a single model: give each role its own named block …
- Very specific: line 171
Reusable instructions ship as skills, not as prompt strings: When behavior would otherwise be pasted into an ever-growing @SystemMessage, …
- Very specific: line 197
Use @QuarkusTest (artifact io.quarkus:quarkus-junit) for integration-style tests and io.rest-assured:rest-assured to exercise HTTP …
- Very specific: line 199
Run native integration tests through maven-failsafe-plugin inside the native profile.
- Very specific: line 200
Keep model interactions deterministic in tests (temperature=0, fixed prompts) or mock the model so tests do not depend on live inference.
- Very specific: line 216
When maintaining eldermoraes/quarkus-agentic-scaffolding itself, apply the tooling requirements per operation as described in …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- BEGIN quarkus-agentic-scaffolding conventions (managed block; do not edit inside. Re-run /setup-agentic-scaffolding to update.) -->Quarkus + LangChain4j + AI Stack - Project Conventions
Version: 0.23.4
These conventions apply whenever Codex or Bob writes, reviews, or configures code in a Quarkus +
LangChain4j project. They are always-on. Procedural scaffolding steps and starter code live in
the scaffold-project skill and its templates, not here.
1. Required tooling (mandatory)
These tools are prerequisites for this project, not suggestions. Do not work around their absence: if a required tool is unavailable, stop and report it rather than falling back to model memory or a generic web search.
- Quarkus Agents MCP - required for every Quarkus task. Project creation, extension selection,
configuration, version checks, API usage, and troubleshooting MUST go through the Quarkus Agents
MCP; never create a Quarkus project, add an extension, or answer a Quarkus question from model
memory by hand. Before any Quarkus task, VERIFY the MCP is reachable - its
quarkus_*tools are present and a cheap call (e.g.quarkus_status) succeeds. If the tools are absent or the call fails, STOP immediately: report exactly what is missing, point the user to/setup-agentic-scaffolding(and to restarting the session after registering it, since MCPs load at session start), and end the turn. A missing or unreachable MCP is never permission to proceed manually - do not fall back to the Quarkus CLI, Maven/Gradle archetypes, model memory, or web search, do not offer to "continue without it", and do not treat the stop as optional. The only exception is/setup-agentic-scaffolding, whose job is to install it. - context7 - required for external library and framework documentation. Look up a library
or framework API (LangChain4j included) with
context7before relying on memory or web search.
Optional tooling - not covered by the stop rule above:
- superpowers skills - optional. When the third-party
superpowersplugin is installed, use its skill for a task it fits. The user installs it by choice, so its absence never blocks work and is not a reason to stop.
2. Java conventions
- Java 25 is the minimum language level, not a ceiling. Compile with
maven.compiler.releaseset to at least 25 and adopt newer language levels freely. Document any project that must pin an older level and explain why (see section 6). One cap applies to native targets: GraalVM ships no releases for JDK 26, 27, or 28, so native-image stays on the JDK 25 baseline (with quarterly updates) until JDK 29 lands (September 2027) - projects that build a native binary keepmaven.compiler.releaseat 25 until then (GraalVM release calendar). - Default to Virtual Threads for I/O-bound and blocking concurrent work. Platform threads
are acceptable only when the runtime or a critical dependency forbids virtual threads (for
example, a JDBC driver that pins the carrier). When a blocking AI or tool call must run inside
a reactive endpoint, run it on a virtual thread rather than on the event loop. Concretely:
every synchronous REST resource method that calls an AI service, a tool, or other blocking
I/O carries
@RunOnVirtualThread(io.smallrye.common.annotation) - Quarkus REST otherwise runs it on a pooled platform worker thread - and so does every@Toolmethod that does I/O; code that fans out by hand usesThread.startVirtualThread(...)or anExecutors.newVirtualThreadPerTaskExecutor(). - Use Scoped Values in place of
ThreadLocalfor request- or agent-scoped identity that must survive virtual-thread continuations, avoiding the leakage and inheritance pitfalls ofThreadLocal. - Structured concurrency for related subtasks. For fan-out across related concurrent
subtasks, prefer declarative parallelism (LangChain4j
@ParallelAgent/@ParallelMapperAgent, see section 4) or explicit virtual-thread fan-out (Thread.startVirtualThread(...)or anExecutors.newVirtualThreadPerTaskExecutor()), instead of ad-hoc executor coordination.StructuredTaskScopeis the preferred structured-concurrency primitive where the project can enable it; note it is a Java preview feature (requires--enable-preview) with GraalVM native-image considerations, so adopt it only when the preview flag and the native target allow. - Prefer records, sealed types, and pattern matching where they clarify intent. Use records
for DTOs and value objects (they also minimize the GraalVM reflection surface), sealed
interfaces for closed hierarchies such as event or result types, and pattern-matching
switchover those hierarchies so the compiler enforces exhaustiveness.
3. Quarkus conventions
- Import the platform BOMs; do not pin versions they manage. Import
quarkus-bomandquarkus-langchain4j-bomat the same platform version and let the BOMs manage every extension and LangChain4j version. No dependency the BOMs manage carries a<version>, including the non-extensiondev.langchain4j:langchain4j-embeddings-*models and document parsers. - CDI-first. Use
quarkus-arcand standard CDI (@ApplicationScoped,@Inject,@Produces) for wiring. Produce framework objects (retrieval augmentors, memory providers, embedding stores) from@ApplicationScopedproducer beans. - REST and API surface. Use
quarkus-rest(Quarkus REST) withquarkus-rest-jacksonfor JSON (Jackson is the Quarkus default serializer), and exposequarkus-smallrye-openapiso endpoints are documented and explorable. - Errors leave the REST edge as RFC 9457 problem details. Add
quarkus-http-problem(io.quarkiverse.httpproblem) and every exception escaping a resource becomes anapplication/problem+jsonresponse instead of a raw 500 with a stack trace - which matters here because an unhandled model timeout, a dead inference endpoint, or a throwing tool would otherwise leak prompts and internal names to the caller; the server still logs the failure in full. It needs no configuration: thequarkus.http-problem.*keys only tune it, andinclude-detailsstaysfalseso parser failures do not echo internal class names. This covers the REST edge only - the WebSockets Next streaming path keeps its own@OnErrorhandling (section 4) - and it complements rather than replaces the declarative fault tolerance in section 4, which handles failure inside the service. The extension is in the platform BOM from Quarkus 3.38.0, so it takes no version pin. - Streaming uses WebSockets Next. For token or progress streaming, use
quarkus-websockets-nextrather than rolling a custom transport (see section 4 for the streaming pattern). - Observability comes from platform extensions, not code. Add
quarkus-micrometer-registry-prometheus(metrics, scraped at/q/metrics) andquarkus-opentelemetry(traces) and AI services are instrumented automatically: per-method timers and counters (langchain4j.aiservices.*), GenAI-semconv token usage (gen_ai.client.token.usage, tagged by operation and token type), one span per AI-service call (langchain4j.aiservices.<Interface>.<method>) and per tool call (langchain4j.tools.<tool>). Register a CDICostEstimatorbean (io.quarkiverse.langchain4j.cost) to emitgen_ai.client.estimated_cost. Prompt and completion text reaches spans only when explicitly enabled (quarkus.langchain4j.tracing.include-prompt/.include-completion) - treat those as dev-only and scope them with%dev., since they record user content. - Enable parameter-name retention. Configure the compiler with
-parameters(Maven:<parameters>true</parameters>), which REST and AI-service binding rely on. - Build for both JVM and native. Keep a
nativeMaven profile so the project can produce a GraalVM native binary alongside the JVM build, and gate native integration tests in that profile. Native builds compile against the GraalVM JDK 25 line until JDK 29 (September 2027) - see section 2 - so a project with a native profile does not raise the language level above 25. - Disable Dev Services when an external model endpoint is configured. When the project points
at a real Ollama endpoint (local or cloud), disable LangChain4j Dev Services
(
quarkus.langchain4j.devservices.enabled=false) so a container is not started implicitly.
4. LangChain4j conventions
- Declarative AI services are the default. Define AI services as CDI-managed interfaces
annotated with
@RegisterAiService(the Quarkus form of LangChain4j's declarative service), using@SystemMessage/@UserMessagefor prompts and@MemoryIdfor per-conversation memory. Prefer this over manualChatModelwiring unless there is a documented reason. - Tools are CDI beans. Expose actions to a model with
@Toolmethods on@ApplicationScopedbeans, wired via@RegisterAiService(tools = ...)or@ToolBox- never hand-rolled JSON function dispatch. Tool methods doing I/O follow the section 2 virtual-thread rules. - Multi-agent workflows are composed declaratively. Build agentic workflows from
@RegisterAiServiceagents annotated with@Agent(name, description, outputKey)and orchestrate them with the LangChain4j Agentic annotations -@SequenceAgent,@ParallelAgent,@ParallelMapperAgent, and@SupervisorAgent(+@SupervisorRequest) - assembling results with@Outputover theAgenticScope. Use thequarkus-langchain4j-agenticextension. Avoid hand-rolled executor or coordination glue between AI services. - Structured output via typed return values. Have services return records or enums to get
structured results, and set
temperature=0for classification and other deterministic tasks. - Name and right-size models. Configure models by name (
@RegisterAiService(modelName = "...")on services,@ModelName("...")on injected models) and use a small, fast, low-temperature model for cheap subtasks (classification, query rewriting) and a larger model for the primary task. Every@RegisterAiServicedeclaresmodelName, even when the project has a single model: give each role its own named block (quarkus.langchain4j.<provider>.<name>.chat-model.*) instead of leaning on the unnamed default, so re-sizing one service is a configuration change. - Streaming pattern: reactive only at the edge. Stream over
quarkus-websockets-next(@WebSocket,@OnTextMessagereturning a MutinyMulti,@OnError). Keep the agent and engine logic free of reactive types: have the WebSocket delegate to an@ApplicationScopedorchestrator that runs the blocking pipeline on a virtual thread (Multi.createFrom().emitter(...)+Thread.startVirtualThread(...)) and emits progress. Mutiny appears only at the channel edge, never inside the engine. - Guardrails wrap AI services declaratively. Validate prompts/responses with
@InputGuardrails/@OutputGuardrailsbeans implementing the upstreamdev.langchain4j.guardrailinterfaces (the Quarkus-specific guardrail API was retired in favor of upstream); tune retries withquarkus.langchain4j.guardrails.max-retries. - Externally originated free text is data, never instructions. Free text the application did
not author itself - end-user input, inbound email or ticket bodies, webhook payloads, text
relayed from an upstream system - is interpolated into a prompt only inside explicit delimiters
(
<ticket>...</ticket>), with the system message stating that the delimited span is data to process and never instructions to follow, and every entry method that receives it carries@InputGuardrails. Downstream services reading only model-produced state need no guardrail, but still delimit values derived from that text. - Fault tolerance is declarative on AI-service methods. With
quarkus-smallrye-fault-tolerance, put MicroProfile@Timeout,@Retry, and@Fallback(org.eclipse.microprofile.faulttolerance) directly on@RegisterAiServicemethods, with the fallback as adefaultmethod on the same interface - never hand-rolled try/retry loops around AI calls. Size@Timeoutgenerously on tool-calling methods: a single invocation may span several model/tool round-trips before it returns. - Reusable instructions ship as skills, not as prompt strings. When behavior would otherwise
be pasted into an ever-growing
@SystemMessage, put it in aSKILL.md(YAML front matter withnameanddescription, instructions in the body), pointquarkus.langchain4j.skills.directoriesat the folder, and annotate the service or method with@Skills(io.quarkiverse.langchain4j.skills, extensionquarkus-langchain4j-skills). The extension registers anactivate_skilltool and a system message advertising what is available, so the model pulls in a skill's instructions only when they apply - the prompt stays small and each skill stays independently editable. Narrow the surface with@Skills("name")rather than exposing everything. The extension isstatus:preview: pin the behavior you depend on with a test, and expect its API to move. - RAG starts simple with Easy RAG. For retrieval-augmented generation, start with the
quarkus-langchain4j-easy-ragextension plus an in-process embedding model: pointquarkus.langchain4j.easy-rag.pathat a documents folder and let it ingest on startup. Move to a hand-builtRetrievalAugmentor(a CDI-producedEmbeddingStore+EmbeddingStoreContentRetriever) only when a project needs control Easy RAG does not provide. - Enable request/response logging in dev. Set
%dev.quarkus.langchain4j.log-requests=trueand%dev.quarkus.langchain4j.log-responses=trueso prompts and model output are observable during development without recording user content in production.
5. Testing
- Every project keeps a
@QuarkusTestsmoke test. At least one@QuarkusTestundersrc/test/javainjects an AI service and asserts it wired; it boots the application without calling the model, so it needs no live inference. - Use
@QuarkusTest(artifactio.quarkus:quarkus-junit) for integration-style tests andio.rest-assured:rest-assuredto exercise HTTP endpoints. - Run native integration tests through
maven-failsafe-plugininside thenativeprofile. - Keep model interactions deterministic in tests (
temperature=0, fixed prompts) or mock the model so tests do not depend on live inference. - Grade model quality with the evaluation framework
(
quarkus-langchain4j-testing-evaluation-junit5+ semantic-similarity / AI-judge strategies) rather than brittle string asserts; keep the scaffolded@QuarkusTestwiring smoke test green without a live model.
6. Scope and overrides
These conventions apply to projects in this Quarkus + LangChain4j stack. A per-project addition or override is allowed when justified - for example, pinning a fixed older Java version, choosing platform threads for a pinning dependency, or selecting a different model provider - and must be documented inline near the override so the deviation and its reason stay visible.
When maintaining eldermoraes/quarkus-agentic-scaffolding itself, apply the tooling requirements
per operation as described in CONTRIBUTING.md (Required tooling). An unavailable MCP blocks
only work that needs that tool; independent repository review, documentation, CI inspection,
and approved merges may continue. This override applies only to maintenance of the scaffolding
repository; applications using its conventions retain the requirements in section 1.
<!-- END quarkus-agentic-scaffolding conventions -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

