OURO
SubmitMy JobsMy Files
Docs
Get StartedMCPREST APIBuild an AgentPricing
Get StartedMCPREST APIBuild an AgentPricing
OUROBuilt onBase

Building an Autonomous Agent

Build an agent that pays for and runs compute jobs with its own wallet.

Use @x402/fetch to wrap the standard fetch function with automatic x402 payment handling. When your request gets a 402 response, the library signs the USDC payment with your wallet and retries — no manual payment code needed.

Prerequisites

  • Node.js 18+
  • A wallet with USDC on Base
  • @x402/fetch and @x402/evm packages

Payment Flow

@x402/fetch handles the full payment flow automatically. For the step-by-step details of what happens under the hood, see the API payment flow.

What Happens Under the Hood

@x402/fetch handles this entire flow automatically — you just call fetchWithPayment().

architecture
Your Agent ──POST (no payment)──▶ Ouro API ──▶ 402 + price
Your Agent ──sign payment────▶ Your Wallet (local)
Your Agent ──POST + signature──▶ Ouro API ──▶ 200 + job_id
Ouro API ──submit──▶ Slurm Cluster ──run──▶ Workers

Dependencies

package.json
{
  "dependencies": {
    "@x402/fetch": "^2.6.0",
    "@x402/evm": "^2.6.0",
    "viem": "^2.0.0"
  }
}

Full Example

A complete TypeScript agent that submits a job and polls for results:

agent.ts
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

// 1. Set up wallet and x402-enabled fetch
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
// fetchWithPayment handles 402 → sign → retry automatically

const OURO_API = "https://api.ourocompute.com";

async function runJob(script: string, cpus = 1, timeMin = 1) {
  // 2. Submit job — payment is handled automatically
  const submitRes = await fetchWithPayment(`${OURO_API}/api/compute/submit`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ script, cpus, time_limit_min: timeMin }),
  });

  const { job_id } = await submitRes.json();
  console.log(`Job submitted: ${job_id}`);

  // 3. Poll for results
  // GET /api/jobs/{job_id} requires EIP-191 wallet signature.
  // Sign message "ouro-job-view:{job_id}:{wallet}:{timestamp}" and pass
  // wallet, signature, timestamp as query params. See API docs for details.
  let result;
  while (true) {
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const message = `ouro-job-view:${job_id}:${account.address.toLowerCase()}:${timestamp}`;
    const signature = await account.signMessage({ message });
    const params = new URLSearchParams({
      wallet: account.address, signature, timestamp,
    });
    const res = await fetch(`${OURO_API}/api/jobs/${job_id}?${params}`);
    result = await res.json();
    if (["completed", "failed"].includes(result.status)) break;
    await new Promise((r) => setTimeout(r, 3000));
  }

  console.log(`Status: ${result.status}`);
  console.log(`Output: ${result.output}`);
  return result;
}

runJob("echo hello from autonomous agent");
← REST APIPricing →