camel-agent is a blueprint-driven Apache Camel component for agent orchestration.
camel-agent-core:agent:Camel component, kernel, blueprint parser, tool registry, schema checks.camel-agent-persistence-dscope: persistence adapter usingdscope-camel-persistence(redis,jdbc,redis_jdbc).camel-agent-spring-ai: Spring AI multi-provider gateway (openai,anthropic,vertex gemini).camel-agent-twilio: Twilio-facing telephony adapter built on provider-neutral SIP/outbound-call contracts from core.camel-agent-starter: Spring Boot auto-configuration.samples/agent-support-service: runnable Camel Main support sample.
Core platform capabilities:
- Blueprint-driven agents defined in Markdown with tool schemas, realtime metadata, AGUI pre-run configuration, and JSON route templates.
- Camel-native tool execution through local routes, Kamelets, MCP-discovered tools, and A2A peer agents.
- Multi-plan catalog routing with versioned blueprints, sticky conversation plan selection, and legacy single-blueprint fallback.
- Persistence-backed conversations, task state, audit trail projection, and optional Spring AI chat-memory integration.
- Browser AGUI and realtime voice support with session init, transcript event handling, relay integration, and runtime refresh hooks.
Recent additions:
- Blueprint static resources can load Markdown, PDF, local file, classpath, and HTTP(S) content into chat and realtime instruction context.
- Route-driven agent session invocation now has a structured contract in core via
AgentSessionServiceandAgentSessionInvokeProcessor. - Realtime voice runtime now also supports SIP-style ingress routes, browser session seeding, and route-driven session context patches.
- Outbound support calling uses provider-neutral telephony contracts in core with a Twilio adapter module and sample support-call flow.
- Java:
21 - Camel:
4.15.0 - Jackson:
2.20.0 - JUnit:
5.10.2 - DScope persistence:
1.1.0 - DScope AGUI:
1.1.0
- Changelog:
docs/CHANGELOG.md - Product guide:
docs/PRODUCT_GUIDE.md - Architecture:
docs/architecture.md - Development guide:
docs/DEVELOPMENT_GUIDE.md
mvn -q test
mvn clean installInstall local AGUI and persistence artifacts, then run this project with local profile:
./scripts/bootstrap-local-dscope-deps.shThis activates -Pdscope-local for local DScope dependency alignment used by runtime modules and samples.
agent:agentId?blueprint=classpath:agents/support/agent.md&persistenceMode=redis_jdbc&strictSchema=true&timeoutMs=30000&streaming=true
- Blueprint system instructions plus fenced YAML sections for tools, realtime settings, AGUI pre-run behavior, and resource declarations.
- Tool backends spanning direct Camel routes, Kamelets, MCP tool discovery, A2A remote agents, and generated JSON route templates.
- Multi-plan routing with
agent.agents-config, per-requestplanNameandplanVersion, and persisted conversation plan selection. - Stateful runtime behavior covering conversation history, task state, audit events, archive streams, and optional Spring AI chat memory.
- UI and integration surfaces including AGUI, browser realtime, HTTP/SSE A2A endpoints, admin/runtime refresh endpoints, and SIP-style voice entrypoints.
Any Camel route can invoke the runtime through either the raw agent: contract or the structured session façade.
Raw endpoint contract:
agent.conversationIdis the durable backend session key.- omit
agent.conversationIdto create a new conversation. - reuse the same
agent.conversationIdto continue the conversation.
Minimal route form:
from("direct:agent-call")
.setBody(simple("${body[prompt]}"))
.setHeader("agent.conversationId", simple("${body[conversationId]}"))
.setHeader("agent.planName", simple("${body[planName]}"))
.setHeader("agent.planVersion", simple("${body[planVersion]}"))
.to("agent:support?plansConfig={{agent.agents-config}}&blueprint={{agent.blueprint}}");Structured session contract:
camel-agent-corenow providesAgentSessionRequest,AgentSessionResponse,AgentSessionService, andAgentSessionInvokeProcessor.conversationId,sessionId, andthreadIdare normalized so ordinary Camel routes can use either UI-style or backend-style identifiers.- arbitrary
paramsare preserved as exchange properties underagent.session.paramsand returned in the structured response.
For the canonical request/response payloads, see docs/PRODUCT_GUIDE.md and docs/DEVELOPMENT_GUIDE.md.
Runtime can resolve agents from a catalog instead of a single blueprint:
agent:
agents-config: classpath:agents/agents.yaml
blueprint: classpath:agents/support/agent.md # optional legacy fallbackCatalog behavior:
- multiple named plans
- multiple versions per plan
- one default plan
- one default version per plan
- sticky conversation selection persisted as
conversation.plan.selected
Request entrypoints can pass planName and planVersion. When omitted, runtime uses sticky selection for the conversation, then catalog defaults.
Camel Agent now integrates camel-a2a-component as a first-class protocol bridge.
Runtime config:
agent:
runtime:
a2a:
enabled: true
public-base-url: http://localhost:8080
exposed-agents-config: classpath:agents/a2a-exposed-agents.yamlExposed-agent config is separate from agents.yaml. It maps public A2A identities to local plans:
agents:
- agentId: support-ticket-service
name: Support Ticket Service
defaultAgent: true
planName: ticketing
planVersion: v1Inbound endpoints:
POST /a2a/rpcGET /a2a/sse/{taskId}GET /.well-known/agent-card.json
Outbound behavior:
- blueprint tools can target
a2a:endpoints - runtime persists remote task/conversation correlation
- audit trail records outbound/inbound A2A transitions
For shared-service behavior and task/session model details, see docs/architecture.md and docs/DEVELOPMENT_GUIDE.md.
Default persistence mode is redis_jdbc (Redis fast path + JDBC source-of-truth behavior inherited from camel-persistence).
Core persistence responsibilities include:
- conversation event history
- task snapshots
- dynamic route metadata
- persisted plan-selection state
- audit projection data
- optional conversation archive streams
Audit trail control:
- set
agent.audit-granularity(default:info) none: persist no audit eventsinfo: persist process steps onlyerror: persist process steps and include error payload data for error eventsdebug: persist process steps with full payloads and metadata
By default, audit trail uses the same persistence store as context/state. To store audit trail in a separate JDBC backend, configure either:
agent:
audit:
backend: jdbc
jdbc:
url: jdbc:postgresql://localhost:5432/agent_audit
username: agent_audit_user
password: ${AGENT_AUDIT_DB_PASSWORD}
driver-class-name: org.postgresql.DriverOr namespaced equivalent:
agent:
audit:
persistence:
backend: jdbc
jdbc:
url: jdbc:postgresql://localhost:5432/agent_auditConversation archive note:
- archive persistence is transcript-focused and separate from the main audit stream
- use it for replay and transcript UX scenarios, not as the primary source of task or plan-selection state
Implemented support:
DscopeChatMemoryRepositorypersists Spring AI chat messages todscope-camel-persistence.SpringAiMessageSerdehandles serialization/deserialization forUSER,SYSTEM,ASSISTANT(including tool calls), andTOOLmessages.- Starter auto-config creates:
ChatMemoryRepositorybacked by DScope persistenceMessageWindowChatMemorywith configurable window
Starter properties:
agent.chat-memory-enabled(default:true)agent.chat-memory-window(default:100)
Distributed task ownership is implemented via persistence-backed lease locks (flowType=agent.task.lock):
tryClaimTask(taskId, ownerId, leaseSeconds)uses optimistic append semantics.resumeTask(taskId)claims lease before processing and releases after completion.- Conflicting resume attempts return a lock message instead of double-processing.
Starter properties:
agent.task-claim-owner-id(optional; defaults to generated node id)agent.task-claim-lease-seconds(default:120)
mvn -f samples/agent-support-service/pom.xml -DskipTests compile exec:javaOr run with local hidden secrets file (samples/agent-support-service/.agent-secrets.properties):
samples/agent-support-service/run-sample.shSee sample-specific usage and test guidance in:
samples/agent-support-service/README.md
For local no-key A2A demo runs, the sample also includes:
io.dscope.camel.agent.samples.DemoA2ATicketGateway
Use it to simulate support-agent -> A2A ticket-service -> local ticket route behavior without a live model backend:
./mvnw -q -f samples/agent-support-service/pom.xml \
-Dagent.runtime.spring-ai.gateway-class=io.dscope.camel.agent.samples.DemoA2ATicketGateway \
-Dagent.runtime.routes-include-pattern=classpath:routes/kb-search.camel.yaml,classpath:routes/kb-search-json.camel.xml,classpath:routes/ticket-service.camel.yaml,classpath:routes/ag-ui-platform.camel.yaml,classpath:routes/admin-platform.camel.yaml \
exec:javasamples/agent-support-service/src/main/resources/application.yaml configures runtime provider routing:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
base-url: https://api.openai.com
agent:
runtime:
ai:
mode: spring-ai
spring-ai:
provider: openai # openai | gemini | claude
api-mode: ${AGENT_OPENAI_API_MODE:chat}
model: gpt-5.4
temperature: 0.2
max-tokens: 800
openai:
# Supported values:
# - chat (default): Spring AI OpenAI Chat Completions
# - responses-http: reserved (not yet implemented)
# - responses-ws: delegated to pluggable OpenAiResponsesGateway implementation
responses-ws:
endpoint-uri: wss://api.openai.com/v1/responses
model: gpt-5.4Notes:
- OpenAI in this gateway uses Spring AI OpenAI Chat client (
chatmode). responses-httpis a planned mode and currently returns a terminal guidance message.responses-wsis routed through a pluggableOpenAiResponsesGateway; if no plugin is wired, the gateway returns a terminal guidance message.- The sample runtime also enables A2A by default through
agent.runtime.a2a.enabled=trueand exposes the ticket service throughsupport.ticket.manage. - Gemini uses Spring AI Vertex Gemini client and requires:
agent.runtime.spring-ai.gemini.vertex.project-idagent.runtime.spring-ai.gemini.vertex.location
- Claude uses Spring AI Anthropic client (
/v1/messages).
Before running the sample with external providers, verify network and credentials:
nc -vz api.openai.com 443
curl -I https://api.openai.com/v1/models
curl https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"401from OpenAI endpoints usually means missing/invalid API key in the current shell.421with the OpenAI welcome body indicates endpoint/path mismatch (request hitting API root instead of chat endpoint).- If runtime behavior looks stale after code changes, rebuild/install local snapshots from the repo root.
- If tests are unexpectedly skipped, verify
maven.test.skipis not enabled in environment/system properties.
For detailed sample troubleshooting and commands, see:
samples/agent-support-service/README.md
Spring Framework dependency remediation was applied for known spring-core vulnerabilities (including annotation detection issues reported against older releases).
What was changed:
- centralized Spring Framework version management via
spring.framework.version - pinned
org.springframework:spring-corein rootdependencyManagement - updated
camel-agent-spring-aito consume managed Spring version
Current resolved baseline:
org.springframework:spring-core:6.1.21
Verification commands:
mvn -U -f camel-agent-spring-ai/pom.xml -DskipTests dependency:tree -Dincludes=org.springframework:spring-core
mvn -U -f camel-agent-starter/pom.xml -DskipTests dependency:tree -Dincludes=org.springframework:spring-core
mvn -U -f pom.xml verifySample integration tests verify route selection and context carry-over behavior:
- first prompt asks for knowledge base help, route/tool selected:
kb.search - second prompt asks to file a ticket, route/tool selected:
support.ticket.manage - second-turn LLM evaluation context includes first-turn KB result
- negative case: direct ticket prompt without prior KB turn does not inject KB context
Run:
mvn -f samples/agent-support-service/pom.xml -Dtest=SpringAiAuditTrailIntegrationTest testagent.md now supports a jsonRouteTemplates section for safe dynamic route generation.
Runtime behavior:
- templates are parsed from blueprint YAML blocks
- each template is exposed as a callable tool (via
toolName) - LLM returns only template parameters
- runtime expands placeholders into Camel JSON DSL, validates it, dynamically loads route, and executes it
- dynamic route metadata is persisted through existing
DynamicRouteStatepersistence
See docs/PRODUCT_GUIDE.md for field-level template structure and the sample blueprint for a concrete example.
Blueprint tools entries with endpointUri starting with mcp: are treated as MCP service definitions.
Runtime behavior:
- on agent startup, runtime calls MCP
tools/listfor each configuredmcp:endpoint - discovered MCP tools are merged into the runtime tool registry used for LLM evaluation
- MCP tool execution uses MCP
tools/callwith{ name, arguments } - MCP discovery payload is written to audit as
mcp.tools.discovered(full payload available indebuggranularity)
See docs/PRODUCT_GUIDE.md for the seed-tool shape and sample blueprint examples.
Execution-facing fields in agent.md can be tokenized and resolved at runtime.
Supported token forms:
{{key}}{{key:defaultValue}}${NAME}${NAME:defaultValue}
Typical use cases:
- environment-specific endpoint hosts
- secret tokens passed in endpoint query strings or headers-derived URIs
- runtime-selected
agent:endpoint targets for AGUI or route/session entrypoints
Example:
tools:
- name: support.mcp
endpointUri: mcp:https://{{agent.crm.host}}/mcp?token=${CRM_TOKEN}Critical execution-target fields now fail fast if a placeholder remains unresolved at runtime. See docs/PRODUCT_GUIDE.md for the exact field list and behavior.
Blueprints can declare a resources section to stage static reference material into agent context.
Supported resource locations:
classpath:file:- plain file path
http:https:
Supported content handling:
- Markdown and plain text are injected as text.
- PDF documents are resolved through Camel PDF extraction.
- resources can target
chat,realtime, or both viaincludeIn.
Runtime behavior:
- resource text is appended to chat instructions during kernel construction.
- realtime session init seeds resource-backed instruction context for browser and SIP voice sessions.
- runtime refresh re-resolves blueprint resources and can push updated context to active conversations.
See docs/PRODUCT_GUIDE.md for the full resources[] schema and docs/DEVELOPMENT_GUIDE.md for implementation details.
samples/agent-support-service uses AGUI component runtime routes and a built-in UI page:
- open
http://localhost:8080/agui/ui - frontend supports AGUI text transport switch:
POST /agui/agent(POST+SSE)WS /agui/rpc(AGUI over WebSocket)
- backend responds with AGUI events for the selected transport; frontend renders assistant output from AGUI message content events
/agui/stream/{runId}is available for split-transport clients
For run commands and endpoint examples, see samples/agent-support-service/README.md.
Realtime note:
POST /realtime/session/{conversationId}/eventsupports route-driven session-context updates aftertranscript.finalrouting.POST /realtime/session/{conversationId}/initseeds pre-conversation agent context from blueprint metadata before the first user turn.- Agent/tool routes can return a patch via exchange header/property (
realtimeSessionUpdate, aliases:realtime.session.update,sessionUpdate) or assistant JSON body (realtimeSessionUpdate,realtimeSession,sessionUpdate). - Patch is deep-merged into browser session context for the same
conversationId; next/realtime/session/{conversationId}/tokenuses merged context.
For seeded session fields, realtime configuration properties, and sample endpoint details, see samples/agent-support-service/README.md and docs/PRODUCT_GUIDE.md.
Voice UX and transcript updates (sample frontend):
- Single dynamic voice toggle button (
Start Voice/Stop Voice) with idle/live/busy states. - Runtime-selectable pause profiles for VAD (
Fast=800ms,Normal=1200ms,Patient=1800ms) applied to relay and WebRTC session config. - Pause milliseconds shown in both listening status text and the pause label (
Pause (<ms>ms)). - Mobile behavior uses icon-only voice button while preserving dynamic
titleandaria-labeltext. - WebRTC transcript log panel includes input/output transcript lines and clear-log action.
- Voice output transcript de-duplication ensures one final assistant transcript entry per completed output (with spacing preserved).
- Collapsible
Instruction seed (debug)panel shows the current pre-conversation instruction context; it auto-opens when transport is switched to WebRTC (and on initial load when already in WebRTC mode).
SIP and telephony note:
POST /sip/adapter/v1/session/{conversationId}/start,/turn, and/endreuse the same realtime processors and route agent flow.- outbound support calling uses provider-neutral
OutboundSipCallRequest/OutboundSipCallResult/SipProviderClientcontracts in core. - the sample uses
support.call.outboundplusSupportOutboundCallProcessorto place a provider call and return correlation data immediately.
The kernel supports control messages for orchestration testing:
task.async <checkpoint>: creates a persisted task inWAITINGstate.route.instantiate <templateId>: creates a dynamic route lifecycle record (CREATED -> STARTED).AgentKernel.resumeTask(taskId): resumes and completes waiting tasks (RESUMED -> FINISHED).
