Agents

Understand agents as background processes in Elixir.

We'll cover the following

Introduction

An agent is a background process that maintains a state. We can access this state at different places within a process, within a node, or across multiple nodes. A function sets the initial state we pass when we start the agent.

We can interrogate the state using Agent.get, passing it the agent descriptor and a function. The agent runs the function on its current state and returns the result. We can also use Agent.update to change the state held by an agent. As with the get operator, we pass in a function. Unlike with get, the function’s result becomes the new state.

Example

Here’s a bare-bones example. We start an agent whose state is the integer 0. We then use the identity function, &(&1), to return that state. Calling Agent.update with &(&1+1) increments the state, as verified by a subsequent get.

iex> { :ok, count } = Agent.start(fn -> 0 end) 
{:ok, #PID<0.69.0>}
iex> Agent.get(count, &(&1))
0
iex> Agent.update(count, &(&1+1)) 
:ok
iex> Agent.update(count, &(&1+1)) 
:ok
iex> Agent.get(count, &(&1)) 
2

In the previous example, the variable count holds the agent process’s PID. We can also give agents a local or global name and access them using this name. In this case, we exploit the fact that an uppercase bare word in Elixir is converted into an atom with the prefix Elixir., so when we say Sum it’s actually the atom :Elixir.Sum.

iex> Agent.start(fn -> 1 end, name: Sum) 
{:ok, #PID<0.78.0>}
iex> Agent.get(Sum, &(&1))
1
iex> Agent.update(Sum, &(&1+99)) 
:ok
iex> Agent.get(Sum, &(&1))
100

The following example shows a more typical use. The Frequency module maintains a list of word-frequency pairs in a map. The dictionary itself is stored in an agent named after the module.

This is all initialized with the start_link function, which presumably is invoked during application initialization.

Get hands-on with 1400+ tech skills courses.