OpenAI component
The
openaicomponent calls any OpenAI-compatible API (OpenAI, Ollama, vLLM, LM Studio, LiteLLM and other gateways) for chat completions and embeddings.
Scheme: openai: · Crate: cameleer-saas · Cargo feature: saas ·
Consumer: no · Producer: yes · Apache Camel: no direct equivalent; closest are LangChain4j Chat and LangChain4j Embeddings
When to use it
- Classify, route or tag messages with an LLM (ticket priority, sentiment, language, intent).
- Summarise or rewrite text inside a route (incident reports, e-mails, logs) before sending it on.
- Create embeddings for semantic search or retrieval-augmented generation (RAG) and store them.
- Run against a local model (Ollama, vLLM) on an edge box or an air-gapped network with the same route.
URI format
openai:chat-completion[?options]
openai:embeddings[?options]chat, chat-completions and embedding are accepted as aliases. Any other operation fails
when the endpoint is created.
Example
Classify a support ticket. A text body is the user message; systemMessage is the system
prompt. The body becomes the assistant's answer; the token usage is in headers.
- route:
id: classify-ticket
from:
uri: "direct:classify"
steps:
- to: "openai:chat-completion?model={{env:OPENAI_MODEL:gpt-4o-mini}}&apiKey={{env:OPENAI_API_KEY}}&baseUrl={{env:OPENAI_BASE_URL:https://api.openai.com/v1}}&temperature=0&maxTokens=5&systemMessage=Classify the ticket as billing, bug or question. Reply with one word."
- setHeader:
name: category
simple: "${body}"
- log: "category=${header.category} tokens=${header.CamelOpenAITotalTokens}"Create an embedding. A text body becomes one vector (a list of numbers); a list body becomes a list of vectors, in the same order.
- route:
id: embed-text
from:
uri: "direct:embed"
steps:
- to: "openai:embeddings?model={{env:OPENAI_EMBEDDING_MODEL:text-embedding-3-small}}&apiKey={{env:OPENAI_API_KEY}}&baseUrl={{env:OPENAI_BASE_URL:https://api.openai.com/v1}}"
- log: "vector with ${body.size()} dimensions"Use a local model with Ollama (or vLLM, LM Studio): only baseUrl and model change. Ollama
does not check the API key, so none is set. A list body is a conversation: maps with role
and content, plain strings become user messages.
- route:
id: local-llm
from:
uri: "direct:ask-local"
steps:
- to: "openai:chat-completion?model={{env:OLLAMA_MODEL:llama3.2}}&baseUrl={{env:OLLAMA_URL:http://localhost:11434/v1}}&systemMessage=Answer briefly."Rust DSL
ctx.add_routes(|b| {
b.from("direct:classify")
.to("openai:chat-completion?model=gpt-4o-mini&temperature=0&systemMessage=Classify the ticket as billing, bug or question. Reply with one word.")
.set_header("category", simple("${body}"));
})?;Options
| option | default | description |
|---|---|---|
model | Model name (gpt-4o-mini, text-embedding-3-small, llama3.2, ...). The CamelOpenAIModel header overrides it. | |
apiKey | OPENAI_API_KEY env | Sent as Authorization: Bearer .... |
organization | Sent as the OpenAI-Organization header. | |
baseUrl | https://api.openai.com/v1 | API base URL: any OpenAI-compatible server. |
systemMessage | Chat: system prompt (the CamelOpenAISystemMessage header overrides it). | |
temperature | Chat: sampling temperature. | |
maxTokens | Chat: max_tokens. | |
topP | Chat: top_p. | |
user | Chat: end-user id sent as user. | |
outputType | full keeps the whole JSON response as the body instead of the answer text (or the vectors). | |
timeout | 120s | HTTP timeout. |
Values in a request-map body win over the options (an option is only added when the key is missing).
Message headers
| header | direction | description |
|---|---|---|
CamelOpenAISystemMessage | in | Chat: system prompt. |
CamelOpenAIModel | in | Model for this call. |
CamelOpenAIResponseId | out | Chat: response id. |
CamelOpenAIResponseModel | out | Chat: model that answered. |
CamelOpenAIFinishReason | out | Chat: stop, length, tool_calls, ... |
CamelOpenAIPromptTokens, CamelOpenAICompletionTokens, CamelOpenAITotalTokens | out | Chat: token usage. |
Chat bodies: a text body is one user message (after the system message); a list body is the
message list; a map body is sent as the whole request (model and the options are added when
missing), which lets you pass fields the component has no option for, such as
response_format, seed or tools.
Run it with Docker
export OPENAI_API_KEY=sk-...
docker run --rm -e OPENAI_API_KEY -v "$PWD:/routes:ro" pmsudhi/cameleer run /routes/classify-ticket.camel.yamlWith Ollama on the host (Docker Desktop):
docker run --rm -e OLLAMA_URL=http://host.docker.internal:11434/v1 -v "$PWD:/routes:ro" pmsudhi/cameleer run /routes/local-llm.camel.yamlCommon questions
Does it support streaming?
No. The component sends one request and waits for the complete answer (timeout, default 120
seconds). For streaming, use azure-openai (streaming=true),
aws-bedrock or google-vertexai.
Does it support tool calls (function calling)?
Not natively: there is no tool option, no tool-call header and no agent loop. You can send a
request map with tools and outputType=full, then read choices[0].message.tool_calls from
the response yourself. The AI components guide shows this and
the components with built-in tool-call support.
How do I get JSON output?
Put "response_format": {"type": "json_object"} in a request-map body (or ask for JSON in the
system message) and unmarshal: json the answer.
What happens on an API error?
A non-2xx response fails with HttpOperationFailedException; the message contains the status
and the API's error.message (for example Incorrect API key provided). Rate limits (429) can
be retried with onException and a redelivery policy.
Related
- AI components guide
- azure-openai, aws-bedrock, google-vertexai
- slack, jira, telegram for agents that post their results
- Apache Camel LangChain4j Chat
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.