Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Step verbs reference

Every YAML step verb and field, derived from the authoritative source crates/camel-dsl/src/route_ast.rs. Each verb maps to a struct that Route structure.

Where a verb takes a predicate or value expression, the standard language fields apply: simple, rhai, jsonpath, xpath, or language paired with source. The tables below list them in full.

Step verbs

to

Send the exchange to an endpoint URI.

FieldTypeRequiredDescription
tostringyesTarget endpoint URI
- to: "log:info"

log

Log the exchange state.

FormSyntax
Shortlog: "message"
Fulllog: { message: "...", level: "DEBUG" }

The message field accepts a bare string or an expression object (simple, rhai, jsonpath, xpath, or language+source). level is optional.

- log: "Processing exchange"
- log:
    message: "Body is ${body}"
    level: "DEBUG"

set_header

Set a message header.

FieldTypeRequiredDescription
keystringyesHeader name
valueanynoLiteral value
simplestringnoSimple expression
rhaistringnoRhai expression
jsonpathstringnoJSONPath expression
xpathstringnoXPath expression
languagestringnoNamed expression language
sourcestringnoExpression source for language
- set_header:
    key: "MyHeader"
    value: "hello"

remove_header

Remove a message header from the input message. If the header is absent, the step does nothing (no error). Removal is input-only: output message headers are not changed.

FieldTypeRequiredDescription
keystringyesHeader name to remove
- remove_header:
    key: "CamelHttpPath"

set_property

Set an exchange property. Same expression fields as set_header but keyed by name.

FieldTypeRequiredDescription
namestringyesProperty name
valueanynoLiteral value
simplestringnoSimple expression
rhaistringnoRhai expression
jsonpathstringnoJSONPath expression
xpathstringnoXPath expression
languagestringnoNamed expression language
sourcestringnoExpression source for language
- set_property:
    name: "MyProperty"
    value: 42

set_body

Set the exchange body.

FormSyntax
Literalset_body: "value"
Configset_body: { value: ... } or set_body: { simple: "..." }

The config form accepts value plus any expression field (simple, rhai, jsonpath, xpath, language+source).

- set_body: "static value"
- set_body:
    value: "Hello World!"
- set_body:
    simple: "${header.foo}"

transform

Alias for set_body. Same forms and fields.

- transform:
    simple: "${body.field}"

filter

Conditionally run child steps. When the predicate is false, the exchange skips the steps list and continues down the pipeline.

FieldTypeRequiredDescription
simplestringnoSimple predicate
rhaistringnoRhai predicate
jsonpathstringnoJSONPath predicate
xpathstringnoXPath predicate
languagestringnoNamed expression language
sourcestringnoExpression source for language
stepslistnoChild steps when the predicate holds
- filter:
    simple: "${header.type} == 'important'"
    steps:
      - to: "log:important"

choice

Content-based router. Evaluates when clauses in order and runs the first that matches. otherwise runs when no clause matches.

FieldTypeRequiredDescription
whenlistnoPredicate blocks (expression fields + steps)
otherwiselistnoFallback steps
- choice:
    when:
      - simple: "${header.type} == 'a'"
        steps:
          - to: "log:a"
      - simple: "${header.type} == 'b'"
        steps:
          - to: "log:b"
    otherwise:
      - to: "log:other"

do_try

Protected block with catch and finally clauses.

FieldTypeRequiredDescription
stepslistyesProtected steps
catchlistnoCatch clauses
finallyobjectnoFinally clause

Each catch entry accepts exception (list of error kinds), when and on_when predicates, disposition (defaults to handled), and steps. The finally object carries an optional on_when and a required steps list.

- do_try:
    steps:
      - to: "direct:fragile"
    catch:
      - exception: ["ProcessorError"]
        steps:
          - to: "log:error"
    finally:
      steps:
        - to: "log:cleanup"

delay

Pause processing.

FormSyntax
Shortdelay: 500 (milliseconds)
Fulldelay: { delay_ms: 500, dynamic_header: "X-Delay" }
- delay: 500
- delay:
    delay_ms: 200
    dynamic_header: "X-Delay"

loop

Repeat child steps.

FormSyntax
Countloop: 3
Fullloop: { count: 3, steps: [...] }
Whileloop: { while: { simple: "..." }, steps: [...] }

Full-form fields:

FieldTypeRequiredDescription
countintegernoFixed iteration count (exclusive with while)
whileobjectnoPredicate block; loops while it holds
stepslistnoChild steps per iteration
max_iterationsintegernoSafety cap on iterations

The while block accepts the standard predicate fields (simple, rhai, jsonpath, xpath, language+source).

- loop: 3
- loop:
    count: 5
    steps:
      - to: "log:iteration"

split

Split the body into fragments and process each.

FieldTypeRequiredDefaultDescription
expressionstring/objectnoSplit expression (string or language block)
aggregationstringnolast_winsAggregation strategy
parallelboolnofalseProcess fragments in parallel
parallel_limitintegernoMax parallel fragments
stop_on_exceptionboolnotrueStop on first error
streamingboolnofalseStream the split
streamobjectnoStream config (format, max_record_bytes, batch_size, chunk_size)
stepslistno[]Per-fragment steps
- split:
    expression: "body_lines"
    aggregation: "last_wins"
    steps:
      - log: "Split item: ${body}"
      - to: "log:split-item"
- split:
    expression:
      simple: "${header.items}"
    aggregation: "collect_all"
    steps:
      - to: "log:fragment"

aggregate

Group exchanges by correlation key. Emits one combined exchange when a completion condition fires. The combined exchange then continues down the pipeline, so aggregate has no nested steps block.

FieldTypeRequiredDefaultDescription
headerstringyesHeader used as the correlation key
correlation_keystringnoAlternative correlation expression
completion_sizeintegernoComplete after N exchanges
completion_timeout_msintegernoComplete after timeout
completion_predicateobjectnoPredicate-block completion trigger
strategystringnocollect_allAggregation strategy
max_bucketsintegernoMax concurrent buckets
bucket_ttl_msintegernoBucket time-to-live
force_completion_on_stopboolnoEmit pending buckets on route stop
discard_on_timeoutboolnoDrop buckets that time out
- aggregate:
    header: "CorrelationId"
    completion_size: 10

marshal

Serialize the body to a data format.

FieldTypeRequiredDescription
marshalstringyesFormat name (json, protobuf, ...)
configobjectnoFormat-specific config
- marshal: "json"

unmarshal

Parse the body from a data format. An optional schema validates the parsed JSON and rejects mismatches.

FieldTypeRequiredDescription
unmarshalstringyesFormat name
schemaobjectnoJSON Schema for validation
configobjectnoFormat-specific config
- unmarshal: "json"

convert_body_to

Convert the body type.

FieldTypeRequiredDescription
convert_body_tostringyesTarget type (json, ...)
- convert_body_to: json

bean

Invoke a registered bean method.

FieldTypeRequiredDescription
namestringyesBean name
methodstringyesMethod name
- bean:
    name: "myBean"
    method: "handle"

script

Run a script inline.

FieldTypeRequiredDescription
languagestringyesScript language (rhai, ...)
sourcestringyesScript source
- script:
    language: "rhai"
    source: "1 + 1"

function

Run a function in an external runtime.

FieldTypeRequiredDescription
runtimestringyesRuntime name (deno, ...)
sourcestringyesFunction source
timeout_msintegernoExecution timeout
- function:
    runtime: "deno"
    source: "export default (ctx) => ctx.body = { processed: true }"

stop

Stop route processing. The exchange returns to the consumer as a successful response.

- stop: true

stream_cache

Materialize a stream body into bytes.

FormSyntax
Boolstream_cache: true
Configstream_cache: { threshold: 65536 }
- stream_cache: true
- stream_cache:
    threshold: 65536

wire_tap

Send a fire-and-forget copy of the exchange to another endpoint.

- wire_tap: "log:tap"

multicast

Fan the exchange out to multiple endpoints.

FieldTypeRequiredDefaultDescription
parallelboolnofalseSend in parallel
parallel_limitintegernoMax parallel sends
stop_on_exceptionboolnofalseStop on first error
timeout_msintegernoPer-endpoint timeout
aggregationstringnolast_winsAggregation strategy
stepslistno[]Target endpoints as steps
- multicast:
    steps:
      - to: "log:a"
      - to: "log:b"

scatter_gather

Fan out to a fixed set of endpoints and aggregate the results.

FieldTypeRequiredDefaultDescription
endpointslistno[]Target endpoint URIs
aggregationstringnolast_winsAggregation strategy
- scatter_gather:
    endpoints:
      - "log:a"
      - "log:b"

recipient_list

Resolve recipients from an expression and send to each.

FieldTypeRequiredDefaultDescription
simplestringnoSimple expression for the recipient list
rhaistringnoRhai expression
languagestringnoNamed expression language
sourcestringnoExpression source for language
delimiterstringno,URI delimiter
parallelboolnofalseSend in parallel
parallel_limitintegernoMax parallel sends
stop_on_exceptionboolnofalseStop on first error
strategystringnoAggregation strategy
- recipient_list:
    simple: "${header.recipients}"

routing_slip

Route through a list of endpoints carried on the exchange.

FieldTypeRequiredDefaultDescription
simplestringnoSimple expression for the slip
rhaistringnoRhai expression
languagestringnoNamed expression language
sourcestringnoExpression source for language
uri_delimiterstringno,URI delimiter
cache_sizeintegerno1000Endpoint cache size
ignore_invalid_endpointsboolnofalseSkip invalid endpoints
- routing_slip:
    simple: "${header.routeSlip}"

dynamic_router

Resolve the next endpoint at each step until the expression returns empty.

FieldTypeRequiredDefaultDescription
simplestringnoSimple expression
rhaistringnoRhai expression
languagestringnoNamed expression language
sourcestringnoExpression source for language
uri_delimiterstringno,URI delimiter
cache_sizeintegerno1000Endpoint cache size
ignore_invalid_endpointsboolnofalseSkip invalid endpoints
max_iterationsintegerno1000Max routing iterations
- dynamic_router:
    simple: "${header.nextEndpoint}"

throttle

Rate-limit the exchange flow.

FieldTypeRequiredDefaultDescription
max_requestsintegeryesMax requests per period
period_secsintegerno1Time period in seconds
strategystringnoThrottle strategy
stepslistno[]Child steps
- throttle:
    max_requests: 10
    steps:
      - to: "log:throttled"

load_balance

Distribute exchanges across target endpoints.

FieldTypeRequiredDefaultDescription
strategystringnoround_robinLoad balance strategy
distribution_ratiostringnoWeighted distribution
stepslistno[]Target endpoints
- load_balance:
    strategy: "round_robin"
    steps:
      - to: "log:a"
      - to: "log:b"

enrich

Enrich the exchange by requesting data from an endpoint.

FormSyntax
Shortenrich: "http:..."
Fullenrich: { uri: "...", strategy: "...", timeout: 5000 }

The full form takes uri (required), strategy, and timeout.

- enrich: "http:my-service/api/data"
- enrich:
    uri: "http:my-service/api/data"
    strategy: "use_enriched_body"
    timeout: 5000

poll_enrich

Enrich the exchange by polling an endpoint. Same fields as enrich.

- poll_enrich: "file:data"

validate

Assert a predicate over the exchange. A failed assertion fails the exchange.

- validate: "${body.field} != null"

idempotent_consumer

Deduplicate exchanges by message ID.

FieldTypeRequiredDefaultDescription
repositorystringyesRepository name
expressionstringyesMessage ID expression
stepslistno[]Steps for first-time exchanges
eagerboolnoReserve the key before processing
remove_on_failureboolnoRemove the key if the child fails
- idempotent_consumer:
    repository: "memory"
    expression: "${header.messageId}"
    steps:
      - to: "log:first-time"

claim_check

Stash or retrieve the message body in a claim check repository.

FieldTypeRequiredDescription
repositorystringyesRepository name
operationstringyesset, get, get_and_remove, push, or pop
keystringyesClaim check key expression
filterstringnoSelective merge-back filter
- claim_check:
    repository: "memory"
    operation: "set"
    key: "${header.claimKey}"

cache

Cache a computed body by key with TTL. On hit, serves the cached body. On miss, runs the on_miss sub-pipeline and stores the result.

FieldTypeRequiredDefaultDescription
repositorystringno"memory"Repository name
keystringyesCache key expression (None = bypass cache)
ttldurationnoTime-to-live for the cached entry
max_entry_bytesintegerno10 MiBMaximum body size to cache
coalesce_missesboolnofalseRun one on_miss per concurrent miss wave on the same key
on_misslistyesSub-pipeline to run on cache miss
- cache:
    key: "${header.cacheKey}"
    ttl: "5s"
    on_miss:
      - set_body: "computed"

With coalesce_misses: true, concurrent misses on the same key run the on_miss sub-pipeline once. The first miss leads. The rest wait and share the leader's body and error.

cache_invalidate

Remove a single entry or a namespace from the cache repository. Set key for an exact-key removal or key_prefix for a namespace purge. Exactly one of the two is required.

FieldTypeRequiredDefaultDescription
repositorystringno"memory"Repository name
keystringnoExact cache key expression (mutually exclusive with key_prefix)
key_prefixstringnoNamespace prefix expression (mutually exclusive with key)

On success the step sets the CamelCacheInvalidatedCount exchange property: 1 for an exact key, the removed count for a prefix. A backend without key iteration (memory) fails closed on key_prefix.

- cache_invalidate:
    key: "${header.cacheKey}"
- cache_invalidate:
    key_prefix: "user-profile-"

cache_clear

Remove every entry from the cache repository.

FieldTypeRequiredDefaultDescription
repositorystringno"memory"Repository name
- cache_clear: {}
- cache_clear:
    repository: "persistent"

cache_stats

Replace the body with a JSON snapshot of the cache repository statistics.

FieldTypeRequiredDefaultDescription
repositorystringno"memory"Repository name
- cache_stats: {}

The snapshot holds repository, hits, misses, evictions, entries, peek_stale_served, invalidations, and bytes. The bytes field is the stored payload size when the backend reports it (null for the memory backend).

cache_peek_stale

Serve a cached entry, ignoring its in-band expiry. Used as a stale-read fallback.

FieldTypeRequiredDescription
keystringyesCache key expression
on_missstringnoOn-miss policy: "stop" (default) or "continue"

on_miss does not have the same meaning as the on_miss field of cache. In cache, the field holds a sub-pipeline. In cache_peek_stale, the field holds a policy word. Do not write a step list under cache_peek_stale.on_miss.

- cache_peek_stale:
    key: "${header.cacheKey}"
    on_miss: continue

sampling

Process one exchange out of every N.

FormSyntax
Shortsampling: 5 (period)
Fullsampling: { period: 5 }
- sampling: 5
- sampling:
    period: 10

sort

Sort the body array by a key expression.

FieldTypeRequiredDefaultDescription
expressionstringyesSort key expression
reverseboolnofalseDescending sort
languagestringnoExpression language
- sort:
    expression: "${body.field}"
    reverse: true

resequence

Reorder exchanges by sequence number. Batch mode collects and sorts; stream mode is reserved for future use.

FieldTypeRequiredDescription
batchobjectnoBatch config: correlation, sort, completion
streamobjectnoStream config (not yet implemented)

The completion object accepts size, timeout, and size_or_timeout.

- resequence:
    batch:
      correlation: "${header.seq}"
      sort: "asc"
      completion:
        size: 100
        timeout: 5000

Route-level config

These objects attach to a route. See Route structure for where each one goes.

Error handler config

FieldTypeRequiredDefaultDescription
dead_letter_channelstringnoDLC endpoint URI
retryobjectnoRedelivery policy
on_exceptionslistnoPer-exception clauses
use_original_messageboolnofalseUse original message in DLC

Redelivery policy

FieldTypeRequiredDefaultDescription
max_attemptsintegeryesMax retry attempts
initial_delay_msintegerno100Initial delay in ms
multiplierfloatno2.0Backoff multiplier
max_delay_msintegerno10000Max delay in ms
jitter_factorfloatno0.0Jitter factor (0.0-1.0)
handled_bystringnoRoute here after retries are exhausted

OnException clause

FieldTypeRequiredDescription
kindstringnoError variant name to match
message_containsstringnoSubstring match on error message
retryobjectnoPer-clause redelivery policy
stepslistnoHandler steps
handledboolnoAbsorb the error
continuedboolnoClear error and continue the pipeline

Circuit breaker config

FieldTypeRequiredDefaultDescription
failure_thresholdintegerno5Failures before opening
open_duration_msintegerno30000Duration in the open state
fallbacklistnoSub-pipeline executed while the circuit is open

The fallback list holds a sub-pipeline of steps. The breaker runs it instead of rejecting the exchange while the circuit is open. See Circuit breaker for the full surface.

Security policy config

Choose exactly one form: roles, scopes, ref, wasm, or permission.

FieldTypeRequiredDescription
roleslistnoRequired roles
scopeslistnoRequired scopes
all_requiredboolnoAll roles/scopes required
refstringnoReference to a policy
wasmstringnoWASM policy source
configmapnoPolicy-specific config
permissionobjectnoPermission-based policy

Top-level blocks

A route file also accepts these top-level keys alongside routes.

REST DSL

The rest key defines REST API blocks.

FieldTypeRequiredDefaultDescription
hoststringno0.0.0.0Listen host
portintegerno8080Listen port
pathstringno""Base path
security_policyobjectnoBlock authorization copied to every lowered route
operationslistno[]HTTP operations

REST operation:

FieldTypeRequiredDefaultDescription
methodstringyesHTTP method (GET, POST, ...)
pathstringno/Sub-path
operation_idstringnoUnique operation ID
tostringnoTarget endpoint URI
stepslistno[]Child steps
consumesstringnoapplication/jsonRequest content type
producesstringnoapplication/jsonResponse content type
bindingstringnojsonBinding mode: json or raw
success_statusintegernoSuccess HTTP status
request_schemaobjectnoRequest body schema
responseobjectnoResponse definition
descriptionstringnoOperation description
parametersmapno{}Additional parameters

Operations bind in one of two modes. The default json mode accepts JSON-essence media types for consumes and produces: bare application/json, parameterized forms such as application/json; charset=utf-8, and +json suffixes such as application/problem+json. It unmarshals requests, marshals responses, and validates declared schemas automatically. Any other media type in json mode fails route load. The raw mode accepts any RFC 9110 type/subtype media type, leaves the request as Body::Stream with no automatic unmarshal or marshal, and sends the trimmed produces value as the response Content-Type. request_schema and response.schema are rejected in raw mode. The default success status is injected in both modes; a raw POST returns 201 with the declared produces type.

- method: post
  path: /ingest
  binding: raw
  consumes: application/octet-stream
  produces: text/plain
  to: direct:ingest

Raw binding streaming contract

raw operations own the stream semantics of their request and reply bodies. The contract:

  • No pipeline caching. Lowering injects no unmarshal/marshal, so no StreamCacheService-wrapped processor compiles ahead of the user steps. The request Body::Stream reaches the first user step unpollied; the injected Content-Type and default-status steps never read it.
  • Single consumption. The request stream is consumed at most once. A second consumption attempt fails with AlreadyConsumed and propagates as a route error — never a panic. A reply whose stream was already consumed returns HTTP 500 with an empty body.
  • Metadata preservation. The HTTP consumer records the request Content-Type and Content-Length in the stream metadata before the exchange enters the route, and the pipeline never alters them.
  • Original or new reply stream. A route may reply with the original request stream (echo) or a newly generated Body::Stream; both are streamed to the wire under the route-supplied Content-Type.
  • Request limits fail closed. A request with Content-Length over max_request_body is rejected 413 before the stream opens. A chunked request over the cap fails with the limit error when consumed.
  • Response limits cover materialized bytes only. max_response_body caps materialized reply bodies — an over-cap materialized reply is replaced with HTTP 500 (Response body exceeds configured limit). A streamed reply is not byte-capped: capping a stream mid-flight would truncate an already-committed response, so routes that need response caps must materialize the body first.
  • Client disconnects do not fail the consumer. If a client drops the connection during a streamed reply, the server keeps serving subsequent requests.

Template declaration

FieldTypeRequiredDefaultDescription
idstringyesTemplate identifier
parameterslistno[]Template parameters
routeslistno[]Route definitions with {{param}} placeholders

Templated route instantiation

FieldTypeRequiredDescription
route_template_refstringyesTemplate ID to instantiate
route_idstringnoOverride route ID
parametersmapnoConcrete parameter values

Reference: DSL crate