Browse Clojure Foundations for Java Developers

Agents

Agents manage asynchronous, independent state changes: queue actions with send/send-off and handle failures explicitly.

Agents are for asynchronous, independent state changes. Each agent has a value plus a queue of actions. Actions are applied serially per agent, but run asynchronously on thread pools.

Use agents when:

  • updates should happen in the background (logging, metrics aggregation, caches)
  • state updates are independent (no multi-agent transaction/invariant)

Create and Read

1(def stats (agent {:requests 0 :errors 0}))
2
3@stats ; => {:requests 0, :errors 0}

Update with send

send queues an action (a function) to apply to the agent’s current state:

1(send stats update :requests inc)
2(send stats update :errors inc)

Actions are functions of the current state → new state.

send vs send-off

  • send is intended for CPU-bound actions.
  • send-off is intended for potentially blocking actions (I/O).

Waiting and Errors

1(await stats)           ; wait for queued actions to finish
2(agent-error stats)     ; => exception or nil

If an action throws, the agent enters a failed state and stops processing future actions until you handle it (for example with restart-agent).

Knowledge Check: Agents

### What does `send` do? - [x] Queues an action function to run asynchronously and update the agent’s state. - [ ] Mutates the agent immediately on the current thread. - [ ] Starts a Java thread per update. - [ ] Updates multiple agents atomically. > **Explanation:** `send` enqueues a function to be applied to the agent’s state. Actions are processed serially for that agent. ### When should you prefer `send-off` over `send`? - [x] When the action may block (I/O, long waits), so you don’t starve the CPU-bound pool. - [ ] When you need atomic updates across two values. - [ ] When you need a synchronous update. - [ ] When you want retries like `swap!`. > **Explanation:** `send-off` uses a separate pool intended for blocking work. It’s a safety/performance choice, not a semantic one. ### What happens if an agent action throws an exception? - [x] The agent enters an error state and stops processing queued actions until handled. - [ ] The exception is ignored and actions continue. - [ ] The agent automatically retries the action until it succeeds. - [ ] The JVM exits. > **Explanation:** Agent failures are explicit. Check with `agent-error` and recover with `restart-agent` when appropriate.
Revised on Friday, April 24, 2026