Embabel Agents Execution Modes: Focused, Closed, and Open Explained

Embabel agents support three distinct execution modes—Focused, Closed, and Open—that determine how the AgentPlatform selects, constrains, and runs agents, ranging from direct invocation to dynamic AI-driven composition.

The embabel/embabel-agent repository provides a flexible runtime for AI agents through the AgentPlatform interface. Understanding the three Embabel agents execution modes is essential for controlling the trade-off between determinism and autonomous decision-making in your applications. Each mode offers a different level of explicit control versus AI-driven flexibility, as defined in the project README (lines 126-138).

Understanding the Three Execution Modes

The AgentPlatform implementation can operate in three distinct modes that dictate how an agent (or goal) is selected and how the interaction proceeds.

Focused Mode (Direct Execution)

Use Focused mode when the caller knows exactly which agent or action to invoke. This is typical for code-driven flows such as handling incoming HTTP requests where the target agent is predetermined.

In embabel-agent-api/src/main/kotlin/com/embabel/agent/core/AgentPlatform.kt (line 32), the runAgentFrom() method enables this mode by accepting a specific Agent or AgentScope parameter. The platform executes exactly what is passed without performing any classification or selection logic against other deployed agents.

Closed Mode (Intent Classification)

Closed mode delegates intent classification to the platform. When processing an incoming event or user request, the platform scans all deployed agents via the agents() method and matches the intent against each agent's declared goals.

The platform selects the best-matching agent and restricts execution to only the actions defined within that specific agent. This provides a balance between automation and bounded, predictable behavior.

Open Mode (Dynamic Composition)

Open mode offers maximum flexibility by allowing the platform to compose a new agent on-the-fly. The platform evaluates all known goals across the entire system, then builds a custom agent combining capabilities from multiple sources to achieve the requested outcome.

This mode is the least deterministic but most powerful, as it can blend functionality from any deployed agents. The GoalChoiceApprover interface (referenced in README lines 135-139 and defined in GoalChoiceApprover.kt) lets developers restrict which goals are eligible for such dynamic composition.

Core Platform API Implementation

The AgentPlatform interface defines the primitives used across all three Embabel agents execution modes:

  • runAgentFrom(agent, …) – Executes a Focused run with an explicit agent target
  • agents() – Returns the full list of deployed agents for Closed and Open selection logic
  • deploy(agent) – Registers an agent so it can be discovered during classification

Practical Code Examples

Executing in Focused Mode

val platform: AgentPlatform = /* obtain via Spring injection */
val myAgent: Agent = /* an @Agent-annotated class */
val result = platform.runAgentFrom(
    agent = myAgent,
    processOptions = ProcessOptions(timeout = Duration.ofMinutes(5)),
    bindings = mapOf("input" to "Hello world")
).awaitResult()
println(result)

Implementing Closed Mode Selection

val platform: AgentPlatform = /* get instance */
val userIntent = "Create a calendar event for tomorrow at 9 AM"

val chosenAgent = platform.agents()
    .firstOrNull { it.goals.any { goal -> goal.matches(userIntent) } }
    ?: error("No suitable agent found")

val process = platform.createAgentProcess(
    agent = chosenAgent,
    processOptions = ProcessOptions(),
    bindings = emptyMap()
)
process.run()

Leveraging Open Mode Composition

val platform: AgentPlatform = /* obtain */
val request = "Plan a weekend trip to Paris"

val openAgent = platform.buildOpenAgentFromIntent(request)
val result = platform.runAgentFrom(openAgent).awaitResult()
println(result)

Advanced Control Mechanisms

Limiting Tool Calls in Focused Mode

The FocusedToolCallControl class in embabel-agent-api/src/main/kotlin/com/embabel/agent/prompt/element/ToolCallControl.kt (lines 35-46) implements tool-call limiting by injecting a prompt fragment that the LLM respects. This allows you to restrict how many times a specific tool may be invoked during a Focused execution.

val platform: AgentPlatform = /* ... */
val control = FocusedToolCallControl(toolName = "search", toolCalls = 3)

val process = platform.createAgentProcess(
    agent = myAgent,
    processOptions = ProcessOptions(promptContributors = listOf(control)),
    bindings = emptyMap()
)
process.run()

Restricting Goal Selection in Open Mode

To prevent unrestricted composition in Open mode, implement the GoalChoiceApprover interface. This hook allows you to filter which goals the platform may consider when dynamically building agents, ensuring that sensitive or restricted capabilities are excluded from AI-driven composition.

Summary

  • Focused mode requires explicit agent selection via runAgentFrom(), offering maximum determinism for known workflows where the caller specifies the exact agent
  • Closed mode uses agents() to classify intent against declared goals, automatically selecting the single best-matching agent while restricting actions to that agent's scope
  • Open mode dynamically composes agents from available goals across the system, constrained by GoalChoiceApprover configurations to maintain security boundaries
  • All three modes rely on the AgentPlatform interface defined in AgentPlatform.kt
  • FocusedToolCallControl provides fine-grained tool usage limits within Focused executions by injecting prompt constraints

Frequently Asked Questions

What is the difference between Closed and Open mode in Embabel agents?

Closed mode selects one existing agent based on intent classification, restricting execution to that agent's predefined actions. Open mode constructs a new agent dynamically by combining goals and actions from multiple agents across the platform, offering greater flexibility but less predictability regarding which specific actions will execute.

How do I control which agent runs in Focused mode?

Pass the specific Agent instance or AgentScope directly to the runAgentFrom() method as implemented in AgentPlatform.kt. The platform executes exactly what you provide without scanning other deployed agents or performing intent classification.

Can I limit tool usage when running an agent in Focused mode?

Yes. Use the FocusedToolCallControl class found in ToolCallControl.kt (lines 35-46) to inject prompt constraints via ProcessOptions(promptContributors). This tells the LLM it may call a specific tool only a limited number of times during the execution.

How do I restrict which goals are available for Open mode composition?

Implement the GoalChoiceApprover interface to filter candidate goals before the platform dynamically builds an agent. This acts as a security gate, preventing the composition of agents using capabilities that should not be combined in Open mode's autonomous planning process.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →