Silverback — Part I: Introduction, Setup, Local Testing, Cloud Deployment
Exploring ApeWorX's New Bot Platform
It’s great to have a bot, but let’s be real — the time and cost you’ll pay to get the first one online is painful.
I give readers the tools necessary to do everything for themselves, but it’s not always the right choice. For some tasks, you just can’t justify buying another 2 TB NVMe disk, writing tens of thousands of lines of code, and then sleeping with one eye open watching the logs in case something goes wrong.
For most bot operators, the infrastructure requirement is the most oppressive.
You can go for the fully self-hosted route, paying for a bare metal server in a data center, or run a set of light clients on virtual servers connected to a remote RPC provider. If you choose either of these options, you’ll select one or more infrastructure-as-a-service (IaaS) providers. Instead of running your own server, you rent one in a data center. Instead of running your own node, you connect to a remote provider and use theirs. The last decade has taught us that these infrastructure services are both viable and popular.
Many operators still want to write their own code to manage the execution of their strategy, which rejects the software-as-a-service (SaaS) model that operates both the infrastructure and the application.
In the middle of both of these is the platform-as-a-service (PaaS) model, which provides the infrastructure and a set of tools to build software on top of it. This gives developers more freedom about what they can build and how they integrate with it.
Silverback
Silverback is a platform for deploying and managing chain-connected bots on cloud hardware. It is developed and operated by ApeWorX, the same company that maintains the open-source Ape Framework, which I use for smart contract testing and development.
IMPORTANT NOTE
I have no business relationship with ApeWorX or their employees. I’m exploring the platform from personal curiosity and as a service to my readers. The company is not paying me to review or write about their platform.
The quick start documentation says:
Silverback lets you create and deploy your own Python bots that respond to on-chain events. The Silverback library leverages the Ape development framework as well as it’s ecosystem of plugins and packages to enable you to develop simple-yet-sophisticated automated bots that can listen and respond to live chain data.
Silverback bots are excellent for use cases that involve continuously monitoring and responding to on-chain events, such as newly confirmed blocks or contract event logs.
Some examples of these types of bots:
Monitoring new pool creations, and depositing liquidity
Measuring trading activity of popular pools
Listening for large swaps to update a telegram group
Degen Code readers are the ideal users of the platform — we know Python, have experience with Ape, and we’re all here to build bots (consuming dad joke content a close runner-up).
The Developing Bots section in the documentation lists some useful capabilities, including:
Handling new blocks
Handling new event logs (with filtering)
Performing periodic tasks
Creating dedicated task workers
Performing single-execution tasks at startup and shutdown
Sharing state across multiple workers
Signing and sending transactions
Managing nonces for high-speed signing and broadcast
Distributing execution (single listener client, multiple workers)
At its core, a bot does three things:
Observe the chain
React to relevant events
Generate and send transactions when conditions merit
If Silverback provides enough tooling to do these three things reliably, then even your mom might try botrunning.
Reducing mental overhead by eliminating many infrastructure concerns will take us far.
Installation and Local Testing
Silverback allows you to develop and run a bot locally. It can connect to arbitrary networks and use arbitrary signers, provided that they are already defined in Ape. For example, this command would run a particular bot defined in degen.py
on the default Ethereum mainnet RPC defined by Ape:
silverback run degen --network ethereum:mainnet
Since an account was not provided, the bot would not have the ability to sign and send transactions.
Let’s try building a simple bot now to demonstrate.
At the time of writing, the latest release of Silverback is version 0.7.19.
First create a directory where your bot (or bots) will live, and make a virtual environment. I’ll use uv here, but feel free to use another tool if you prefer:
btd@dev:~$ mkdir ~/code/silverback_bots
btd@dev:~$ cd ~/code/silverback_bots/
btd@dev:~/code/silverback_bots$ uv venv
Using CPython 3.13.1
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
btd@dev:~/code/silverback_bots$ uv pip install silverback
Resolved 127 packages in 586ms
Installed 127 packages in 857ms
[...]
Now create a very simple bot that will receive and print the block number whenever a new one arrived:
block_watcher.py
from ape import chain
from silverback import SilverbackBot
bot = SilverbackBot()
@bot.on_(chain.blocks)
def handle_new_block(block):
print(f"New Block: {block.number}")
Activate the virtual environment and run it:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback run block_watcher --network ethereum:mainnet
INFO: Connecting to existing Reth node at http://localhost:8545.
INFO: Loading Silverback Bot with settings:
BOT_NAME="bot"
BROKER_CLASS="taskiq:InMemoryBroker"
NETWORK_CHOICE="ethereum:mainnet:http://localhost:8545"
SUCCESS: Loaded Silverback Bot:
NETWORK="ethereum:mainnet"
FORK_MODE=False
SIGNER=None
INFO: Connecting to existing Reth node at http://localhost:8545.
INFO: Using PollingRunner: max_exceptions=3
WARNING: The polling runner makes a significant amount of requests. Do not use in production over long time periods unless you know what you're doing.
INFO: Worker using Silverback SDK v0.7.19
SUCCESS: Startup complete, transitioning to runtime
INFO: `ape-cache` database has not been initialized
INFO: handle_new_block[block=0x6c232c7da7de7ce8f3fdc9f689da9e2114f4486d873812100abad1b19650897d] - Started
New Block: 22441990
SUCCESS: handle_new_block[block=0x6c232c7da7de7ce8f3fdc9f689da9e2114f4486d873812100abad1b19650897d] - 0.000s (0.0%)
INFO: handle_new_block[block=0xec88b8d901e4278373f77e6dfb920e08c0bb9a67961c2c8cc56c19caea714cac] - Started
New Block: 22441991
SUCCESS: handle_new_block[block=0xec88b8d901e4278373f77e6dfb920e08c0bb9a67961c2c8cc56c19caea714cac] - 0.000s (0.0%)
[...]
Launching the bot works as expected, and you can observe that it connected to the ethereum:mainnet
network defined in ~/.ape/ape-config.yaml
, which points to my local Reth node running on port 8545.
At the top of the log, Silverback warned about the number of requests it would generate:
INFO: Connecting to existing Reth node at http://localhost:8545.
INFO: Using PollingRunner: max_exceptions=3
WARNING: The polling runner makes a significant amount of requests. Do not use in production over long time periods unless you know what you're doing.
Given what we know about polling vs. subscriptions, I suspect that Silverback chose the polling runner because the ethereum:mainnet
network was defined in Ape with an HTTP endpoint.
Changing the endpoint from http://localhost:8545
to ws://localhost:8546
results in a different runner being selected:
INFO: Connecting to existing Geth node at ws://localhost:8546.
INFO: Using WebsocketRunner: max_exceptions=3
INFO: Worker using Silverback SDK v0.7.19
Silverback relies on Ape for a lot, so you may need to spend time sorting out your Ape configuration before your Silverback bots can run locally.
Cloud Bots
The local bot example above uses an Ape network to make a connection to my local node. However once the bot is deployed to the cloud platform, it needs access to an externally accessible RPC. This means defining a network for your provider (Ankr, Infura, or similar) and defining it in ape-config.yaml
in the same directory as your bot.
For quick testing I like to use the free publicnode endpoints. Here’s a simple ape-config.yaml
with network definitions for Ethereum mainnet and Base mainnet:
ape-config.yaml
base:
default_network: mainnet
mainnet:
default_provider: node
mainnet-fork:
default_provider: foundry
ethereum:
default_network: mainnet
mainnet:
default_provider: node
mainnet_fork:
default_provider: foundry
node:
ethereum:
mainnet:
uri: wss://ethereum-rpc.publicnode.com
base:
mainnet:
uri: wss://base-rpc.publicnode.com
Saving this and re-running the block watcher shows the new endpoint is used:
btd@dev:~/code/silverback_bots$ silverback run block_watcher --network ethereum:mainnet
INFO: Connecting to existing Geth node at wss://ethereum-rpc.publicnode.com.
INFO: Loading Silverback Bot with settings:
BOT_NAME="bot"
BROKER_CLASS="taskiq:InMemoryBroker"
NETWORK_CHOICE="ethereum:mainnet:wss://ethereum-rpc.publicnode.com"
SUCCESS: Loaded Silverback Bot:
NETWORK="ethereum:mainnet"
FORK_MODE=False
SIGNER=None
INFO: Connecting to a 'tenderly' node.
INFO: Using WebsocketRunner: max_exceptions=3
INFO: Worker using Silverback SDK v0.7.19
SUCCESS: Startup complete, transitioning to runtime
INFO: handle_new_block[block=0x89812bdaf0e600d688f3d53400c67234bf09b7550df48bfc938fa18e9ec6d1c8] - Started
New Block: 22443414
SUCCESS: handle_new_block[block=0x89812bdaf0e600d688f3d53400c67234bf09b7550df48bfc938fa18e9ec6d1c8] - 0.000s (0.0%)
Cloud Deployment
You can continue to run Silverback bots locally with no charge. But if you want to offload their operation to the cloud platform, you need to perform several steps.
First, create an account through the web interface, and connect your local client to the service:
btd@dev:~$ silverback login
⠸ Please complete authentication in your browser.Opening in existing browser session.
Successfully authenticated Getting a token...
INFO: Logged in to 'https://account.apeworx.io' as 'bowtieddevil'
Then create a new workspace, which wraps permissions for one or more users and clusters:
btd@dev:~$ silverback cluster workspaces new --name "Test Workspace" --slug "test-workspace"
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
SUCCESS: Created 'Test Workspace' (slug: 'test-workspace')
Then create a cluster in that workspace:
btd@dev:~$ silverback cluster new --name "Test Cluster" test-workspace
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
SUCCESS: Created 'Test Cluster' (slug: 'test-cluster')
WARNING: To use this cluster, please pay via `silverback cluster pay create test-workspace/test-cluster`
The cluster is now ready to go, but the platform will not activate it without payment. Silverback is crypto-native, paid through ApeWorX’s streaming payment system ApePay.
ApePay works by authorizing an ERC-20 transfer of a supported payment token to a streaming payment contract.
Here’s the first gotcha — Silverback needs to fetch contract data for the payment token you’re using, but it doesn’t depend on the Ape plugin to use Etherscan. So if you try creating a payment, you’ll get an awkward error that doesn’t seem to fit:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback cluster pay create --token USDC --account base_acct --time "1 hour" --network base:mainnet test-workspace/test-cluster
INFO: Connecting to existing Geth node at wss://base-rpc.publicnode.com.
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
WARNING: Unable to determine the ContractType for the proxy at '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'.
Traceback (most recent call last):
[...]
ape.exceptions.ContractNotFoundError: Failed to get contract type for address '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'. Current network 'base:mainnet:wss://base-rpc.publicnode.com' has no associated explorer plugin. Try installing an explorer plugin using ape plugins install etherscan, or using a network with explorer support.
Note: the USDC token address on Base mainnet is 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
.
You can solve the issue by installing the ape-etherscan
plugin via pip
within the Silverback virtual environment. ApeWorX would be wise to avoid this confusing issue by making silverback
depend on ape-etherscan
specifically, or eth-ape['recommended-plugins']
broadly.
The bots that you deploy on Silverback are Docker containers running in Kubernetes. So to deploy a bot, its container has to be pushed to an accessible container registry. The registry can be public or private. Docker Hub allows basic users a single free private repo, which you can use to create and publish the bot container to.
Give the Silverback cluster access to the private repo like this:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback cluster registry new --cluster test-workspace/test-cluster dockerhub docker.io
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
Email: devil@bowtieddevil.com
Username: []
Password:
created: 2025-05-09 23:01:42+00:00
hostname: docker.io
name: dockerhub
updated: 2025-05-09 23:01:42+00:00
Then build the container:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback build
STEP 1/8: FROM ghcr.io/apeworx/silverback:stable
STEP 2/8: USER root
--> Using cache 9f686772e7813183b7c9493e4887606503fd45daf49f77e2fcb4c1b4cb4b647e
--> 9f686772e781
STEP 3/8: WORKDIR /app
--> Using cache e04650456a1e3ceb1d354373453cf6ee651983bc22606b3a71e506224983e899
--> e04650456a1e
STEP 4/8: RUN chown harambe:harambe /app
--> Using cache 08a721aa01a589f0ef9e151fc5e150334d7dc85b14eedf849ecb09b3461045fb
--> 08a721aa01a5
STEP 5/8: USER harambe
--> Using cache 9f624e10de0c8beb9379b242734585e9fe8e61bafd241a99fb2c6ec1f9127f69
--> 9f624e10de0c
STEP 6/8: COPY ape-config.yaml /app
--> Using cache 6ed97d42a6a3dd4993b0f5a2109a160822146853a9817a33aff2e6223ad926cd
--> 6ed97d42a6a3
STEP 7/8: RUN ape plugins install -U .
--> Using cache c998bc4770537999c67dc0d48b007c342d7e58bc9ca3ab54deb65804bca741a2
--> c998bc477053
STEP 8/8: COPY block_watcher.py /app/bot.py
--> Using cache 52e96a28d7ad1cec355659ed42bd67462e61b9afb72ca772cb6aacf3facd6869
--> 52e96a28d7ad
52e96a28d7ad1cec355659ed42bd67462e61b9afb72ca772cb6aacf3facd6869
This will create a Dockerfile in the .silverback-images
folder and build an image with the shown tag on the last line. Here mine is 52e96a28d7ad
, yours may differ.
Push the container to the registry using Docker:
btd@dev:~/code/silverback_bots$ docker push [user]/[repo_name]/bot:latest
After this is done, pay for some cluster time. The current price for bot time is roughly 38 cents / hr, but it may be different when you read this:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback cluster pay create --token USDC --account base_acct --time "1 hour" --network base:mainnet test-workspace/test-cluster
INFO: Connecting to existing Geth node at wss://base-rpc.publicnode.com.
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
configuration:
cluster:
cpu: 1 vCPU
memory: 2 GiB
recorder:
bandwidth: 1 KiB/sec
duration: 3 months
runner:
bots: 5
networks: 3
version: 1
duration: 1:00:00
payment: 0.379626 USDC
Do you want to use this configuration to fund Cluster 'test-workspace/test-cluster'? [y/N]: y
[...]
SUCCESS: Cluster funded for 1:00:00.
WARNING: Cluster may take up to 1 hour to deploy. Check back in 2-5 minutes using `silverback cluster info` to start using your cluster.
Now the bot can be deployed to the cluster:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback cluster bots new blockwatcher --image [user]/[repo_name]:latest --network ethereum:mainnet --cluster test-workspace/test-cluster
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
Name: 'blockwatcher'
Image: '[user]/[repo_name]:latest'
Network: 'ethereum:mainnet:node'
Do you want to create and start running this bot? [y/N]: y
Bot 'blockwatcher' (396845b1-ef9e-43c3-9fc2-c787103a7ab1) deploying...
You can monitor a particular bot by inspecting its logs:
(silverback_bots) btd@dev:~/code/silverback_bots$ silverback cluster bots logs blockwatcher --cluster test-workspace/test-cluster
INFO: Logged in to 'https://silverback.apeworx.io' as 'bowtieddevil'
05/09/25 16:08:49 INFO | Connecting to existing Geth node at wss://ethereum-rpc.publicnode.com.
05/09/25 16:08:49 INFO | Loading Silverback Bot with settings:
| BOT_NAME="bot"
| BROKER_CLASS="taskiq:InMemoryBroker"
| NETWORK_CHOICE="ethereum:mainnet:wss://ethereum-rpc.publicnode.com"
05/09/25 16:08:49 SUCCESS | Loaded Silverback Bot:
| NETWORK="ethereum:mainnet"
| FORK_MODE=False
| SIGNER=None
05/09/25 16:08:50 INFO | Connecting to a 'mevblocker' node.
05/09/25 16:08:51 INFO | Using WebsocketRunner: max_exceptions=3
05/09/25 16:08:52 INFO | Worker using Silverback SDK v0.7.19
05/09/25 16:08:52 WARNING | No state snapshot detected, using empty snapshot
05/09/25 16:08:53 SUCCESS | Startup complete, transitioning to runtime
05/09/25 16:16:50 INFO | handle_new_block[block=0x48f3020f72bed71cf09912a7ce71f789b2e02ba4a214bea1fee956671a1cce26] - Started
| New Block: 22449088
05/09/25 16:16:50 SUCCESS | handle_new_block[block=0x48f3020f72bed71cf09912a7ce71f789b2e02ba4a214bea1fee956671a1cce26] - 0.000s (0.0%)
05/09/25 16:17:02 INFO | handle_new_block[block=0x876dbca3fbce72606659045ea2c26e2377c49aa2fe7d6566ae0e26479526bd8a] - Started
| New Block: 22449089
05/09/25 16:17:02 SUCCESS | handle_new_block[block=0x876dbca3fbce72606659045ea2c26e2377c49aa2fe7d6566ae0e26479526bd8a] - 0.000s (0.0%)
05/09/25 16:17:24 INFO | handle_new_block[block=0x30ab35e376d7b02081e4fd619366e4f911789479e53063811f9431f622121857] - Started
| New Block: 22449090
05/09/25 16:17:24 SUCCESS | handle_new_block[block=0x30ab35e376d7b02081e4fd619366e4f911789479e53063811f9431f622121857] - 0.000s (0.0%)
05/09/25 16:17:37 INFO | handle_new_block[block=0xa272748b741de1c6edbaa6f1b398a1db7de057cb92cf7ff678b8985f6b988cb2] - Started
| New Block: 22449091
05/09/25 16:17:37 SUCCESS | handle_new_block[block=0xa272748b741de1c6edbaa6f1b398a1db7de057cb92cf7ff678b8985f6b988cb2] - 0.000s (0.0%)
Wrap-Up
The Silverback platform is not batteries-included (yet) — bot runners will need to write their own bots, connect them to an external RPC, then build and push containers to their own repo for final deployment to the Silverback cluster.
I think it will be especially attractive for users who want to deploy narrowly-scoped bots while avoiding the cost and maintenance of the full hardware stack.
I have consulted with several NFT projects to write bots that generate and update metadata as mints are claimed following launch. I typically connected these bots to Infura and deployed them over SSH to shared VPS instances. A bot like this could happily run on Silverback, and being able to sustain its operation with crypto payments instead of using a payment processor is certainly attractive.
Next Steps
I have explored the platform from the perspective of an ignorant first-timer. The reason is simple: I’m an ignorant first-timer! I have plenty of experience building bots, but always within my own sandbox. I only have access to the docs, the Silverback client code on Github, and the ApeWorX Discord and Telegram channels.
There are many features I did not cover at all, including workers, shared bot state, secure signing keystores, and MCP integration with AI tools. I’m certain there are some features I’m completely unaware of, so I hope you’ll comment below and tell me what caught your eye.