Execute ElizaOS AI agents with full confidentiality in iExec TDX Trusted Execution Environments (TEEs).
π§΅ Use case: In this demo, the agent impersonates a custom character and posts tweets on the userβs X (Twitter) account based on the characterβs personality and configuration.
This iExec Application (iApp) runs ElizaOS AI agents securely inside Intel TDX enclaves, providing:
- β Model integrity verification using model ID (e.g., SHA-256)
- π‘οΈ Full isolation of the AI stack (Eliza Agent + model)
- π Support for protected character datasets and user credentials
Important
To test and run this agent, you must have a twitter account identified as an automated account, otherwise your account may be suspended.
You can run and test the iApp locally in a Docker container before deploying it on iExec.
To run an agent, you need:
- Model name (e.g.,
qwen2.5:0.5b) - Model ID (e.g.,
a8b0c5157701)
β‘οΈ Visit https://ollama.com/search Select a model, and you will find:
- The model name at the top
- The model ID (short hash or full SHA256) in the model details/download section
Important
Make sure the model is supported by ElizaOS. Stick with small/medium-sized models like 0.5b for local runs.
The agent expects a character definition file as input in the iexec_in folder. This file must follow the ElizaOS character format.
An example is provided in:
iexec_in/characterModify it to fit your custom personality, prompt, and configuration.
Important
Ensure the clients and modelProvider fields are defined with valid values matching your integration setup.
"clients": ["twitter"],
"modelProvider": "ollama",Build the Docker image locally:
docker build -t eliza .You can edit and adjust the .env.template to suit your needs, but do not touch lines 5 to 24. For testing purposes, we recommend that you leave the file as is. Values with a _TO_REPLACE suffix will be replaced at runtime with automatically injected secrets.
Moreover, this file will be used in the docker build and automatically renamed to .env, so there's no need to do this (you can see line 29 of the Dockerfile).
Run the app using Docker:
docker run --rm --name eliza \
-v ./iexec_in:/iexec_in \
-v ./iexec_out:/iexec_out \
-e IEXEC_DATASET_FILENAME=character \
-e IEXEC_IN=/iexec_in \
-e IEXEC_OUT=/iexec_out \
-e IEXEC_REQUESTER_SECRET_1="twitter-username" \
-e IEXEC_REQUESTER_SECRET_2="twitter-password" \
-e IEXEC_REQUESTER_SECRET_3="twitter-email@example.com" \
eliza:latest "<model_name> <model_id>"β‘οΈ Result: The agent will generate and post content on your X (Twitter) profile according to the personality and behavior defined in your custom character file.
If everything's ok and you want to continue testing, then tag the image with your docker account and push it to the hub :
docker tag eliza:latest <docker-hub-user>/eliza:1.0.0
docker push <docker-hub-user>/eliza:1.0.0TDX is currently an experimental environment. The associated SDK/CLI is not yet released and there are a few steps to install it.
First move to another folder, the one of your choice, we'll clone a repo and install it.
# clone this project locally https://github.com/aimen-djari/iexec-sdk/tree/feature/tdx
git clone --single-branch --branch feature/tdx git@github.com:aimen-djari/iexec-sdk.git
# install modules
npm install iexec
# build iExec
npm run build
# install
npm install -g .
# check version
iexec --version
#8.13.0-tdxNow, you can create a dedicated project/folder to manage the deployment but you can also stay in the application folder, which is not a problem, and the generated files are excluded in the .gitignore file. In the rest of this readme, we'll assume that we're staying in the application/agent folder.
Create a new Wallet file
iexec wallet createInitialize your iExec project
iexec init --skip-walletCheck that the generated chain.json file is as follows:
{
"default": "bellecour",
"chains": {
"bellecour": {
"sms": { "tdx": "https://sms.labs.iex.ec" }
}
}
}TEE applications need a few more keys in the iexec.json file; run this to add them automatically:
iexec app init --tee-framework tdxYour iexec.json should now look like this example:
{
...
"app": {
"owner": "<your-wallet-address>", // starts with 0x
"name": "tee-scone-hello-world", // application name
"type": "DOCKER",
"multiaddr": "<docker-hub-user>/eliza:1.0.0", // app image
"checksum": "<checksum>", // starts with 0x, update it with your own image digest
"mrenclave": {
"framework": "TDX", // TEE framework (keep default value)
}
},
...
}- Normally, the
owneris automatically filled in (via your wallet). - Change the
multiaddrfield to match the docker image you've pushed onto the hub checksumneeds to be changed
The checksum of your app is the sha256 digest of the docker image prefixed with 0x , you can use the following command to get it.
docker pull <docker-hub-user>/eliza:1.0.0 | grep "Digest: sha256:" | sed 's/.*sha256:/0x/'remplacer
Deploy the app with the standard command:
iexec app deployiexec requester push-secret twitter-username --secret-value <your-twitter-username>
iexec requester push-secret twitter-email --secret-value <your-twitter-email>
iexec requester push-secret twitter-password --secret-value <your-twitter-password>Init the dataset configuration.
iexec dataset init --encryptedThis command will create the datasets/encrypted, datasets/original and .secrets/datasets folders. A new dataset section will be added to the iexec.json file as well.
.
βββ datasets
β βββ encrypted
β βββ original
βββ .secrets
βββ datasetsPut your character file into datasets/original folder.
For example if you have directly updated the sample file in iexec_in :
cp iexec_in/character datasets/originalNow run the following command to encrypt the file:
iexec dataset encryptNote
iexec dataset encrypt will output a checksum, keep this value for a later use.
datasets
βββ encrypted
β βββ character.enc
βββ original
βββ characterAs you can see, the command generated the file datasets/encrypted/character.enc. That file is the encrypted version of your dataset, you should push it somewhere accessible because the worker will download it during the execution process. You will enter this file's URI in the iexec.json file (multiaddr attribute) when you will deploy your dataset. Make sure that the URI is a DIRECT download link (not a link to a web page for example).
Note
You can use Github for example to publish the file but you should add /raw/ to the URI like this:https://github.com/<username>/<repo>/raw/master/character.enc
The file .secrets/datasets/character.key is the encryption key, make sure to back it up securely. The file .secrets/datasets/dataset.key is just an "alias" in the sense that it is the key of the last encrypted dataset.
.secrets
βββ datasets
βββ dataset.key
βββ character.keyFill in the fields of the iexec.json file. Choose a name for your dataset, put the encrypted file's URI in multiaddr (the URI you got after publishing the file) and fill the checksum field. The checksum of the dataset consists of a 0x prefix followed by the sha256sum of the dataset. This checksum is printed when running the iexec dataset encrypt command. If you missed it, you can retrieve the sha256sum of the dataset by running sha256sum datasets/encrypted/character.enc.
$ cat iexec.json
{
"description": "My iExec ressource description...",
...
"dataset": {
"owner": "0x-your-wallet-address",
"name": "Encrypted character dataset",
"multiaddr": "/ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ",
"checksum": "<0x-sha256sum-of-the-dataset>" // starts with 0x
}To deploy your dataset run:
iexec dataset deployYou will get a hexadecimal address for your deployed dataset. Use that address to push the encryption key to the SMS so it is available for authorized applications.
For simplicity, we will use the dataset with a TEE-debug app on a debug workerpool. The debug workerpool is connected to a debug Secret Management Service so we will send the dataset encryption key to this SMS (this is fine for debugging but do not use to store production secrets).
iexec dataset push-secretOnce you have successfully tested the iApp locally and verified that tweets are being posted, you can deploy the iApp to iExec TDX production. Follow the iExec documentation for detailed steps.
When you're ready to run on iExec TDX (application deployed, dataset deployed, and requester secrets pushed):
iexec app run \
--args "<model_name> <model_id>" \
--tag tee,tdx \
--dataset <DATASET_ADDRESS> \
--secret 1=twitter-username \
--secret 2=twitter-password \
--secret 3=twitter-email \
--workerpool tdx-labs.pools.iexec.eth \
--skip-preflight-check \
--watchImportant
twitter-username, twitter-email and twitter-password are the labels defined when you pushed the secrets, you must not indicate here the real values of your identifiers.