Intented docs

Any language: the three calls

Use Intented from an agent in any language, with a NEAR library and plain HTTP.

The intented package is a convenience. Underneath, a payment is three calls any agent can make: propose on the wallet, POST /api/verdict to the Intented API, then execute on the wallet. You need a NEAR library that can sign function calls (near-api-js, py-near, near-cli-rs or another) and an HTTP client.

Before you start

The agent needs an ed25519 key pair whose public key is on the wallet as a function-call key for propose and execute. Make it with any NEAR tooling, keep the private key on the agent's machine, and paste the public key into the Create page, or Add the agent key on an existing wallet. The wallet itself is the account the key signs for: transactions go from my-agent.intented.testnet to my-agent.intented.testnet.

1. Propose

Build the payment and its action. For a token transfer of 0.001 wNEAR to the vendor:

args_json = {"receiver_id":"intented-vendor.testnet","amount":"1000000000000000000000"}
action
{
  "receiver_id": "wrap.testnet",
  "method": "ft_transfer",
  "args_sha256": "<lowercase hex sha256 of the exact args_json string>",
  "deposit": "1",
  "nonce": "1793877407816",
  "expiry_ms": "1793878307816"
}
  • receiver_id is the token contract; the payee is inside args_json.
  • deposit is in yoctoNEAR, a decimal string. ft_transfer needs exactly "1", which the wallet attaches from its own balance.
  • nonce is unique per payment; the current time in milliseconds works.
  • expiry_ms is at most an hour ahead. 15 minutes is a good default.
  • args_sha256 must be over the exact string you send as args_json, byte for byte.

Call propose({ action, args_json }) on the wallet with 30 Tgas and no attached deposit. It returns the proposal_id.

2. Get the verdict

curl -s -X POST "$INTENTED_API_URL/api/verdict" \
  -H 'content-type: application/json' \
  -d '{"wallet_id":"my-agent.intented.testnet","proposal_id":0,"context":"<what the agent read, verbatim>"}'
Response
{
  "id": "p_7aebf727ad7a11d7",
  "verdict": "ALLOW",
  "reason": "The action transfers 0.001 wNEAR to intented-vendor.testnet, which matches …",
  "model": "Qwen/Qwen3.8-27B",
  "chat_id": "chatcmpl-…",
  "signer": "0x835ab53d20294ef795906dff21ae4c045336aa26",
  "signature": "0x…",
  "req_bytes": "<base64>",
  "resp_bytes": "<base64>"
}

The API reads the action from the chain, not from your request, so you can't ask it to judge something other than what you proposed. context is at most 20,000 characters. See the API reference for every error.

3. Execute

Call execute on the wallet with 300 Tgas and no attached deposit:

{ "proposal_id": 0, "req_bytes": "<from the verdict>", "resp_bytes": "<from the verdict>", "sig_65": "<signature from the verdict>" }

Send it for a DENY too. The wallet refuses with "verdict is not ALLOW", and that refusal is the on-chain record. A successful execute makes the transfer; a refused one moves nothing. The errors reference lists every refusal.

4. Report it (optional)

curl -s -X POST "$INTENTED_API_URL/api/executed" \
  -H 'content-type: application/json' \
  -d '{"wallet_id":"my-agent.intented.testnet","proposal_id":0,"near_tx_hash":"<execute tx hash>"}'

The API looks the transaction up on-chain and links it on the payment's receipt. Without it, the receipt still shows the verdict and the proposal's status, read from the wallet.

A working implementation

The TypeScript in the repo does exactly these steps: agent/src/wallet.ts builds the action, and agent/src/pay.ts runs propose, verdict, execute and report.

On this page