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 worker application.properties
  • spec.secrets — Kubernetes Secrets injected as env vars (envFrom: true) or volume mounts
  • spec.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-inBaked into the Quay worker imagecamel.main.routes-reload-enabled
2 — Component-requiredComponentPropertiesRegistry from detected route schemescamel.component.kafka.brokers=${KAFKA_BOOTSTRAP:localhost:9092}
3 — Scaffold-generatedOTel endpoint, resilience from spec.resiliencequarkus.opentelemetry.enabled=true
4 — User overridesspec.ephemeral.propertiesquarkus.langchain4j.openai.api-key=${OPENAI_API_KEY}
5 — Disable filterspec.ephemeral.disableProperties globs remove keysquarkus.infinispan-client.*
  1. You set spec.ephemeral.properties with Quarkus/Camel keys.
  2. ComponentPropertiesRegistry adds safe defaults when components like langchain4j-chat are detected.
  3. EphemeralConfigMerger merges all layers into the ConfigMap.
  4. The worker pod mounts the ConfigMap at /deployments/config and sets QUARKUS_CONFIG_LOCATIONS=file:/deployments/config/application.properties.
  5. Quarkus LangChain4j extensions create ChatModel CDI beans; Camel langchain4j-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, LangChain4jquarkus.log.level, quarkus.langchain4j.openai.api-key
camel.component.<name>.*Camel component defaultscamel.component.kafka.brokers, camel.component.slack.webhookUrl
camel.main.*Camel context / route reloadcamel.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)
OpenAIOPENAI_API_KEY, optional OPENAI_MODEL
Azure OpenAIAZURE_OPENAI_API_KEY
OllamaOLLAMA_BASE_URL, OLLAMA_MODEL
AnthropicANTHROPIC_API_KEY
MistralMISTRAL_API_KEY
Hugging FaceHF_API_TOKEN
Vertex AIGOOGLE_APPLICATION_CREDENTIALS (mount JSON key file)
BedrockAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
MCP bridgeOPERATOR_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 + invoke web_search
  • k8s/examples/ephemeral-ai/24-mcp-llm-chain.yaml — MCP result → LLM synthesis
Note: The MCP bridge currently returns stub responses for off-cluster MCP servers until JSON-RPC transport is fully implemented. The API contract, auth, and allowlist are production-ready; wire your MCP server URL to test end-to-end once transport is enabled.

Console & Kaoto

The console plugin can call the same operator endpoints for AI-assisted design steps. Flow routes can combine:

  1. MCP tool call → structured context
  2. langchain4j-chat → natural language answer
  3. 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

  • 0120 — plain-text LLM prompts (chat, CoT, sentiment, RAG-inline, …)
  • 21-multi-model-profiles.yaml — fast + strong OpenAI profiles
  • 22-ollama-local.yaml — Ollama without OpenAI key
  • 23-mcp-bridge-call.yaml — operator MCP bridge HTTP
  • 24-mcp-llm-chain.yaml — MCP + LLM pipeline