Agents
Agents operate within the simulator and are permitted to take actions in an environment
. It is important to understand that each agent can act independently and not every agent needs to take actions in at every step.
The agent
field allows you to specify agents within the simulator and map them to an address
for each environment. Agents also require a source
(read more here), which defines how the agent functions.
Each agent should specify the following itemsadvanced in the configuration:
address
(required)agentType
(required)environments
(required)metrics
(optional)settings
(optional)source
(optional)strategy
(optional)
address is the primary identifier for the agent throughout the simulation. This MUST be unique across all agents. It should be a wallet address.
agentType specifies the type of agent you want to create. Currently, we support mev
and regular
. mev
agents have distinct behaviors, which you can read more about here.
environments indicates in which environments the agent is allowed to act. You can also specify an address specific to each environment. Additionally, you can specify a wallet
to set the initial token holdings of the agent in that environment. See the example below for implementation details.
metrics provides more information on metrics here.
settings is a simple key-value list that helps modularize agents. This can include any value, which will be passed into the agent class.
source is the location of the Python file that implements the AgentInterface
. Read more about sources here.
strategy specifies the source of the strategy you want the agent to use. See below for more details on this relationship.
Strategy
Agents have a close relationship with strategies, which are used to define the agent's behavior. The specific implementation of how to handle the behavior defined in a strategy should be within the agent itself.
State
Agents are executed using multithreading, which means variables assigned to self
are not retained between function executions. To enable agents to maintain a state, you can use the AgentHelperInterface
to add_variable
, set_variable
, and get_variable
.
Any value stored in this manner is accessible throughout the simulator when the agent's actions are performed.
Agent Type
Regular (Base Agent)
To simplify development, we provide a "Base Agent." If no source
is specified, this will be used automatically.
The base agent simply said just calls the strategy that is defined by the agent and performs the actions that have been configured there.
If you don't have a need for adding any special actions to the agent and just
want it to do what the Strategy
specifies you can remove the source
field of
the agent in the configuration. The simulator will see that you left it out and
pick the Base Agent Class
as the source
option automatically.
You can still use all the other features of the agent like metrics
for example
to record metrics from the agent.
The following is an example of a configuration this type of agent.
agents:
- address: '0x52F065344b1298C5fc8b01217A2EfC3ef7Dd3AF6'
agentType: regular
environments:
- address: '0x52F065344b1298C5fc8b01217A2EfC3ef7Dd3AF6'
alias: ethereum1
wallet:
tokens:
- amount: 4338109590
token: bnWBTC
- amount: 2847843290371928722
token: ETH
- amount: 2847843290371928722
token: DAI
metrics:
- alias: amazing_agent_metric
source: file://metrics/amazing_agent_metric/
settings:
deposit: 1002
pool1:
fee: 5000
token0: WETH
token1: USDT
source: file://agent/defi/
strategy: file://strategy/trend-following/
MEV
MEV agents are a special type of agent that are only asked to perform a step
after all other agents have completed theirs.
The purpose of this is to allow MEV agents to search for MEV opportunities and capitalize on them by ordering transactions for the block that will be mined. They primarily do this by using priority fees to arrange the transactions within the block.
Each agent has access to a function within the EnvironmentHelper
called get_tx_pool
, which allows the agent to retrieve information about the transaction pool for that block. This information can then be used to identify MEV opportunities.
Class implementation
One of the required items for the agent is a Python file that implements
the AgentInterface
. If you haven't done this before please read
this before continuing.
You can find an example of an agent that has implemented the AgentInterface
in
the configuration template under agent/defi/main.py
(use simcli generate
to
get the template in a local directory).
✅ What to add to the Agent implementation:
- Performing actions on behalf of agents
❌ What not to add:
- Logging metrics inside the environment (use environment metrics)
Methods to implement
__init__(self, strategy: StrategyInterface | None, agent_helper: AgentHelperInterface, metric_helper: MetricHelperInterface)
agent_initialization(self, simulation_state: SimulationStateHelperInterface)
agent_pre_step(self, simulation_state: SimulationStateHelperInterface)
agent_step(self, environment_helper: EnvironmentHelperInterface, simulation_state: SimulationStateHelperInterface)
agent_post_step(self, simulation_state: SimulationStateHelperInterface)
agent_teardown(self, simulation_state: SimulationStateHelperInterface)
Library file
The library file for the agent class supports a few extra parameters besides the standard ones, see a full example of a library file for an agent below:
name: "Liquidator"
version: "1.0.0"
type: "agent"
author: "Almanak AG"
description: ""
license: "MIT"
supported_chains:
- engine: 'evm'
chainId: '1'
dependencies:
protocols:
- "library://almanak/protocols/aave-v3:1.0.0"
- engine: 'evm'
chainId: '2'
dependencies:
protocols:
- "library://almanak/protocols/aave-v3:1.0.0"
settings:
uniswap_v3_usdc_pool: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
As you can see the main part that we add is the supported_chains
, which is
simply an array of objects that you can use to configure dependencies and only
allow the agent to work on certain chains because it has unique features to
them.
engine
is the Chain Engine as configured for the environment.chainId
is the chain id as configured for the environment.dependencies
allow you to set certain dependencies on an environment level, these have to be library items.settings
are like any other settings but can overwrite them on an environment level. Useful for contract addresses that are different per chain