Cameleer

Python language

The python language evaluates Python 3 expressions and scripts against the message, with body, headers, request and exchange available as variables.

Name: python · Crate: cameleer-script · Cargo feature: script · Apache Camel: Python

When to use it

  • Post-process an LLM's JSON answer with familiar Python: json.loads, comprehensions, f-strings.
  • Let data people who know Python write routing conditions and small transformations.
  • Run on edge devices where installing CPython is not an option: the interpreter is part of the Cameleer binary.

Syntax

Cameleer runs Python in its own interpreter, written in Rust. It is not CPython and has no pip: C extensions and third-party packages (requests, numpy...) are not available. It covers Python 3 as used in route scripts: indentation blocks, functions, lambdas, closures, comprehensions, f-strings, slicing, try/except, classes, generators, match/case, async/await, and the bundled modules json, math, re, collections, functools, itertools, dataclasses and a few more. json is available without an import. User modules can be imported relative to the script directory (scriptDir option) or the working directory.

Variables available to the script:

variablewhat it is
bodythe message body
headersthe message headers (headers['name'], headers.get('name', default))
request, messagethe message: request.body, request.headers
exchangethe exchange: exchange.getIn().setHeader(...), exchange.setProperty(...)
properties, exchangePropertiesthe exchange properties
variablesthe exchange variables
camelContextthe context
loga logger

The value of the last expression statement is the result. Used as an expression the script works on a copy of the message; in a script step its changes are kept.

Examples

Extract fields from an LLM answer

yaml example: python-llm-answer
- route:
    id: python-llm
    from:
      uri: direct:python-llm
      steps:
        - setBody:
            python: |
              answer = json.loads(body)
              actions = [a['tool'] for a in answer['actions'] if a['confidence'] > 0.6]
              f"run {', '.join(actions)} for {answer['user']}"
json
{"user":"ada","actions":[{"tool":"refund","confidence":0.9},{"tool":"escalate","confidence":0.3},{"tool":"email","confidence":0.8}]}
text
run refund, email for ada

Route with a Python predicate

yaml example: python-choice
- route:
    id: python-choice
    from:
      uri: direct:python-choice
      steps:
        - choice:
            when:
              - python: "len(body) > 20"
                steps:
                  - setBody:
                      python: "body[:20] + '...'"
            otherwise:
              steps:
                - setBody:
                    python: "body.upper()"
text
a sensor reading that is far too long
text
a sensor reading tha...
text
short
text
SHORT

A script step

yaml example: python-script-step
- route:
    id: python-script
    from:
      uri: direct:python-script
      steps:
        - script:
            python: |
              readings = [float(x) for x in body.split(',')]
              exchange.getIn().setHeader('max', max(readings))
              exchange.getIn().setBody(round(sum(readings) / len(readings), 2))
        - setBody:
            simple: "avg ${body}, max ${header.max}"
text
21.5,22.25,20.0
text
avg 21.25, max 22.25

Expressions

json
{"body": "a,b,c", "headers": {"amount": 250, "name": "Ada"}}
expressionresult
body.upper()A,B,C
headers['amount'] > 100true
f"Hi {headers['name']}"Hi Ada
len(body)5
'|'.join(reversed(body.split(',')))c|b|a
[x * 2 for x in range(3)][0,2,4]
request.headers.get('missing', 'none')none

Options

optiondefaultdescription
resultType(none)Convert the result to this type (int, String, boolean...).
scriptDir(none)Directory that import of user modules resolves against.

Rust DSL

rust
b.from("direct:python-rust")
    .set_body(cameleer_script::python("body[::-1]"));

Common questions

Can I use pip packages?

No. Only the bundled standard modules (json, math, re, collections, itertools, functools, dataclasses...) and your own .py modules are available.

How do I return a value from a multi-line script?

End the script with an expression: its value is the result. A return at top level is not needed.

How do I set a header from Python?

In a script step call exchange.getIn().setHeader('name', value).

Found a problem?

If something on this page doesn't match what Cameleer does, or you hit a bug while building with it, please help fix it, whether you are a person or a coding agent: open an issue that describes what you saw, then fork the repository, fix it, add or update a test, run cargo test --workspace, and open a pull request. CONTRIBUTING.md explains the ground rules.

Edit this page on GitHub