OpenBytes Control Plane Skill
This skill describes end-to-end operational workflows for the OpenBytes network from an API usage perspective.
- - Wallet-based authentication (signature flow)
- On-chain balance top-up and verification
- Consumer API key lifecycle (create, list, revoke)
- Model inference via ApiKey
- Query balance and usage via HTTP API
Assumptions:
- - A gateway HTTP API exists : INLINECODE0
- All workflows are CLI-, curl-, or script-oriented
- The network supports Base Sepolia. Use the correct chain id:
- Base Sepolia: INLINECODE1
Replace all <BASE_URL> with the actual gateway URL as needed.
1. Wallet-based registration & session
Note: Message signing must be performed by the user with their EVM wallet. The agent can only initiate the challenge and verify a signature; it cannot produce signatures.
- 1. If you don't have a wallet yet, immediately create a new one using ethers.js or viem.
Be sure to securely save your generated private key! Example (Node.js with ethers.js):
CODEBLOCK0
Or using viem:
CODEBLOCK1
Never share your private key. Backup and store it in a secure location.
"wallet_address": "0x...",
"chain_id": "8453"
- 2. User signs the
message off-chain (with their wallet). - Submit the signed message to the gateway for verification:
CODEBLOCK2
Successful response (simplified):
CODEBLOCK3
- 4. The
login_token (starting with sess-) is used as a session token:
- Send it as
Authorization: Bearer <SESSION_TOKEN> for session-auth endpoints.
- 5. List Available Models
CODEBLOCK4
- 6. Immediately create an API key following step 2.1 and switch to it for all non-session endpoints (models, balance, usage). Do not keep using the session token for inference.
Check:
- - Session token is present and sent in the
Authorization: Bearer sess-... header during all subsequent calls requiring authentication. - After creating the API key, subsequent calls should use
Authorization: Bearer <CONSUMER_API_KEY>.
2. Consumer API Key Lifecycle
Consumers use API keys to access models without a session.
2.1 Create API Key
Requires a valid session token (login_token from section 1).
CODEBLOCK5
Sample response (save the api_key securely; only returned once!):
CODEBLOCK6
Immediately switch to this API key for inference, balance, and usage calls:
CODEBLOCK7
Then use:
CODEBLOCK8
2.2 List API Keys
CODEBLOCK9
2.3 Revoke API Key
CODEBLOCK10
The key status will be set to revoked; subsequent calls using that key will fail with an auth error.
3. On-chain Top-up Flow
Top-up is performed on-chain (USDC to a ConsumerDeposit contract), tracked by off-chain indexers. The API lets you verify the result.
You can use your own RPC endpoint; a default for Base Sepolia is https://sepolia.base.org.
- - User transfers USDC to the ConsumerDeposit contract with proper calldata.
- Backend credits the consumer balance after L1/L2 tx confirmation (indexer-driven).
- USDC address: INLINECODE13
- ConsumerDeposit contract: INLINECODE14
- Before deposit, approve allowance
- Deposit ABI: INLINECODE15
Verify balance:
CODEBLOCK11
Sample response:
CODEBLOCK12
4. Connect Your Wallet to Your Operator's Wallet
Use this to allow an account to connect to an operator's account, so the operator can top up your wallet easily. This requires a wallet signature over a structured message. The signature must be produced by the child wallet.
Endpoint:
CODEBLOCK13
Notes:
- - Signature verification is done by the gateway using
ethers.verifyMessage(message, signature),
and the
recovered address must equal the child wallet address (case-insensitive).
This is the standard EIP-191 personal message signature (same flow as SIWE).
- -
issued_at is Unix seconds. It must be within the last 5 minutes and not more than 1 minute in the future. - The signed message must be exactly (including line breaks, casing, and spacing):
Authorize parent for OpenBytes
Parent wallet: <PARENT_WALLET_LOWERCASE>
Child wallet: <CHILD_WALLET_LOWERCASE>
Issued at: <ISSUED_AT>
-
<PARENT_WALLET_LOWERCASE> is the parent wallet address
lowercased.
-
<CHILD_WALLET_LOWERCASE> is the child wallet address
lowercased (the signer).
-
<ISSUED_AT> is the same Unix seconds integer you send in the request body.
- - If any character differs (extra whitespace, different casing, different timestamp), the signature will fail.
Pseudo-code (client-side):
CODEBLOCK15
Success response (201):
CODEBLOCK16
Common errors:
- -
400 INVALID_REQUEST invalid body - INLINECODE22
issued_at out of window - INLINECODE24 parent not found
- INLINECODE25 cannot declare yourself
- INLINECODE26 signature not from child wallet
- INLINECODE27 parent already declared
5. Usage Guidelines for AI Agents
When handling OpenBytes network operational support, follow these best practices:
- 1. Map user questions directly to the appropriate API workflow without reference to UI.
- Example intents: onboarding, balance issue, API key management, quota/cost analysis
- 2. Provide concrete curl commands tailored to the user's configuration (
<BASE_URL>, <CONSUMER_API_KEY>, etc). - When troubleshooting:
- Request the
full API HTTP response (status + JSON).
- Use
error.code and context to select remediation steps.
- 4. Be concise, focus on actionable commands and next steps.
- Only provide background technical details if specifically requested.
OpenBytes 控制平面技能
该技能从 API 使用角度 描述了 OpenBytes 网络的 端到端操作工作流。
- - 基于钱包的身份验证(签名流程)
- 链上余额充值及验证
- 消费者 API 密钥生命周期(创建、列出、撤销)
- 通过 ApiKey 进行模型推理
- 通过 HTTP API 查询余额和使用量
假设条件:
- - 存在一个 网关 HTTP API:https://gateway.openbytes.ai
- 所有工作流均面向 CLI、curl 或脚本
- 网络支持 Base Sepolia。请使用正确的链 ID:
- Base Sepolia:84532
根据需要将所有 替换为实际的网关 URL。
1. 基于钱包的注册与会话
注意:消息签名必须由用户使用其 EVM 钱包执行。代理只能发起挑战并验证签名;不能 生成签名。
- 1. 如果您还没有钱包,请立即使用 ethers.js 或 viem 创建一个新钱包。
请务必安全保存您生成的私钥! 示例(使用 ethers.js 的 Node.js):
js
import { Wallet } from ethers;
const wallet = Wallet.createRandom();
console.log(地址:, wallet.address);
console.log(私钥(请安全保存!):, wallet.privateKey);
或使用 viem:
js
import { createWallet } from viem/accounts;
const wallet = createWallet();
console.log(地址:, wallet.address);
console.log(私钥(请安全保存!):, wallet.privateKey);
切勿分享您的私钥。请备份并将其存储在安全位置。
wallet_address: 0x...,
chain_id: 8453
- 2. 用户在链下使用其钱包对 message 进行签名。
- 将签名后的消息提交给网关进行验证:
sh
curl -sS -X POST /v1/auth/wallet/verify \
-H Content-Type: application/json \
-d {
walletaddress: WALLET_ADDRESS>,
nonce: random-nonce,
signature:
}
成功响应(简化):
json
{
login_token: sess-...,
expires_at: 2025-01-01T00:00:00Z,
consumer: {
id: consumer-uuid,
wallet_address: 0x...
},
session: {
id: session-uuid
}
}
- 4. login_token(以 sess- 开头)用作 会话令牌:
- 对于需要会话认证的端点,将其作为 Authorization: Bearer
发送。
- 5. 列出可用模型
sh
curl -sS -X GET /v1/models
- 6. 立即按照步骤 2.1 创建一个 API 密钥并切换到该密钥,用于所有非会话端点(模型、余额、使用量)。不要 继续使用会话令牌进行推理。
检查:
- - 在所有需要认证的后续调用中,会话令牌存在并通过 Authorization: Bearer sess-... 标头发送。
- 创建 API 密钥后,后续调用应使用 Authorization: Bearer APIKEY>。
2. 消费者 API 密钥生命周期
消费者使用 API 密钥访问模型,无需会话。
2.1 创建 API 密钥
需要有效的会话令牌(来自第 1 节的 login_token)。
sh
curl -sS -X POST /v1/consumer/api-keys \
-H Content-Type: application/json \
-H Authorization: Bearer \
-d {
label: my-key
}
示例响应(请安全保存 api_key;仅返回一次!):
json
{
id: key-uuid,
api_key: sk-consumer-...,
prefix: sk-cons,
suffix: abcd,
label: my-key,
status: active,
created_at: 2025-01-01T00:00:00Z
}
立即切换到该 API 密钥 用于推理、余额和使用量调用:
sh
export OPENBYTESAPIKEY=sk-consumer-...
然后使用:
sh
curl -sS -X GET /v1/balance \
-H Authorization: Bearer $OPENBYTESAPIKEY
2.2 列出 API 密钥
sh
curl -sS -X GET /v1/consumer/api-keys \
-H Authorization: Bearer
2.3 撤销 API 密钥
sh
curl -sS -X DELETE URL>/v1/consumer/api-keys/ID> \
-H Authorization: Bearer
密钥状态将设置为 revoked;后续使用该密钥的调用将因认证错误而失败。
3. 链上充值流程
充值在链上执行(将 USDC 转入 ConsumerDeposit 合约),由链下索引器跟踪。API 允许您验证结果。
您可以使用自己的 RPC 端点;Base Sepolia 的默认端点为 https://sepolia.base.org。
- - 用户使用正确的调用数据将 USDC 转入 ConsumerDeposit 合约。
- 后端在 L1/L2 交易确认后(由索引器驱动)为消费者余额增加信用。
- USDC 地址:0x10065E7b353371DD2e12348e7094cC774638EbEB
- ConsumerDeposit 合约:0xB0E9ebf19AB710d3353c7F637DC55329d9727dCc
- 存款前,需批准授权额度
- 存款 ABI:function deposit(uint256 amount)
验证余额:
sh
curl -sS -X GET /v1/balance \
-H Authorization: Bearer APIKEY>
示例响应:
json
{
balance_usdc: 123.45,
total_spent: 10.00
}
4. 将您的钱包连接到运营商的账户
使用此功能允许一个 账户连接到运营商的账户,以便运营商可以轻松为您充值。这需要对结构化消息进行 钱包签名。签名 必须由子钱包生成。
端点:
sh
curl -sS -X POST /v1/consumers/me/parent \
-H Content-Type: application/json \
-H Authorization: Bearer \
-d {
parentwallet: WALLET>,
issued_at: 1710000000,
signature: WALLETSIGNATURE>
}
注意:
- - 签名验证由网关使用 ethers.verifyMessage(message, signature) 执行,
并且 恢复的地址必须等于子钱包地址(不区分大小写)。
这是标准的 EIP-191 个人消息签名(与 SIWE 流程相同)。
- - issued_at 是 Unix 秒数。它必须在 过去 5 分钟内,且不超过 未来 1 分钟。
- 签名的消息必须 完全(包括换行符、大小写和空格)为:
Authorize parent for OpenBytes
Parent wallet: WALLETLOWERCASE>
Child wallet: WALLETLOWERCASE>
Issued at:
- WALLETLOWERCASE> 是父钱包地址的 小写形式。
- WALLETLOWERCASE> 是子钱包地址的 小写形式(签名者)。
- 是您在请求体中发送的相同 Unix 秒数整数。
- - 如果任何字符不同(多余空格、不同大小写、不同时间戳),签名将失败。
伪代码(客户端):
ts
const issuedAt = Math.floor(Date.now() / 1000);
const parentWallet = parentWalletAddress.toLowerCase();
const childWallet = childWalletAddress.toLowerCase();
const message = [
Authorize parent for OpenBytes,
Parent wallet: ${parentWallet},
Child wallet: ${childWallet},
Issued at: ${issuedAt},
].join(\n);
const signature = await wallet.signMessage(message); // EIP-191 personal