Summary
Out of the box, the TS SDK (opengradient-sdk@2.1.1) cannot perform any LLM inference on the current OpenGradient testnet. The default TEE registry address points to a deprecated registry with 0 active LLM-proxy TEEs, so TEE discovery always fails. The maintained Python SDK (1.1.0) points to a different, current registry that has live TEEs.
The paid path itself (x402 + Permit2 on Base) works fine: this is purely a discovery problem.
Reproduction
import { Client } from 'opengradient-sdk';
const client = new Client(/* default config */);
await client.llm.chat({ model: 'anthropic/claude-haiku-4-5', messages: [...] });
Fails, after a successful Permit2 approval, with:
TEE LLM request failed and registry refresh failed:
Error: No active LLM proxy TEE found in the registry.
Root cause
Both SDKs use the same network (testnet, RPC https://ogevmdevnet.opengradient.ai, chain id 10740) and the same discovery call getActiveTEEs(TEE_TYPE_LLM_PROXY=0), but differ in two coordinated ways:
|
TS SDK 2.1.1 |
Python SDK 1.1.0 |
| Default registry address |
0x4e72238852f3c918f4E4e57AeC9280dDB0c80248 |
0x703cB174AEadB35D611858369B4b1111dC9Abda6 |
getActiveTEEs struct |
10 fields |
11 fields (+ ohttpConfig) |
- TS:
src/defaults.ts (address), src/abi/teeRegistry.ts (getActiveTEEs struct ends at lastHeartbeatAt, no ohttpConfig).
- Because the structs differ, overriding
teeRegistryAddress to the new address on the released SDK is not enough: viem decodes tuples positionally and throws on the extra field (caught internally, returns [], surfaces as "No active TEE").
Evidence (read-only, on-chain)
Queried both registries directly with viem on the testnet RPC, using the Python (new) ABI:
NEW 0x703c -> 3 active LLM-proxy TEE(s) (enabled=true, hasTLS=true)
OLD 0x4e72 -> 0 active LLM-proxy TEE(s)
Confirmed end to end by pointing a Client at one of the new registry's endpoints via llmServerUrl (bypasses discovery): real inference returns a valid teeSignature (TEE attestation) and usage. So payment + attestation work, only registry discovery is broken.
Proposed fix
src/defaults.ts : bump DEFAULT_TEE_REGISTRY_ADDRESS to 0x703cB174AEadB35D611858369B4b1111dC9Abda6.
src/abi/teeRegistry.ts : append ohttpConfig to the getActiveTEEs output struct so viem can decode the current registry (copy the OhttpConfig components verbatim from the Python ABI opengradient/abi/TEERegistry.abi). The reading code in src/teeRegistry.ts does not need to change (it only uses endpoint/tlsCertificate/paymentAddress/publicKey).
Workaround today
Pass llmServerUrl with an endpoint read from the new registry. This bypasses on-chain discovery and TLS pinning (rejectUnauthorized: false), so it is fine for dev but not the secure production path.
Open question
Can a maintainer confirm 0x703cB174…Abda6 is the canonical current registry (not just one of several deployments)? Happy to send a PR bumping the default address + extending the ABI once confirmed.
Context
I hit this while building a community OpenGradient provider for the Vercel AI SDK: opengradient-ai-provider (npm), so OpenGradient inference is usable through that ecosystem (one of the most widely used TS toolkits for LLM apps). This bug blocks the default zero-config path; the current workaround is passing llmServerUrl manually, which also disables on-chain TLS pinning. PR #11 proposes the fix.
Summary
Out of the box, the TS SDK (
opengradient-sdk@2.1.1) cannot perform any LLM inference on the current OpenGradient testnet. The default TEE registry address points to a deprecated registry with 0 active LLM-proxy TEEs, so TEE discovery always fails. The maintained Python SDK (1.1.0) points to a different, current registry that has live TEEs.The paid path itself (x402 + Permit2 on Base) works fine: this is purely a discovery problem.
Reproduction
Fails, after a successful Permit2 approval, with:
Root cause
Both SDKs use the same network (testnet, RPC
https://ogevmdevnet.opengradient.ai, chain id10740) and the same discovery callgetActiveTEEs(TEE_TYPE_LLM_PROXY=0), but differ in two coordinated ways:0x4e72238852f3c918f4E4e57AeC9280dDB0c802480x703cB174AEadB35D611858369B4b1111dC9Abda6getActiveTEEsstructohttpConfig)src/defaults.ts(address),src/abi/teeRegistry.ts(getActiveTEEsstruct ends atlastHeartbeatAt, noohttpConfig).teeRegistryAddressto the new address on the released SDK is not enough: viem decodes tuples positionally and throws on the extra field (caught internally, returns[], surfaces as "No active TEE").Evidence (read-only, on-chain)
Queried both registries directly with viem on the testnet RPC, using the Python (new) ABI:
Confirmed end to end by pointing a
Clientat one of the new registry's endpoints viallmServerUrl(bypasses discovery): real inference returns a validteeSignature(TEE attestation) and usage. So payment + attestation work, only registry discovery is broken.Proposed fix
src/defaults.ts: bumpDEFAULT_TEE_REGISTRY_ADDRESSto0x703cB174AEadB35D611858369B4b1111dC9Abda6.src/abi/teeRegistry.ts: appendohttpConfigto thegetActiveTEEsoutput struct so viem can decode the current registry (copy theOhttpConfigcomponents verbatim from the Python ABIopengradient/abi/TEERegistry.abi). The reading code insrc/teeRegistry.tsdoes not need to change (it only usesendpoint/tlsCertificate/paymentAddress/publicKey).Workaround today
Pass
llmServerUrlwith an endpoint read from the new registry. This bypasses on-chain discovery and TLS pinning (rejectUnauthorized: false), so it is fine for dev but not the secure production path.Open question
Can a maintainer confirm
0x703cB174…Abda6is the canonical current registry (not just one of several deployments)? Happy to send a PR bumping the default address + extending the ABI once confirmed.Context
I hit this while building a community OpenGradient provider for the Vercel AI SDK:
opengradient-ai-provider(npm), so OpenGradient inference is usable through that ecosystem (one of the most widely used TS toolkits for LLM apps). This bug blocks the default zero-config path; the current workaround is passingllmServerUrlmanually, which also disables on-chain TLS pinning. PR #11 proposes the fix.