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

> Explore Embabel agents execution modes: Focused, Closed, and Open. Understand how each mode dictates agent selection, constraint, and execution for direct or dynamic AI-driven composition.

- Repository: [Embabel/embabel-agent](https://github.com/embabel/embabel-agent)
- Tags: deep-dive
- Published: 2026-08-09

---

**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`](https://github.com/embabel/embabel-agent/blob/main/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`](https://github.com/embabel/embabel-agent/blob/main/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

```kotlin
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

```kotlin
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

```kotlin
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`](https://github.com/embabel/embabel-agent/blob/main/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.

```kotlin
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`](https://github.com/embabel/embabel-agent/blob/main/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`](https://github.com/embabel/embabel-agent/blob/main/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`](https://github.com/embabel/embabel-agent/blob/main/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.