DEV Community

Cover image for I built EDITH so AI agents can remember bad API purchases
Bunnyy
Bunnyy

Posted on

I built EDITH so AI agents can remember bad API purchases

During a Mainnet test, I paid 0.001 SUI for an API response that contained nothing useful.

The API returned HTTP 200, which usually means the request succeeded. But the response body was just an empty JSON object:

{}
Enter fullscreen mode Exit fullscreen mode

The payment had already gone through.

I sent the same request again, this time with EDITH remembering the earlier result. It refused before asking for another wallet approval.

The first request cost 0.001 SUI. The second cost nothing.

That is the problem I wanted to solve when I started building EDITH for the Tatum × Walrus Total Recall hackathon.

The problem

An AI agent can request information from an API, receive a response, and continue working.

When that API charges money, there is another question to consider: was the response worth paying for?

Imagine an agent using a paid market data API. It asks for a price, pays the provider, and receives an empty response.

The agent has spent money but has nothing useful to work with.

Now imagine the agent tries the exact same request again. Unless something remembers the earlier failure, it might repeat the payment.

A spending limit can restrict how much the agent uses. It does not explain whether a previous purchase was useful.

I wanted to connect those two things.

EDITH is a payment and memory layer that checks what happened on previous paid requests before deciding whether another payment should be allowed.

It does not replace the agent or the API provider. It sits between them and keeps a record of the outcomes.

What EDITH does

EDITH lets users connect a Sui wallet, create agent credentials, and control how much their agents can spend.

The agent can request paid data through EDITH, but it cannot spend money by itself. Every payment still requires approval from the wallet owner.

Before presenting a payment for approval, EDITH checks its memory for relevant past requests.

If the same request has already returned bad data, EDITH can refuse it without contacting the provider again.

After an approved payment, EDITH verifies the transfer and records what the API returned.

The main features are:

  • Wallet-controlled payments: the user signs each transaction, not the agent.
  • Spending limits: users can set limits per payment and across a rolling 24-hour period.
  • Payment verification: Tatum's Sui gRPC service is used to check what actually happened onchain.
  • Persistent memory: Walrus Memory stores the outcomes of paid requests.
  • Memory-based decisions: earlier failures can change whether later requests are allowed.
  • Reviewable history: users can inspect decisions, transaction references, and memory records.

The important distinction is that EDITH checks memory before money moves, not only afterward.

How a payment works

I separated the payment process into two stages: deciding whether a payment should happen, and handling an approved payment.

1. The agent makes a request

An agent sends a paid API URL to EDITH using its own agent key.

EDITH identifies the request using its method, path, query parameters, provider, and network.

It then looks up relevant history in Walrus Memory.

For example, these are different requests:

GET /demo/quote?ticker=SUI
GET /demo/quote?ticker=ZZZ
Enter fullscreen mode Exit fullscreen mode

They use the same API endpoint, but ask for different data.

That distinction matters. A failed request for one ticker should not automatically cause every request to the provider to be rejected.

2. EDITH checks previous outcomes

If the request has failed before, EDITH checks what kind of failure occurred.

For an earlier unusable response, it can refuse the exact request immediately.

For a temporary server error, it applies a cooldown rather than permanently treating the request as bad.

If there is no reason to refuse, EDITH continues to the provider.

3. The provider returns a price

The bundled demo API uses an HTTP 402 response to provide payment details.

EDITH reads the amount and receiving address, checks the price against the user's spending limits, and prepares the request for approval.

Nothing has been paid yet.

4. The wallet owner approves

The user sees the payment and signs it using their Sui wallet.

EDITH checks the signed transaction before passing it to the provider. The sender, recipient, and amount must match the expected payment.

The agent never receives the user's wallet private key.

5. EDITH verifies the payment

Once the signed payment has been submitted, EDITH queries Sui through Tatum to check whether the transaction succeeded and whether the provider received the required amount.

This matters because an API response is not enough to establish that a blockchain payment succeeded or failed.

6. The result is remembered

After confirming payment, EDITH evaluates the API response and saves the outcome to Walrus Memory.

The record includes details such as the request, provider, network, amount paid, transaction digest, result, and time.

When the agent asks again, that history is available before another payment is considered.

How I used Tatum

I integrated Tatum's Sui gRPC gateway directly into the EDITH backend.

The application uses the Sui SDK with Tatum's endpoint to interact with the network.

Tatum is involved in checking signed transfers and verifying completed transactions.

For a completed payment, EDITH checks that:

  1. The transaction succeeded on Sui.
  2. The expected provider received native SUI.
  3. The amount received meets the payment terms.

The application also checks the signed transaction before submission to make sure it is paying the correct address and amount.

There is a reason I kept this separate from the provider's response.

An API might return an error after receiving a signed transaction. That does not necessarily mean the payment failed.

If EDITH cannot establish what happened onchain, it treats the payment as unresolved and keeps the amount reserved against the user's spending limit until it can be checked again.

I did not want an uncertain payment to become an excuse to send another one.

Tatum provides the blockchain verification. The API provider provides the data. EDITH keeps track of both.

Read the Tatum Sui gRPC documentation

How I used Walrus Memory

This is the part that makes EDITH different from a normal payment approval interface.

I used the @mysten-incubation/memwal SDK to store and retrieve records through Walrus Memory.

Each signed-in wallet has its own memory namespace, keeping one user's payment history separate from another's.

Before making a payment decision, EDITH recalls previous records for the provider and endpoint.

The relevant part of the implementation is small:

const history = await loadHistory(
  memory,
  context,
  namespace
);

const early = decide(history, {
  key: request.key,
  now: Date.now()
});

if (early.action === "skip") {
  return declined(context, {
    ...early,
    source: "memory"
  });
}
Enter fullscreen mode Exit fullscreen mode

This runs before EDITH requests payment.

Walrus Memory retrieves relevant records, and EDITH applies its own rules to decide what to do.

I also kept exact request details in the stored records. Memory search helps find the relevant history, while matching the provider, endpoint, and network makes sure EDITH is using the right evidence.

After a payment completes, EDITH waits for the outcome to be saved and keeps the returned Walrus blob reference.

How EDITH learns from previous requests

EDITH is not training a new AI model after every payment.

Its learning comes from storing real outcomes and applying them to future decisions.

I built several rules around that history:

What EDITH remembers What happens next
The exact request previously returned unusable data Refuse the same purchase
A request encountered a temporary server error Wait 15 minutes before considering a retry
A new price is more than twice the highest previously successful price Refuse the unexpected price
At least three distinct paid requests failed, representing more than half the remembered requests to that endpoint Treat new requests to that endpoint as unreliable

These rules are deliberately different.

An empty response and a temporary server outage should not produce the same decision.

If a provider is briefly unavailable, trying again later may be reasonable. If the same request already returned permanently unusable data, paying again is harder to justify.

The endpoint-level rule also looks at distinct requests, rather than allowing repeated attempts at one bad request to make an entire provider appear unreliable.

For the current demo API, EDITH uses a clear validation rule: a useful quote must contain a numeric priceUsd value.

An empty object does not pass that check.

That is an important limitation of the current build. Different paid APIs would need their own response validation rules. EDITH does not claim to understand the value of every possible API response.

Read the Walrus Memory SDK documentation

Testing it with real SUI payments

I wanted the demo to show an actual payment changing a later decision.

So I ran the full sequence on Sui Mainnet, with payments approved through a Slush wallet.

The bundled Quote Desk API made it possible to test both valid and deliberately bad responses.

Here is the part of the run that matters:

Request Result Provider payment
GET /demo/quote?ticker=SUI Useful quote returned and remembered 0.001 SUI
GET /demo/quote?ticker=ZZZ API returned {}, recorded as failure 0.001 SUI
Repeat GET /demo/quote?ticker=ZZZ EDITH refused based on the earlier failure 0 SUI

The failed purchase produced a real Sui transaction and a Walrus Memory record.

Payment evidence:

On the repeated request, EDITH found the earlier failure, refused the purchase, and referenced the transaction that had already been paid.

There was no second wallet approval and no second payment.

The acceptance run on November 3, 2026 recorded three approved Mainnet payments and one refusal based on memory. I also ran a separate verification script that checked the transactions through Tatum and confirmed their associated Walrus Memory records.

By that point, the project's evidence report recorded 41 Walrus Memory records on Mainnet across its namespaces, including earlier command-line tests.

The full record, with transaction digests and memory references, is available in the repository.

Read the Mainnet evidence report

The application behind the demo

EDITH is a working web application with an API that other agents can call.

I kept the architecture relatively simple:

Component What it handles
Sui Mainnet The actual payments
Tatum Sui gRPC Blockchain access and transaction verification
Walrus Memory Previous payment outcomes and memory retrieval
Neon Postgres Wallet settings, agent credentials, pending approvals, and payment history
Node.js and Vercel Backend APIs and hosting
Vanilla JavaScript, Vite, and Sui Wallet Standard The web interface and wallet connection

The agent-facing API lets an agent submit a paid URL and check its request status.

The browser application gives the wallet owner a place to review the request and approve or decline payment.

I also built a guided demo, so someone can see the useful response, failed purchase, and memory-based refusal without having to write a separate agent first.

What still needs work

There are a few boundaries I want to be clear about.

The first bad purchase still costs money. EDITH cannot undo an already completed transfer. It is meant to prevent known mistakes from being repeated.

The usefulness checks are currently specific to the demo provider. Supporting more kinds of paid APIs will require provider-specific validation.

Wallet approval is intentional. EDITH does not let an agent spend freely. It can recommend and request payments, but the user remains responsible for approving them.

I also want to improve how payment history is displayed, make it easier to understand why a particular request was refused, and test the decision rules against more types of paid API responses.

Those are areas I would rather test properly than claim are already solved.

Try EDITH

EDITH was built for the Tatum × Walrus Total Recall hackathon.

The complete source code is public, along with the integration details and Mainnet evidence.

The result I care about most is still the simplest one from the test.

The agent paid for an empty response once. When it tried the same thing again, EDITH remembered why it should not pay.

Top comments (0)