Overview
Integration flows use Apache Camel LangChain4j for LLM steps and the operator MCP Bridge for external tool discovery and invocation. Both are configured from the CR:
spec.ephemeral.properties— Quarkus/Camel key-value map merged into the workerapplication.propertiesspec.secrets— Kubernetes Secrets injected as env vars (envFrom: true) or volume mountsspec.ephemeral.disableProperties— glob patterns to remove auto-detected defaults (e.g. disable OpenAI when using Ollama only)
Plain-text index of 20+ ephemeral AI YAML examples: docs/ephemeral-ai-examples.txt and k8s/examples/ephemeral-ai/.
How CR properties reach the worker
The EphemeralConfigMerger assembles five layers into
application.properties mounted in ConfigMap iflow-<name>-sources.
Later layers override earlier ones; Layer 5 removes keys matched by glob patterns.
| Layer | Source | Example |
|---|---|---|
| 1 — Worker built-in | Baked into the Quay worker image | camel.main.routes-reload-enabled |
| 2 — Component-required | ComponentPropertiesRegistry from detected route schemes | camel.component.kafka.brokers=${KAFKA_BOOTSTRAP:localhost:9092} |
| 3 — Scaffold-generated | OTel endpoint, resilience from spec.resilience | quarkus.opentelemetry.enabled=true |
| 4 — User overrides | spec.ephemeral.properties | quarkus.langchain4j.openai.api-key=${OPENAI_API_KEY} |
| 5 — Disable filter | spec.ephemeral.disableProperties globs remove keys | quarkus.infinispan-client.* |
- You set
spec.ephemeral.propertieswith Quarkus/Camel keys. ComponentPropertiesRegistryadds safe defaults when components likelangchain4j-chatare detected.EphemeralConfigMergermerges all layers into the ConfigMap.- The worker pod mounts the ConfigMap at
/deployments/configand setsQUARKUS_CONFIG_LOCATIONS=file:/deployments/config/application.properties. - Quarkus LangChain4j extensions create
ChatModelCDI beans; Camellangchain4j-chat:uses the default or named bean.
spec:
deploymentMode: EPHEMERAL
ephemeral:
properties:
quarkus.langchain4j.openai.api-key: "${OPENAI_API_KEY}"
quarkus.langchain4j.openai.chat-model.model-name: "gpt-4o-mini"
secrets:
- name: openai-credentials
envFrom: true
oc create secret generic openai-credentials -n openshift-integration \
--from-literal=OPENAI_API_KEY=sk-proj-REPLACE_ME \
--from-literal=OPENAI_MODEL=gpt-4o-mini
Quarkus vs Camel property prefixes
Use the correct prefix in spec.ephemeral.properties (ephemeral) or scaffold
src/main/resources/application.properties (GitOps). Mixing prefixes silently ignores values.
| Prefix | Use for | Examples |
|---|---|---|
quarkus.* | Quarkus core, extensions, LangChain4j | quarkus.log.level, quarkus.langchain4j.openai.api-key |
camel.component.<name>.* | Camel component defaults | camel.component.kafka.brokers, camel.component.slack.webhookUrl |
camel.main.* | Camel context / route reload | camel.main.routes-reload-enabled |
quarkus.opentelemetry.* | Telemetry (Layer 3 scaffold) | quarkus.opentelemetry.tracer.exporter.otlp.endpoint |
Reference secrets with ${ENV_VAR} or ${ENV_VAR:default} — never commit real keys.
GitOps parity: the same keys belong in the scaffolded worker repo; use ESO-synced Secrets for env injection.
Credential types by integration (authType)
Catalog flows with external APIs declare an authType so the console create form shows
contextual hints. Store credentials in Kubernetes Secrets (or ESO-synced Secrets) and reference via
spec.secrets.
| authType | Integrations | Registration steps | Typical Secret keys |
|---|---|---|---|
oauth2_refresh |
Slack, Gmail, Office365, Teams, Google Workspace, Salesforce, HubSpot, LinkedIn | Create OAuth app → authorize → store refresh token in Secret | SLACK_BOT_TOKEN, GOOGLE_REFRESH_TOKEN, SALESFORCE_CLIENT_SECRET |
static_token_webhook |
Telegram, Discord, WhatsApp Business | BotFather / Developer Portal → bot token + webhook verify secret | TELEGRAM_BOT_TOKEN, DISCORD_WEBHOOK_URL, WHATSAPP_TOKEN |
api_key |
OpenAI, Anthropic, Stripe, PagerDuty, Notion, Mercado Pago | Dashboard → generate API key → oc create secret |
OPENAI_API_KEY, STRIPE_API_KEY, MP_ACCESS_TOKEN |
basic_auth |
Zendesk, Freshdesk, WooCommerce | API token or app password paired with username/email | ZENDESK_EMAIL, ZENDESK_API_TOKEN |
none |
Public timer→log demos | No Secret required | — |
Example — api_key (OpenAI)
oc create secret generic openai-credentials -n openshift-integration \
--from-literal=OPENAI_API_KEY=sk-proj-REPLACE_ME
spec:
secrets:
- name: openai-credentials
envFrom: true
ephemeral:
properties:
quarkus.langchain4j.openai.api-key: "${OPENAI_API_KEY}"
Example — static_token_webhook (Slack)
oc create secret generic slack-credentials -n openshift-integration \
--from-literal=SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXX
spec:
secrets:
- name: slack-credentials
envFrom: true
ephemeral:
properties:
camel.component.slack.webhookUrl: "${SLACK_WEBHOOK_URL}"
Production: sync the same keys from Vault via ESO — see Security — Secrets Management.
Worker image
Routes with langchain4j-chat auto-select camel-worker-ai. Pin explicitly when needed:
spec:
ephemeral:
workerImage: quay.io/maximilianopizarro/camel-worker-ai:v0.8.1
Baked into camel-worker-ai: Quarkus LangChain4j OpenAI, Ollama, Camel HTTP/Jackson (for MCP bridge calls).
GitOps custom workers: add extra Quarkus extensions to your worker pom.xml for Anthropic, Azure OpenAI, Mistral, Hugging Face, Vertex AI, Bedrock — property keys below still apply via scaffold application.properties.
Provider reference
Set provider keys under spec.ephemeral.properties. Use Secrets for API keys — never commit real keys to Git.
OpenAI / OpenAI-compatible APIs
Works with OpenAI, local proxies, and many compatible gateways via base-url.
quarkus.langchain4j.openai.api-key: "${OPENAI_API_KEY}"
quarkus.langchain4j.openai.base-url: "https://api.openai.com/v1" # optional
quarkus.langchain4j.openai.chat-model.model-name: "gpt-4o-mini"
quarkus.langchain4j.openai.chat-model.temperature: "0.7"
quarkus.langchain4j.openai.chat-model.max-completion-tokens: "2048"
quarkus.langchain4j.openai.embedding-model.model-name: "text-embedding-3-small"
Azure OpenAI
Requires quarkus-langchain4j-azure-openai in GitOps worker; or use OpenAI extension + Azure endpoint as base-url.
quarkus.langchain4j.azure-openai.api-key: "${AZURE_OPENAI_API_KEY}"
quarkus.langchain4j.azure-openai.resource-name: "my-resource"
quarkus.langchain4j.azure-openai.deployment-name: "gpt-4o"
quarkus.langchain4j.azure-openai.chat-model.temperature: "0.3"
Ollama (on-cluster or local)
Included in camel-worker-ai. Disable default OpenAI when Ollama-only:
quarkus.langchain4j.openai.chat-model.enabled: "false"
quarkus.langchain4j.ollama.base-url: "http://ollama.llm.svc:11434"
quarkus.langchain4j.ollama.chat-model.model-id: "llama3.2"
quarkus.langchain4j.ollama.chat-model.temperature: "0.3"
Example: k8s/examples/ephemeral-ai/22-ollama-local.yaml
Anthropic Claude
quarkus.langchain4j.anthropic.api-key: "${ANTHROPIC_API_KEY}"
quarkus.langchain4j.anthropic.chat-model.model-name: "claude-3-5-sonnet-20241022"
quarkus.langchain4j.anthropic.chat-model.max-tokens: "4096"
Mistral AI
quarkus.langchain4j.mistralai.api-key: "${MISTRAL_API_KEY}"
quarkus.langchain4j.mistralai.chat-model.model-name: "mistral-large-latest"
Hugging Face
quarkus.langchain4j.hugging-face.api-key: "${HF_API_TOKEN}"
quarkus.langchain4j.hugging-face.chat-model.model-id: "meta-llama/Llama-3.2-3B-Instruct"
Google Vertex AI
quarkus.langchain4j.vertex-ai.gemini.project-id: "${GCP_PROJECT_ID}"
quarkus.langchain4j.vertex-ai.gemini.location: "us-central1"
quarkus.langchain4j.vertex-ai.gemini.chat-model.model-id: "gemini-2.0-flash"
AWS Bedrock
quarkus.langchain4j.bedrock.aws.region: "${AWS_REGION:us-east-1}"
quarkus.langchain4j.bedrock.aws.access-key-id: "${AWS_ACCESS_KEY_ID}"
quarkus.langchain4j.bedrock.aws.secret-access-key: "${AWS_SECRET_ACCESS_KEY}"
quarkus.langchain4j.bedrock.chat-model.model-id: "anthropic.claude-3-5-sonnet-20241022-v2:0"
Camel also supports aws-bedrock / aws-bedrock-agent-runtime components for direct Bedrock APIs in routes.
Embeddings & RAG
quarkus.langchain4j.openai.embedding-model.model-name: "text-embedding-3-small"
# Vector store (GitOps / full worker): qdrant, elasticsearch, etc. in route YAML
Multiple models in one flow
Named Quarkus profiles map to CDI beans referenced as chatModel: "#profileName" in Camel:
quarkus.langchain4j.openai.fast.chat-model.model-name: "gpt-4o-mini"
quarkus.langchain4j.openai.fast.api-key: "${OPENAI_API_KEY}"
quarkus.langchain4j.openai.strong.chat-model.model-name: "gpt-4o"
quarkus.langchain4j.openai.strong.api-key: "${OPENAI_API_KEY}"
- to:
uri: "langchain4j-chat:analyst"
parameters:
chatModel: "#strong"
Example: k8s/examples/ephemeral-ai/21-multi-model-profiles.yaml
Per-request overrides: Camel headers CamelLangChain4jChatTemperature, CamelLangChain4jChatMaxTokens (see example 12).
Secrets cheat sheet
| Provider | Secret keys (envFrom) |
|---|---|
| OpenAI | OPENAI_API_KEY, optional OPENAI_MODEL |
| Azure OpenAI | AZURE_OPENAI_API_KEY |
| Ollama | OLLAMA_BASE_URL, OLLAMA_MODEL |
| Anthropic | ANTHROPIC_API_KEY |
| Mistral | MISTRAL_API_KEY |
| Hugging Face | HF_API_TOKEN |
| Vertex AI | GOOGLE_APPLICATION_CREDENTIALS (mount JSON key file) |
| Bedrock | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION |
| MCP bridge | OPERATOR_MCP_TOKEN, MCP_SERVER_URL |
MCP (Model Context Protocol)
The operator exposes a secured MCP bridge so flows and the console can discover and invoke tools on external MCP servers without embedding MCP client code in every worker.
Operator API
GET /api/mcp/tools?serverUrl=... | List tools (JSON-RPC tools/list) |
POST /api/mcp/tools/{toolName}/call?serverUrl=... | Invoke tool (JSON-RPC tools/call) |
Requires Authorization: Bearer <k8s-token>. Configure allowlist in Helm:
mcp:
allowedServerUrls:
- https://mcp.example.com
- http://mcp-tools.internal.svc
See Architecture — MCP Bridge.
Calling MCP from an ephemeral flow
Use HTTP from the worker to the operator Service (port 8080) with a bearer token:
oc create token default -n openshift-integration --duration=24h > /tmp/token
oc create secret generic mcp-flow-credentials -n openshift-integration \
--from-literal=OPERATOR_MCP_TOKEN="$(cat /tmp/token)" \
--from-literal=MCP_SERVER_URL=https://mcp.example.com
spec:
secrets:
- name: mcp-flow-credentials
envFrom: true
ephemeral:
workerImage: quay.io/maximilianopizarro/camel-worker-ai:v0.8.1
Examples:
k8s/examples/ephemeral-ai/23-mcp-bridge-call.yaml— list tools + invokeweb_searchk8s/examples/ephemeral-ai/24-mcp-llm-chain.yaml— MCP result → LLM synthesis
Console & Kaoto
The console plugin can call the same operator endpoints for AI-assisted design steps. Flow routes can combine:
- MCP tool call → structured context
langchain4j-chat→ natural language answer- Optional publish to Kafka / HTTP response
Validate on cluster
# Publish images (Quay login required)
podman login quay.io
VERSION_TAG=v0.8.1 ./scripts/publish-quay.sh
operator-sdk cleanup openshift-integration-operator -n openshift-integration
operator-sdk run bundle quay.io/maximilianopizarro/openshift-integration-operator-bundle:v0.8.1 \
--namespace openshift-integration --install-mode AllNamespaces --timeout 10m
# AI smoke test
oc create secret generic openai-credentials -n openshift-integration \
--from-literal=OPENAI_API_KEY=sk-proj-REPLACE_ME
oc apply -f k8s/examples/ephemeral-ai/01-openai-simple-chat.yaml
oc logs -l platform.io/flow-name=ephemeral-ai-simple-chat -n openshift-integration -f
Or run ./scripts/validate-ephemeral-ai.sh after secrets are configured.
Example index
01–20— plain-text LLM prompts (chat, CoT, sentiment, RAG-inline, …)21-multi-model-profiles.yaml— fast + strong OpenAI profiles22-ollama-local.yaml— Ollama without OpenAI key23-mcp-bridge-call.yaml— operator MCP bridge HTTP24-mcp-llm-chain.yaml— MCP + LLM pipeline