The AgentProcess

An AgentProcess is created every time an agent is run. It has a unique id.

Execution Modes

Embabel supports two execution modes for agent processes, controlled by the embabel.agent.platform.process-type property.

SimpleAgentProcess (Default)

SimpleAgentProcess is the default execution mode. On each planning tick it selects the single best action from the current plan and runs it to completion before replanning.

This sequential approach is predictable and easy to reason about: actions never run in parallel and the blackboard is always in a consistent state when the next action begins.

ConcurrentAgentProcess

ConcurrentAgentProcess extends SimpleAgentProcess and runs all currently achievable actions in parallel on each planning tick.

Instead of picking one action per tick, it finds every action in the plan that is achievable given the current world state and launches them concurrently using the platform’s Asyncer abstraction (backed by Spring’s managed task executor with virtual threads). Once all launched actions have completed the process replans, and the cycle repeats.

This is useful when an agent has independent sub-tasks that can proceed simultaneously— for example, enriching multiple data items in parallel, or running several analysis steps whose outputs do not depend on each other.

Activating ConcurrentAgentProcess

Set the following property in your application configuration:

embabel:
  agent:
    platform:
      process-type: CONCURRENT

or in application.properties:

embabel.agent.platform.process-type=CONCURRENT

The default value is SIMPLE.

Replanning in Concurrent Mode

Both SimpleAgentProcess and ConcurrentAgentProcess support ReplanRequestedException, which an action can throw to signal that the agent should update the blackboard and replan before proceeding.

In ConcurrentAgentProcess, multiple concurrently running actions may throw ReplanRequestedException at the same time. When this happens only the first request is honoured—its blackboard updates are applied and the triggering action is blacklisted for the next planning cycle to prevent an immediate infinite loop. The remaining requests are silently dropped, as they ran in a context that is about to be replanned anyway.

The blacklist is cleared automatically after a successful planning cycle. If no plan can be found while a blacklist is active, the blacklist is cleared and planning is retried, ensuring the agent does not become permanently stuck.

Choosing an Execution Mode

ModeWhen to useTrade-offs
SIMPLEMost agents; sequential pipelines; when action order mattersPredictable; easier to debug; no concurrency overhead
CONCURRENTIndependent parallel sub-tasks; fan-out/fan-in patterns; throughput-sensitive workloadsHigher throughput; requires actions to be safe to run concurrently against a shared blackboard

ProcessOptions

Agent processes can be configured with ProcessOptions.

ProcessOptions controls:

  • contextId: An identifier of any existing context in which the agent is running.
  • blackboard: The blackboard to use for the agent. Allows starting from a particular state.
  • test: Whether the agent is running in test mode.
  • verbosity: The verbosity level of the agent. Allows fine grained control over logging prompts, LLM returns and detailed planning information
  • control: Control options, determining whether the agent should be terminated as a last resort. EarlyTerminationPolicy can based on an absolute number of actions or a maximum budget.
  • Delays: Both operations (actions) and tools can have delays. This is useful to avoid rate limiting.
  • ephemaral: blocks Agent Process from persisting in Agent Process Repository and from spawning child processes (light-weighted agent process)
  • toolCallContext: Out-of-band metadata (e.g., auth tokens, tenant IDs, correlation IDs) passed to all tool invocations during the process. This context propagates through the entire tool pipeline—including decorator chains and MCP tools—without being exposed to the LLM. Set via withToolCallContext():
var processOptions = new ProcessOptions()
    .withToolCallContext(Map.of(
        "authToken", bearerToken,
        "tenantId", tenantId
    ));

See /reference/tools#tool-call-context for how tools receive this context.

ExecutionContextProcessContextProcessContext(Process-scoped services)OperationContextOperationContext(Operation execution context)ProcessContext->OperationContextprovidesLlmOperationsLlmOperations(LLM backend services)ProcessContext->LlmOperationsprovidesActionContextActionContext(Action-specific context)OperationContext->ActionContextspecializes toPromptRunnerPromptRunner(LLM interaction API)OperationContext->PromptRunnercreatesBlackboardBlackboard(Shared state store)OperationContext->BlackboardaccessesIoBindingIoBinding(Input/output binding)OperationContext->IoBindingmanagesActionContext->PromptRunnerenhancesToolGroupRequirementToolGroupRequirement(Tool dependency)ActionContext->ToolGroupRequirementdeclaresToolObjectToolObject(@Tool annotated object)ActionContext->ToolObjectcreates from domain objectsActionContext->Blackboardreads/writesPromptRunner->LlmOperationsdelegates toLlmOptionsLlmOptions(Model configuration)PromptRunner->LlmOptionsconfigured byThinkingPromptRunnerOperationsThinkingPromptRunnerOperations(Thinking-aware operations)PromptRunner->ThinkingPromptRunnerOperationswithThinking()ToolGroupToolGroup(Coherent tool set)PromptRunner->ToolGroupwith tool groupsPromptRunner->ToolObjectwith tool objectsPromptContributorPromptContributor(Prompt element)PromptRunner->PromptContributorwith contributorsMessageMessage(Conversation element)PromptRunner->Messagewith messagesThinkingResponseThinkingResponse(Result + thinking blocks)ThinkingPromptRunnerOperations->ThinkingResponsereturnsToolGroupRequirement->ToolGrouprequiresBlackboard->IoBindingstores via

Was this page helpful?

Share