advancedcookbook
Always-on Twitter agent
An autonomous AI account that posts, replies, and survives forever.
Persistent Agent (`0x0820`) spawns a Docker container in a TEE with its own DKMS-derived wallet, encrypted memory on DA, and heartbeat-driven revival. The agent posts to X via HTTP precompile, processes replies via LLM, and pays for its own gas via RitualWallet — fully autonomous, no off-chain keeper.
Architecture
┌────────────────────┐ heartbeat ┌───────────────────┐
│ AgentHeartbeat │ ◀──────────────────── │ Persistent Agent │
│ 0xEF505E…3aCa │ every 150 blocks │ 0x0820 (Docker) │
└────────────────────┘ │ in TEE │
│ │ │
│ if missed → │ ┌───────────────┐ │
│ revive from DA │ │ DKMS-derived │ │
▼ │ │ wallet (own) │ │
┌────────────────────┐ │ └───────────────┘ │
│ Spawn from CID │ │ │
│ (encrypted memory) │ │ HTTP → X API │
└────────────────────┘ │ LLM → replies │
└───────────────────┘Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";
contract AlwaysOnAgent is PrecompileConsumer {
address constant PERSISTENT_AGENT = address(0x820);
address constant ASYNC_DELIVERY = 0x5A16214fF555848411544b005f7Ac063742f39F6;
address constant HEARTBEAT = 0xEF505E801f1Db392B5289690E2ffc20e840A3aCa;
bytes32 public agentCid; // restoration point on DA
address public agentWallet; // DKMS-derived address
function spawn(address executor, bytes32 reviveCid) external {
// soulRef: identity + system prompt
// memoryRef: append-only event log
bytes memory encoded = abi.encode(
executor,
soulStorageRef(),
memoryStorageRef(),
reviveCid, // 0x0...0 = fresh spawn, else revive
"ritual/sigil-agent:latest",
uint256(150_000), // ttl in blocks
address(this),
this.onPersistentAgentResult.selector,
// ... 17 more fields per spec
);
(bool ok, bytes memory result) = PERSISTENT_AGENT.call(encoded);
require(ok, "persistent agent failed");
}
function onPersistentAgentResult(bytes32 jobId, bytes calldata result) external {
require(msg.sender == ASYNC_DELIVERY, "unauth");
// Agent completed an action cycle — extract new memory CID
(bytes32 newCid, address derivedWallet) =
abi.decode(result, (bytes32, address));
agentCid = newCid; // store for next revival
agentWallet = derivedWallet;
}
function soulStorageRef() internal pure returns (bytes memory) {
// ('hf', 'taufik/sigil-soul/agent.jsonl', 'HF_TOKEN')
return abi.encode("hf", "taufik/sigil-soul/agent.jsonl", "HF_TOKEN");
}
function memoryStorageRef() internal pure returns (bytes memory) {
return abi.encode("gcs", "agents/sigil/memory.jsonl", "GCS_CREDS");
}
}