ai-oracle
Signed AI answers with commitments anchored to 0G Storage (default) or on-chain. Each answer is hashed, signed by the operator key (✓ signature verified — not TEE-quote), and anchored as an immutable proof. Composes into
prediction-market.
What it does
The ai-oracle kit adds a verifiable AI query endpoint to your 0G app.
When a request arrives the kit:
- Calls
@foundryprotocol/0gkit-computeto run inference against the configured model. - Serialises the result into an oracle receipt (
{ question, answer, answerHash, ts }). - Signs the receipt with the operator key via EIP-191 personal-sign:
digestJson(receipt)is hashed and signed withsignMessage; the badge reads ✓ signature verified and is backed byrecoverSigner— this is an operator-signed receipt, not a hardware TEE quote. - Anchors the receipt to 0G Storage by default (immutable,
content-addressed
root= the commitment). SetOG_ANCHOR_ONCHAIN=1to also write the root on-chain via the bundledAnchor.solcontract (@foundryprotocol/0gkit-contracts).
Compatible bases
react-app · chat · tee-attested-api · mcp-agent
Apply
# scaffold-time
npm create 0gkit-app -- --kits ai-oracle
# add to an existing project
0g add ai-oracle
Environment variables
| Variable | Example | Notes |
|---|---|---|
OG_COMPUTE_MODEL | neuralmagic/Meta-Llama-3.1-70B-Instruct-FP8 | Model for inference (optional — provider default if omitted) |
OG_PRIVATE_KEY | 0x... | Operator key for signing receipts and 0G transactions |
OG_RPC_URL | https://evmrpc-testnet.0g.ai | 0G chain RPC endpoint |
OG_ANCHOR_ONCHAIN | 1 | Set to 1 to commit receipts on-chain via Anchor.sol (default: 0G Storage) |
OG_ANCHOR_ADDRESS | 0x... | Deployed Anchor.sol address — required when OG_ANCHOR_ONCHAIN=1 |
Quick start
0g add ai-oracle
resolveOracle(deps, question) runs inference → hashes the answer → signs the
receipt → anchors it. deps is injected; here is the default wiring the
react-app adapter builds (compute router + signed-receipt attestor + 0G
Storage anchor). The .env keys are the ones in the table above:
import { Compute } from "@foundryprotocol/0gkit-compute";
import { Storage } from "@foundryprotocol/0gkit-storage";
import { digestJson } from "@foundryprotocol/0gkit-core";
import { fromPrivateKey } from "@foundryprotocol/0gkit-wallet";
import { recoverSigner } from "@foundryprotocol/0gkit-attestation";
import { resolveOracle, type Attestor, type Anchor } from "./lib/oracle.js";
const privateKey = process.env.OG_PRIVATE_KEY as `0x${string}`;
const signer = await fromPrivateKey(privateKey);
const compute = new Compute({ signer });
const infer = {
async infer({ prompt, model }: { prompt: string; model?: string }) {
const r = await compute.router({
messages: [{ role: "user" as const, content: prompt }],
...(model ? { model } : {}),
});
return { output: r.output };
},
};
const attestor: Attestor = {
async sign(receipt) {
const digest = digestJson(receipt);
return { digest, signature: await signer.signMessage({ raw: digest }) };
},
async verify(receipt, signed, expectedSigner) {
const match = digestJson(receipt).toLowerCase() === signed.digest.toLowerCase();
const recovered = await recoverSigner({
digest: signed.digest as `0x${string}`,
signature: signed.signature as `0x${string}`,
});
return {
ok: match && recovered.toLowerCase() === expectedSigner.toLowerCase(),
signer: recovered,
};
},
};
const storage = new Storage({ privateKey, rpcUrl: process.env.OG_RPC_URL! });
const anchor: Anchor = {
async anchor(payload) {
const bytes =
typeof payload === "string" ? new TextEncoder().encode(payload) : payload;
const { root } = await storage.upload(bytes);
return { ref: root, kind: "storage" };
},
};
const result = await resolveOracle(
{ infer, attestor, anchor, model: process.env.OG_COMPUTE_MODEL },
"Will 0G mainnet launch in 2026?"
);
console.log(result.answer, result.answerHash, result.commitment); // { ref, kind: "storage" }
Honesty caveat:
attestationis a signed receipt (operator key signsdigestJson(receipt)via EIP-191), not a TEE-quote. The badge means "the expected operator signed this exact receipt" — swap theAttestorfor a real TEE-quote verifier later without touchingresolveOracle.
Tiers
- lib —
lib/oracle.ts(portableresolveOracle+OracleReceipttype),lib/anchor-abi.ts(ABI constant for the optional on-chain anchor). - adapters — one per base (
app/api/oracle/route.tsfor Next.js,src/routes/oracle.tsfor Hono,src/tools/oracle.tsfor MCP). - contracts —
Anchor.sol+ deploy script (opt-in on-chain path only).
Honesty note
The attestation layer signs digestJson(receipt) via EIP-191 personal-sign
(signMessage); verification recovers the signer via recoverSigner. There
is no TEE quote verification in the current stack. The badge is always
"✓ signature verified" — never "TEE attested". The Attestor interface is
injected so a real TEE-quote verifier can slot in later without changing
calling code.