How to Use Worker Pools for High-Throughput Agent Workloads in Jido

Jido provides a Poolboy-based worker pool abstraction via Jido.Agent.WorkerPool that maintains pre-initialized agents for reuse, eliminating expensive startup costs during high-throughput scenarios.

The agentjido/jido repository ships with a robust worker pool implementation designed specifically for agent workloads. When an agent's initialization is expensive—such as loading machine learning models or establishing network connections—creating a new process per request creates unacceptable latency. Jido's worker pool solves this by keeping a set of warm Jido.AgentServer processes ready for immediate checkout.

Architecture Overview

Jido's pooling system consists of several coordinated components:

Component Role Key Source
Jido.Agent.WorkerPool Provides transaction-style API (with_agent/4, call/4, cast/4) and low-level checkout/3 / checkin/3 operations lib/jido/agent/worker_pool.ex
Pool Configuration Declared via :agent_pools option with Poolboy settings (size, max_overflow, strategy) lib/jido/agent/worker_pool.ex (docs)
Jido.Config.Defaults Supplies default timeouts for checkout and calls lib/jido/config/defaults.ex
Jido.agent_pool_name/2 Generates unique module names for pool supervision lib/jido.ex
Jido.AgentServer The actual GenServer implementation running inside each pool worker lib/jido/agent_server.ex

When a Jido instance starts, the supervisor calls WorkerPool.build_pool_child_spec/4 to create Poolboy child specs for every pool declared in :agent_pools. Each worker in the pool is an instance of Jido.AgentServer initialized with the specified agent module.

Configuring Worker Pools

Define pools in your application supervision tree using the :agent_pools option:

children = [
  {Jido,
   name: MyApp.Jido,
   agent_pools: [
     # High-throughput search pool: 8 permanent workers, 4 overflow, LIFO checkout

     {:fast_search, MyApp.Agents.SearchAgent,
      size: 8, max_overflow: 4, strategy: :lifo},

     # Planner pool: 4 workers with FIFO ordering

     {:planner, MyApp.Agents.PlannerAgent,
      size: 4, strategy: :fifo}
   ]}
]

Configuration parameters:

  • size – Number of agents kept permanently alive (default: 5)
  • max_overflow – Temporary workers created when pool is exhausted (default: 0)
  • strategy:lifo (default) or :fifo checkout order
  • worker_opts – Additional options passed to Jido.AgentServer.start_link/1

Default timeouts are defined in Jido.Config.Defaults via worker_pool_checkout_timeout_ms/0 and worker_pool_call_timeout_ms/0, but you can override these per-call using the :timeout (checkout) or :call_timeout (signal) options.

Using the Pool API

The Jido.Agent.WorkerPool module provides three high-level patterns for executing work against pooled agents.

Transaction-Style Execution with with_agent/4

Use with_agent/4 when you need to execute multiple operations against the same agent or require complex logic:

defmodule MyApp.BatchProcessor do
  @jido MyApp.Jido
  @pool :planner

  def process_batch(batch) do
    Jido.Agent.WorkerPool.with_agent(@jido, @pool, fn pid ->
      Enum.each(batch, fn item ->
        # Reuse the same checked-out agent for multiple signals

        Jido.AgentServer.call(pid, {:plan, item})
      end)
    end)
  end
end

The with_agent/4 function guarantees check-in even if the supplied function raises an exception, as it runs inside :poolboy.transaction/3.

Synchronous Calls with call/4

For single-shot synchronous operations, use call/4 which handles checkout, signal delivery, and check-in automatically:

defmodule MyApp.Search do
  @jido MyApp.Jido
  @pool :fast_search

  def search(query) do
    signal = {:search, query}
    # Automatically checks out agent, sends signal, waits for reply, checks in

    {:ok, results} = Jido.Agent.WorkerPool.call(@jido, @pool, signal)
    results
  end
end

This corresponds to the implementation in lib/jido/agent/worker_pool.ex lines 101-129.

Asynchronous Casts with cast/4

For fire-and-forget operations where you don't need a response:

defmodule MyApp.Notifications do
  @jido MyApp.Jido
  @pool :fast_search

  def notify(event) do
    # Checks out worker, sends async signal, immediately checks in

    Jido.Agent.WorkerPool.cast(@jido, @pool, {:notify, event})
    :ok
  end
end

The cast/4 function checks out the worker, sends the asynchronous signal, and immediately checks the worker back in, as implemented in lines 130-152 of the worker pool module.

Error Handling and Guarantees

Jido's worker pools provide several safety guarantees for production workloads:

  • Supervised workers: Each agent process is supervised by the top-level Jido supervisor. If a worker crashes, Poolboy discards the crashed process and spawns a fresh replacement.
  • State persistence: Agent state persists across checkouts unless the worker crashes. For request-specific isolation, pass request data via signals rather than storing it in the agent's internal state.
  • Guaranteed check-in: The with_agent/4 function ensures the agent is returned to the pool even if the supplied function raises an exception, preventing pool exhaustion due to leaked workers.

Monitoring Pool Status

For debugging and metrics collection, query the current state of any pool:

status = Jido.Agent.WorkerPool.status(MyApp.Jido, :fast_search)
IO.inspect(status)

# => %{state: :ready, available: 8, overflow: 0, checked_out: 0}

The status/2 function forwards to :poolboy.status/1 and returns a map showing available workers, overflow count, and checked-out count. This is implemented in lib/jido/agent/worker_pool.ex lines 199-207.

Summary

  • Worker pools in Jido use Jido.Agent.WorkerPool to maintain pre-initialized agents via Poolboy, eliminating expensive startup costs.
  • Configuration happens through the :agent_pools option when starting your Jido instance, specifying pool size, overflow limits, and checkout strategy.
  • High-level APIs include with_agent/4 for complex transactions, call/4 for synchronous requests, and cast/4 for asynchronous fire-and-forget operations.
  • Safety guarantees ensure crashed workers are replaced and agents are always returned to the pool, even when errors occur.
  • Monitoring via status/2 provides visibility into pool utilization for capacity planning.

Frequently Asked Questions

What is the difference between call/4 and with_agent/4 in Jido worker pools?

call/4 is optimized for single-shot synchronous operations—it checks out an agent, sends one signal, waits for the response, and immediately returns the worker to the pool. with_agent/4 provides a transaction-style API where you receive the raw pid of a checked-out agent and can execute multiple operations or complex logic before the worker is automatically returned to the pool when your function completes or raises an exception.

How does Jido handle crashed workers in a pool?

Each worker in a Jido pool is supervised by the top-level Jido supervisor. If a worker process crashes during execution, Poolboy detects the crash, discards the failed process, and spawns a fresh replacement worker. This ensures that your pool maintains the configured capacity without manual intervention, though any state stored in the crashed worker is lost.

Can I customize timeouts for worker checkout and signal execution?

Yes. Jido defines default timeouts in Jido.Config.Defaults via worker_pool_checkout_timeout_ms/0 and worker_pool_call_timeout_ms/0. You can override these per-call by passing the :timeout option for checkout duration or the :call_timeout option for signal execution duration to call/4, cast/4, or with_agent/4.

What monitoring capabilities are available for Jido worker pools?

Jido exposes pool statistics through Jido.Agent.WorkerPool.status/2, which returns a map containing the pool state (:ready), number of available workers, overflow count, and currently checked-out workers. This function interfaces directly with :poolboy.status/1 and is useful for debugging connection leaks, capacity planning, and monitoring pool utilization in production environments.

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 →