Guidelines for AI agents working on this codebase.
Apache Camel is an integration framework supporting routing rules in Java, XML and YAML DSLs.
- Version: 4.21.0-SNAPSHOT
- Java: 17+
- Build: Maven 3.9.12+
These rules apply to ALL AI agents working on this codebase.
- All AI-generated content (GitHub PR descriptions, review comments, JIRA comments) MUST clearly identify itself as AI-generated and mention the human operator. Example: "Claude Code on behalf of [Human Name]"
- An agent MUST NOT open more than 10 PRs per day per operator to ensure human reviewers can keep up.
- Prioritize quality over quantity — fewer well-tested PRs are better than many shallow ones.
- An agent MUST NEVER push commits to a branch it did not create.
- If a contributor's PR needs changes, the agent may suggest changes via review comments, but must not push to their branch without explicit permission.
- An agent should prefer to use his own fork to push branches instead of the main apache/camel repository. It avoids to fill the main repository with a long list of uncleaned branches.
- An agent must provide a useful name for the git branch. It should contain the global topic and issue number if possible.
- After a Pull Request is merged or rejected, the branch should be deleted.
- An agent MUST ONLY pick up Unassigned JIRA tickets.
- If a ticket is already assigned to a human, the agent must not reassign it or work on it.
- Before starting work, the agent must assign the ticket to its operator and transition it to "In Progress".
- Before closing a ticket, always set the correct
fixVersionsfield. Note:fixVersionscannot be set on an already-closed issue — set it before closing, or reopen/set/close if needed.
When pushing new commits to a PR, always update the PR description (and title if needed) to
reflect the current state of the changeset. PRs evolve across commits — the description must stay
accurate and complete. Use gh pr edit --title "..." --body "..." after each push.
When creating a PR, always identify and request reviews from the most relevant committers:
- Run
git log --format='%an' --since='1 year' -- <affected-files> | sort | uniq -c | sort -rn | head -10to find who has been most active on the affected files. - Use
git blameon key modified files to identify who wrote the code being changed. - Cross-reference with the committer list to ensure you request reviews from active committers (not just contributors).
- For component-specific changes, prefer reviewers who have recently worked on that component.
- For cross-cutting changes (core, API), include committers with broader project knowledge.
- Request review from at least 2 relevant committers using
gh pr edit --add-reviewer. - When all comments on the Pull Request are addressed (by providing a fix or providing more explanation) and the PR checks are green, re-request review on existing reviewers so that they are aware that the new changeset is ready to be reviewed.
- An agent MUST NOT merge a PR if there are any unresolved review conversations.
- An agent MUST NOT merge a PR without at least one human approval.
- An agent MUST NOT approve its own PRs — human review is always required.
- Every PR must include tests for new functionality or bug fixes.
- Every PR must include documentation updates where applicable.
Any user-visible change must be documented in the upgrade guide
(
docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_XX.adoc) and in the relevant command or component documentation page. This includes: changed defaults, new auto-detection behavior, removed or renamed options, changed header names or values, API/SPI signature changes, removed or deprecated components, migrated libraries, and renamed documentation pages. For backported changes, the upgrade guide entry must be added on themainbranch (not on the maintenance branch where the fix is backported). - All code must pass formatting checks (
mvn formatter:format impsort:sort) before pushing. - All generated files must be regenerated and committed (CI checks for uncommitted changes).
Do NOT use Thread.sleep() in test code. It leads to flaky, slow, and non-deterministic tests.
Use the Awaitility library instead, which is already
available as a test dependency in the project.
Example — waiting for a route to be registered:
import static org.awaitility.Awaitility.await;
await().atMost(20, TimeUnit.SECONDS)
.untilAsserted(() -> assertEquals(1, context.getRoutes().size()));Rules:
- New test code MUST NOT introduce
Thread.sleep()calls. - When modifying existing test code that contains
Thread.sleep(), migrate it to Awaitility. - Always set an explicit
atMosttimeout to avoid hanging builds. - Use
untilAssertedoruntilwith a clear predicate — do not replace a sleep with a busy-wait loop.
Before implementing a fix for a JIRA issue, thoroughly investigate the issue's validity and context. Camel is a large, long-lived project — code often looks "wrong" but exists for good reasons. Do NOT jump straight to implementation after reading the issue description and the current code.
Required investigation steps:
- Validate the issue: Confirm the reported problem is real and reproducible. Question assumptions in the issue description — they may be incomplete or based on misunderstanding.
- Check git history: Run
git log --oneline <file>andgit blame <file>on the affected code. Read the commit messages and linked JIRA tickets for prior changes to understand why the code is written the way it is. - Search for related issues: Search JIRA for related tickets (same component, similar keywords) to find prior discussions, rejected approaches, or intentional design decisions.
- Look for design documents: Check the
design/directory for design docs (.adocfiles) that may explain architectural decisions in the affected area. Key documents by area:- Security (secrets, SSL/TLS, serialization, policy enforcement):
design/security.adoc - Tracing / Telemetry (OpenTelemetry, spans, context propagation):
design/tracing.adoc - MDC / Logging (MDC propagation, logging context):
design/mdc.adoc - Headers (naming conventions, constants, upgrade policy):
design/headers.adoc
- Security (secrets, SSL/TLS, serialization, policy enforcement):
- Understand the broader context: If the issue involves a module that replaced or deprecated
another (e.g.,
camel-opentelemetry2replacingcamel-opentelemetry), understand why the replacement was made and what was intentionally changed vs. accidentally omitted. - Check if the "fix" reverts prior work: If your proposed change effectively reverts a prior intentional commit, stop and reconsider. If the revert is still justified, explicitly acknowledge it in the PR description and explain why despite the original rationale.
Present your findings to the operator before implementing. Flag any risks, ambiguities, or cases where the issue may be invalid or the proposed approach may conflict with prior decisions.
AI agents have a training data cutoff and may not know about recent releases, API changes, or deprecations in external projects. Never make authoritative claims about external project state based solely on training knowledge.
- When a JIRA issue, PR, or code references a specific version of an external dependency (e.g., Spring Boot 4.0, JUnit 6, Jakarta EE 11), verify it exists by checking official sources (web search, Maven Central, release notes) before questioning or relying on it.
- When implementing or reviewing changes that depend on external project behavior, verify the current state rather than assuming training data is up to date.
- If uncertain about whether something exists or has changed, say so and verify — do not confidently assert something is wrong based on potentially stale knowledge.
When reviewing PRs, apply the same investigative rigor:
- Check
git logandgit blameon modified files to see if the change conflicts with prior intentional decisions. - Verify that "fixes" don't revert deliberate behavior without justification.
- Check for design documents (
design/*.adoc) related to the affected area (see the area-to-document mapping in "Issue Investigation" above). - Search for related JIRA tickets that provide context on why the code was written that way.
When writing or modifying .adoc documentation:
- Use
xref:for internal links, never externalhttps://camel.apache.org/...URLs. Example:xref:manual::camel-jbang.adoc[Camel JBang]instead ofhttps://camel.apache.org/manual/camel-jbang.html[Camel JBang]. - Cross-version xref fragments: When linking to a section anchor (e.g.,
#_my_section) using thecomponents::prefix, verify that the target section exists in the current released version, not just onmain. Thecomponents::prefix resolves to the latest released version, so anchors that only exist onmainwill produce broken links. Either omit the fragment or use a version-aware reference. - When reviewing doc PRs, check that all
xref:links and anchors resolve correctly, especially cross-component references that may span versions.
Camel has a documented threat model that defines who is trusted, where the trust boundaries sit,
what counts as a framework vulnerability, and what is operator responsibility. The canonical
document is docs/user-manual/modules/ROOT/pages/security-model.adoc.
Use it as the reference when triaging security reports, deciding whether a finding warrants a
CVE, or reviewing a security-sensitive PR.
For the vulnerability reporting convention, SECURITY.md at the repository
root is the entry point GitHub and security tooling expect. It points to the threat model above
for scope and to the ASF process for private disclosure. An agent that discovers or is handed a
suspected vulnerability MUST NOT open a public issue, PR, or mailing-list post about it — follow
the private process in SECURITY.md and stop.
- Camel committers and component authors are trusted to ship secure defaults.
- Route authors (the people writing DSL routes) are fully trusted. They execute arbitrary
Java in
.bean()/.process(), evaluate arbitrary expressions insimple/groovy/jexl/mvel/xpath, and configure every component option. Code execution by a route author is by design and is not a vulnerability. - Deployment operators are fully trusted. They set configuration, secrets, network exposure and the JVM. Their misconfiguration is not a framework vulnerability unless Camel's default exposed it.
- External message senders (HTTP clients, JMS producers, file droppers, SMTP senders, CoAP peers, etc.) are untrusted. This is the primary attacker model.
The fundamental trust boundary is between the route plus its configuration (trusted) and the data flowing through the route (untrusted). The framework must not turn untrusted data into code execution, file read, request forgery, or auth bypass on its own.
Reports that demonstrate untrusted input crossing a trust boundary the framework should have held — in a default or reasonably-expected configuration — are in scope. Concrete classes the PMC has historically accepted:
- Unsafe deserialisation of untrusted input (XStream / Hessian / Jackson polymorphic / raw
ObjectInputStreamin consumers, type converters, aggregation repositories, key stores). - XXE and remote DTD/stylesheet resolution in XML/XSLT/XPath/XSD parsers.
- Expression or template language injection where the framework itself passes untrusted input to an evaluator (not the route author).
- Path traversal in file/mail/FTP consumers and producers.
- SSRF triggered by parser default resolution.
- Camel-header / bean-dispatch abuse when a consumer maps untrusted input into the Exchange
header map without a strict, case-insensitive
HeaderFilterStrategy. - Auth/authz bypass in components implementing AAA (Keycloak, Shiro, platform-http auth, Spring Security integration).
- Information disclosure of secrets or Exchange state via logs, events, world-readable files or HTTP responses.
- Insecure defaults — any component shipping with deserialisation, TLS-skip or admin-exposure enabled out of the box.
- Injection into back-end queries built by Camel itself (Cypher, XSLT extension functions, etc.).
The following are explicitly not framework vulnerabilities and will be closed as such:
- A route author executing arbitrary code through
.bean(),.process(),Runtime.exec(), or evaluatingsimple/groovyon untrusted input. Route code is trusted. - A route author building a SQL / Cypher / LDAP / HTTP URI from untrusted input without parameterising. The route is at fault, not the framework.
- Behaviour that is enabled by explicit opt-in:
allowJavaSerializedObject=true,transferException=true,trustAllCertificates=true,hostnameVerificationEnabled=false, or selecting anObjectInputStream-using data format. - DoS / resource exhaustion through unthrottled routes. Operators apply
throttle,circuitBreaker,resilience4j, JVM limits. - A deployer exposing
camel-management, the developer console,camel-jolokiaor JMX on a public network. - Third-party transitive dependency CVEs that are not reachable through any Camel-exposed code path.
- Automated scanner reports without a PoC demonstrating an actual trust-boundary breach.
When reviewing or recommending a deployment, surface the following:
- Enable the security policy framework: set
camel.main.profile = prodso the default forsecret/insecure:ssl/insecure:serialization/insecure:devisfail(seedesign/security.adoc). - Resolve secrets through one of the supported vaults rather than plain-text properties.
- Configure TLS through
SSLContextParameters(the JSSE Utility); nevertrustAllCertificatesin production. - Strip Camel-internal headers (
Camel*,org.apache.camel.*) from messages arriving from untrusted producers usingremoveHeaders("Camel*")before any dispatching processor. - Do not enable Java serialisation on consumers exposed to untrusted networks.
- Keep
camel-management, the developer console,camel-jolokiaand JMX on a trusted network only.
When reviewing a PR that touches a consumer, type converter, aggregation repository, data
format, parser, or anything that handles @UriParam security knobs:
- Does the inbound side apply a
HeaderFilterStrategythat blocksCamel*/camel*/org.apache.camel.*case-insensitively? The header-injection family (CVE-2025-27636 and five follow-ons) recurred precisely because new consumers shipped without it. - Does the change call
ObjectInputStream.readObject()(directly or via Hessian/Castor/XStream) without anObjectInputFilter? Five sequential CVEs (CVE-2024-22369, 23114, 2026-25747, 27172, 40858) accepted this exact pattern in aggregation repositories. - Does any new
@UriParamcontrol a security-relevant default? If so, mark it withsecret = truefor secrets orsecurity = "insecure:ssl"/"insecure:serialization"/"insecure:dev"for risky flags (see theAnnotationssubsection further down). - Does the change relax a default? New defaults err toward "denied unless opted in". A relaxed default needs an upgrade-guide entry and PMC sign-off.
- Does an authentication or authorization component enforce what its option names claim — issuer validation, audience checking, signature verification, every advertised sub-path covered?
camel/
├── core/ # Core modules (camel-api, camel-core, camel-support, etc.)
├── components/ # 300+ components (kafka, aws, http, etc.)
├── dsl/ # DSLs (jbang, yaml-dsl, endpointdsl)
├── test-infra/ # Testcontainers-based test services
├── catalog/ # Component metadata
├── tooling/ # Maven plugins
├── archetypes/ # Maven archetypes
├── tests/ # Integration tests
└── docs/ # AsciiDoc docs
mvn clean install -Dquickly # fast build, no tests
mvn clean install # full build
mvn clean install -pl components/camel-kafka -am # single module
mvn formatter:format && mvn impsort:sort # format code
mvn clean install -Psourcecheck # verify stylemvn test # unit tests
mvn verify -Pit # integration testsTest infra usage:
@RegisterExtension
static KafkaService service = KafkaServiceFactory.createService();camel-<name>/
├── pom.xml
└── src/
├── main/java/org/apache/camel/component/<name>/
│ ├── <Name>Component.java
│ ├── <Name>Endpoint.java
│ ├── <Name>Producer.java
│ └── <Name>Consumer.java
├── main/docs/
├── generated/
└── test/java/
Classes:
<Name>Component extends DefaultComponent<Name>Endpoint extends DefaultEndpoint<Name>Producer extends DefaultProducer<Name>Consumer extends DefaultConsumer- Tests:
*Test.java(JUnit 5)
Packages:
- Components:
org.apache.camel.component.<name> - Core:
org.apache.camel.<module>
Deprecation:
- Add
(deprecated)suffix to<name>inpom.xml:<name>Camel :: MyComponent (deprecated)</name> - Add
(deprecated)suffix to the doc page title insrc/main/docs/*.adoc - Add
@Deprecatedto Java classes - Document in the upgrade guide (
docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_XX.adoc)
Annotations:
@UriPathfor path params@UriParamfor query params- Always add
descriptionfor docs - Mark sensitive parameters with
secret = trueon@UriParamor@Metadata(passwords, tokens, API keys) - For insecure configuration flags (e.g.,
trustAllCertificates,allowJavaSerializedObject), addsecurity = "insecure:ssl"/"insecure:serialization"/"insecure:dev"on@UriParam. Seedesign/security.adocfor categories and rationale.
Import Style:
- Do NOT use fully qualified class names (FQCNs) in Java code. Always add an
importstatement and use the simple class name (e.g., writeListnotjava.util.List). - Exception: when two classes share the same simple name (e.g.,
java.util.Dateandjava.sql.Date), import the most-used one and qualify the other. - This applies to all code: production, test, and test-infra.
- Generated code (
src/generated/) is excluded from this rule. - The build automatically shortens unnecessary FQCNs via OpenRewrite (
rewrite-maven-plugin). CI will fail if uncommitted FQCN changes are detected after the build.
Javadoc @since Tags:
- All new public classes, interfaces, enums, and annotations in
core/camel-apiMUST include a@since X.YJavadoc tag indicating the Camel version when they are introduced. - All new public methods added to existing interfaces/classes in
core/camel-apiMUST include a@since X.YJavadoc tag on each new method. - Use the upcoming minor release version (e.g.,
@since 4.21if the current SNAPSHOT is 4.21.0). - Place
@sinceas the last Javadoc tag, after@param,@return,@throws, etc.
No extra config needed.
You must register the component in MojoHelper:
File: tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
Add to the getComponentPath() switch:
case "camel-aws":
return Arrays.asList(dir.resolve("camel-aws2-athena"),
// ...
dir.resolve("camel-your-new-component"));Parent folders needing registration:
camel-ai(langchain4j, vector dbs)camel-awscamel-azurecamel-googlecamel-ibmcamel-huaweicamel-debeziumcamel-vertxcamel-microprofilecamel-infinispancamel-cxfcamel-spring-parentcamel-test
Without this, the build won't pick up your component for catalog/docs generation.
- Avoid using Docker Hub images, prefer to use Google
mirror.gcr.ioor Red Hatquay.ioones. - Verify that the container image is available for the tested architectures (currently
amd64,ppc64leands390x). Sometimes the image is provided in different registries such asicr.io. If not available, useskipITs.ppc64leandskipITs.s390xMaven properties to disable it.
CAMEL-XXXX: Brief description
Reference JIRA when applicable.