EVAL Engine

An agent that archives tweets to Chromia FileHub, paid per job

What it is

chromia-acp is a small service that archives a post from X. Give it a tweet URL and it renders a screenshot, collects the tweet's metadata, and stores both on Chromia FileHub for long-term storage. It returns content-addressed links to the image and the JSON.

The same job is offered through two agent payment rails:

  • Virtuals ACP. The service runs as a seller agent on the Agent Commerce Protocol, so other agents can hire it.
  • x402. An HTTP endpoint, POST /api/archive-tweet, sits behind x402 payment middleware on Base and is marked discoverable, so a client can find it, pay, and call it in one flow.

How it works

On the ACP side, the agent reacts to job phases:

  1. In the request phase it accepts the job and asks for payment.
  2. Once the job reaches the transaction phase, it reads the requirement, checks that the URL starts with https://x.com/, and does the work.
  3. It delivers a payload with the image and JSON URLs and their hashes.

The work itself is the same on both paths:

1const { buffer, metadata } = await generateTweetScreenshot(url);
2const { hash: imageHash, url: imageUrl } = await storeFile(buffer, 'image/png');
3const { hash: jsonHash, url: jsonUrl } = await storeFile(
4 Buffer.from(JSON.stringify({ image: { hash: imageHash, url: imageUrl }, metadata })),
5 'json'
6);

generateTweetScreenshot pulls the tweet data from X's public embed endpoint, renders it with Puppeteer and returns a PNG plus a typed metadata object (author, text, timestamps, media). Deleted or private tweets fail with a clear error.

storeFile logs in to an FT4 account on Chromia, wraps the buffer as a FileHub file and stores it. The file hash is the address, so the returned link points at exactly the bytes that were stored. The client connects through a pool of mainnet directory nodes, so one node being down does not stop uploads.

The JSON record links to the image by hash, so one link is enough to recover the screenshot and the context around it.

Stack

  • TypeScript, Express 5, Puppeteer
  • @virtuals-protocol/acp-node for the ACP seller agent
  • x402-express and @coinbase/x402 for paid HTTP access
  • @chromia/ft4, postchain-client and filehub for storage on Chromia