@bnbagent/studio-cli 0.0.6-alpha.6 → 0.0.6-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,69 +1,42 @@
1
1
  ---
2
2
  name: bnbagent-studio-wiring-llm-tools
3
- description: When the user wants their agent's LLM to call read-only chain queries (wallet balance, ERC-8004 agent info, ERC-8183 job status, etc.) exposes the 15 functions in `@bnbagent/studio-runtime/tools` as LLM tools via AI SDK `tool()` wrappers, or any other TS agent framework.
3
+ description: When the user wants their agent's LLM to call read-only chain queries (wallet balance, ERC-8004 agent info, ERC-8183 job status, etc.) - exposes the 15 functions in `@bnbagent/studio-runtime/tools` as LLM tools via AI SDK `tool()` wrappers, or any other TS agent framework.
4
4
  ---
5
5
 
6
- > **Reference file** of the `bnbagent-studio` router skill installed at `bnbagent-studio/references/` and loaded on demand (not a standalone skill). Route here via the router's decision tree.
6
+ > **Reference file** of the `bnbagent-studio` router skill - installed at `bnbagent-studio/references/` and loaded on demand (not a standalone skill). Route here via the router's decision tree.
7
7
 
8
8
  # bnbagent-studio-wiring-llm-tools
9
9
 
10
- Wire `bnbagent-studio`'s 15 chain readonly functions into the user's agent so
11
- the LLM can autonomously query wallet, balance, ERC-8004 identity, ERC-8183
12
- jobs, etc. Studio ships the pure functions plus two emitted wrapper files: the
13
- runtime recipe's curated default (`app/agent/src/tools.ts`, `LLM_READ_TOOLS`)
14
- and the full-inventory `tools-chain` recipe
15
- (`tools-chain/code/{{PKG}}/chainTools.ts.tmpl`, emitted as
16
- `app/agent/src/chainTools.ts`); for a non-AI-SDK framework you (Claude Code)
17
- write a thin wrapping file in the Agent sub-project.
18
-
19
- In v1 the workspace contains one sub-project, `app/agent/` — the single
20
- selected-faces seller runtime. LLM tools always live in
21
- **`app/agent/src/tools.ts`**. The `{{PKG}}` recipe variable resolves to the
22
- agent's `src/` dir, so the emit target is `app/agent/src/tools.ts` — its
23
- meaning is "source dir of the agent sub-project", not "package inside a
24
- single-root project".
10
+ Wire `bnbagent-studio`'s 15 chain readonly functions into the user's agent so the LLM can autonomously query wallet, balance, ERC-8004 identity, ERC-8183 jobs, etc. Studio ships the pure functions plus two emitted wrapper files: the runtime recipe's curated default (`app/agent/src/tools.ts`, `LLM_READ_TOOLS`) and the full-inventory `tools-chain` recipe (`tools-chain/code/{{PKG}}/chainTools.ts.tmpl`, emitted as `app/agent/src/chainTools.ts`); for a non-AI-SDK framework you (Claude Code) write a thin wrapping file in the Agent sub-project.
11
+
12
+ In v1 the workspace contains one sub-project, `app/agent/` - the single selected-faces seller runtime. LLM tools always live in **`app/agent/src/tools.ts`**. The `{{PKG}}` recipe variable resolves to the agent's `src/` dir, so the emit target is `app/agent/src/tools.ts` - its meaning is "source dir of the agent sub-project", not "package inside a single-root project".
25
13
 
26
14
  ## Audience
27
15
 
28
- Claude Code (or another agent) editing the user's workspace. The user has run
29
- `bag init` and wants their Agent sub-project to expose read-only chain queries
30
- to its LLM (`app/agent/src/tools.ts`). These are READ-ONLY — the Agent's
31
- signing always stays in `app/agent/src/signing.ts` (fixed code), never an LLM
32
- tool.
16
+ Claude Code (or another agent) editing the user's workspace. The user has run `bag init` and wants their Agent sub-project to expose read-only chain queries to its LLM (`app/agent/src/tools.ts`). These are READ-ONLY - the Agent's signing always stays in `app/agent/src/signing.ts` (fixed code), never an LLM tool.
33
17
 
34
18
  ## When to use this skill
35
19
 
36
- - The user says "let my agent query its balance" / "agent should know about its
37
- on-chain jobs" / "give the LLM access to chain state"
38
- - The user wants to wire chain tools into a **non-AI-SDK** stack (LangChain.js,
39
- a bare OpenAI/Anthropic SDK tool loop, custom)
20
+ - The user says "let my agent query its balance" / "agent should know about its on-chain jobs" / "give the LLM access to chain state"
21
+ - The user wants to wire chain tools into a **non-AI-SDK** stack (LangChain.js, a bare OpenAI/Anthropic SDK tool loop, custom)
40
22
  - The user wants to **customize** which chain queries their LLM sees
41
23
  - The user uses `bag init` but wants to extend / re-emit the tool list
42
24
 
43
25
  ## When NOT to use this skill
44
26
 
45
- - The user wants the Agent to **sign transactions / pay** in the single seller
46
- model all signing (quote-sign, submit, settle) is FIXED code
47
- in `app/agent/src/signing.ts` (called by A2A's `SellerAgentExecutor` or MCP's
48
- `src/mcpMain.ts` tools), **never** an
49
- LLM-callable tool. The LLM only produces work text after a job is verified
50
- funded; fixed code prices, clamps, signs, and submits. There is no "wire a
51
- signing tool into the LLM" path in v1.
52
- - The user is doing dev-time debugging via Claude Code — that's the `bag` CLI
53
- read commands (`bag wallet`, `bag erc8183 status/list`, …), not LLM tools.
27
+ - The user wants the Agent to **sign transactions / pay** - in the single seller model all signing (quote-sign, submit, settle) is FIXED code in `app/agent/src/signing.ts` (called by A2A's `SellerAgentExecutor` or MCP's `src/mcpMain.ts` tools), **never** an LLM-callable tool. The LLM only produces work text after a job is verified funded; fixed code prices, clamps, signs, and submits. There is no "wire a signing tool into the LLM" path in v1.
28
+ - The user is doing dev-time debugging via Claude Code - that's the `bag` CLI read commands (`bag wallet`, `bag erc8183 status/list`, …), not LLM tools.
54
29
 
55
30
  ---
56
31
 
57
32
  ## The 15 functions
58
33
 
59
- All in `@bnbagent/studio-runtime/tools`. Each returns a plain object (or
60
- string); the wire-format keys stay snake_case (the tool contract shared with
61
- LLMs and MCP clients).
34
+ All in `@bnbagent/studio-runtime/tools`. Each returns a plain object (or string); the wire-format keys stay snake_case (the tool contract shared with LLMs and MCP clients).
62
35
 
63
- ### Wallet & chain basics always safe
36
+ ### Wallet & chain basics - always safe
64
37
 
65
38
  | Function | Reads | Dependency |
66
- |---|---|---|
39
+ | --- | --- | --- |
67
40
  | `walletInfo()` | active wallet address + source + keystore dir | none |
68
41
  | `walletAddress()` | active wallet address (alias of walletInfo) | none |
69
42
  | `walletList()` | all configured keystore addresses | dev concern |
@@ -72,26 +45,25 @@ LLMs and MCP clients).
72
45
  | `networkInfo(network?)` | chain id, RPC host, contract addresses | none |
73
46
  | `txStatus(txHash, network?)` | tx receipt + revert reason | none |
74
47
 
75
- ### LLM provider Pieverse-specific
48
+ ### LLM provider - Pieverse-specific
76
49
 
77
50
  | Function | Reads | Dependency |
78
- |---|---|---|
51
+ | --- | --- | --- |
79
52
  | `pieverseUsage(days=7)` | LLM spend on Pieverse | `[llm.provider=pieverse-llm]` |
80
53
 
81
- Note: `pieverseUsage` does a SIWE EIP-191 personal_sign (no on-chain effect,
82
- domain-locked). Other functions are pure RPC reads.
54
+ Note: `pieverseUsage` does a SIWE EIP-191 personal_sign (no on-chain effect, domain-locked). Other functions are pure RPC reads.
83
55
 
84
56
  ### ERC-8004 identity
85
57
 
86
58
  | Function | Reads | Dependency |
87
- |---|---|---|
59
+ | --- | --- | --- |
88
60
  | `agentInfo(agentId, network?)` | on-chain ERC-8004 record by ID | `[erc8004]` |
89
61
  | `agentByAddress(address, network?)` | look up agent by owner address | `[erc8004]` |
90
62
 
91
63
  ### ERC-8183 jobs
92
64
 
93
65
  | Function | Reads | Dependency |
94
- |---|---|---|
66
+ | --- | --- | --- |
95
67
  | `jobStatus(jobId, network?)` | job state, client, provider, budget | `[erc8183]` |
96
68
  | `jobList(limit=10, mine=false, provider?, network?)` | recent jobs | `[erc8183]` |
97
69
  | `jobCount(network?)` | network-wide inflight job count | `[erc8183]` |
@@ -99,31 +71,29 @@ domain-locked). Other functions are pure RPC reads.
99
71
  ### Advanced / footguns
100
72
 
101
73
  | Function | Reads | Why footgun |
102
- |---|---|---|
74
+ | --- | --- | --- |
103
75
  | `blockInfo(block?, network?)` | block summary | usually noise for LLM |
104
- | `contractCallView(address, functionSignature, args?, outputTypes?, network?)` | arbitrary `eth_call` | accepts **any** ABI LLM can be prompt-injected into calling attacker contracts |
76
+ | `contractCallView(address, functionSignature, args?, outputTypes?, network?)` | arbitrary `eth_call` | accepts **any** ABI - LLM can be prompt-injected into calling attacker contracts |
105
77
 
106
78
  ---
107
79
 
108
- ## Step 1 Confirm the user has run `bag init`
80
+ ## Step 1 - Confirm the user has run `bag init`
109
81
 
110
82
  ```bash
111
83
  # from workspace root:
112
84
  ls app/agent/studio.toml && (ls app/agent/src/main.ts 2>/dev/null || ls app/agent/src/mcpMain.ts)
113
85
  ```
114
86
 
115
- If `app/agent/src/tools.ts` already exists, the user has the AI SDK form
116
- already. Skip to Step 4 if they want to customize.
87
+ If `app/agent/src/tools.ts` already exists, the user has the AI SDK form already. Skip to Step 4 if they want to customize.
117
88
 
118
89
  ---
119
90
 
120
- ## Step 2 Identify the stack
91
+ ## Step 2 - Identify the stack
121
92
 
122
- Look at `app/agent/src/main.ts` or `app/agent/src/mcpMain.ts` imports /
123
- `app/agent/package.json`:
93
+ Look at `app/agent/src/main.ts` or `app/agent/src/mcpMain.ts` imports / `app/agent/package.json`:
124
94
 
125
95
  | Sign in code | Stack |
126
- |---|---|
96
+ | --- | --- |
127
97
  | `import { tool, generateText } from "ai"` | **AI SDK** (use stock recipe) |
128
98
  | `from "langchain"` / `from "@langchain/core"` | **LangChain.js** |
129
99
  | `openai.chat.completions.create({ tools: ... })` | **bare OpenAI SDK loop** |
@@ -135,8 +105,7 @@ If AI SDK: emit the stock recipe and stop.
135
105
  bag recipe code tools-chain > app/agent/src/chainTools.ts # full inventory + CHAIN_READ_TOOLS
136
106
  ```
137
107
 
138
- Then in the protocol entrypoint (`app/agent/src/main.ts` for A2A,
139
- `app/agent/src/mcpMain.ts` for MCP), pass the tool set into the generate call:
108
+ Then in the protocol entrypoint (`app/agent/src/main.ts` for A2A, `app/agent/src/mcpMain.ts` for MCP), pass the tool set into the generate call:
140
109
 
141
110
  ```ts
142
111
  import { LLM_READ_TOOLS } from "./tools.js";
@@ -148,11 +117,9 @@ For non-AI-SDK stacks, continue.
148
117
 
149
118
  ---
150
119
 
151
- ## Step 3 Write a framework-specific wrapper
120
+ ## Step 3 - Write a framework-specific wrapper
152
121
 
153
- Studio doesn't ship adapters for non-AI-SDK stacks (commitment: "agent code
154
- the user owns"). You write a wrapper file in the user's project. Pattern:
155
- import the pure functions, wrap each with the framework's tool primitive.
122
+ Studio doesn't ship adapters for non-AI-SDK stacks (commitment: "agent code the user owns"). You write a wrapper file in the user's project. Pattern: import the pure functions, wrap each with the framework's tool primitive.
156
123
 
157
124
  ### LangChain.js
158
125
 
@@ -168,17 +135,23 @@ export const LLM_READ_TOOLS = [
168
135
  description: "Describe the agent's active wallet.",
169
136
  schema: z.object({}),
170
137
  }),
171
- tool(async ({ address, network }) => cr.balanceNative(address ?? null, network),
138
+ tool(
139
+ async ({ address, network }) => cr.balanceNative(address ?? null, network),
172
140
  {
173
141
  name: "balance_native",
174
- description: "Native BNB balance of an address (defaults to the agent's wallet).",
175
- schema: z.object({ address: z.string().optional(), network: z.string().optional() }),
176
- }),
142
+ description:
143
+ "Native BNB balance of an address (defaults to the agent's wallet).",
144
+ schema: z.object({
145
+ address: z.string().optional(),
146
+ network: z.string().optional(),
147
+ }),
148
+ },
149
+ ),
177
150
  // balanceU (requires [u_token]), networkInfo, txStatus,
178
151
  // pieverseUsage (requires [llm.provider=pieverse-llm]),
179
152
  // agentInfo / agentByAddress (require [erc8004]),
180
- // jobStatus / jobList (require [erc8183]) same pattern.
181
- // ⚠️ contractCallView accepts any ABI keep it out unless deliberate.
153
+ // jobStatus / jobList (require [erc8183]) - same pattern.
154
+ // ⚠️ contractCallView accepts any ABI - keep it out unless deliberate.
182
155
  ];
183
156
  ```
184
157
 
@@ -186,14 +159,16 @@ Wire into the agent (e.g. `createReactAgent({ llm, tools: LLM_READ_TOOLS })`).
186
159
 
187
160
  ### Bare OpenAI / Anthropic tool loop
188
161
 
189
- For a hand-rolled tool loop, declare each function in the provider's tool JSON
190
- format and dispatch on the tool name:
162
+ For a hand-rolled tool loop, declare each function in the provider's tool JSON format and dispatch on the tool name:
191
163
 
192
164
  ```ts
193
165
  // app/agent/src/tools.ts
194
166
  import * as cr from "@bnbagent/studio-runtime/tools";
195
167
 
196
- export const CHAIN_READ_FUNCTIONS: Record<string, (args: any) => Promise<unknown>> = {
168
+ export const CHAIN_READ_FUNCTIONS: Record<
169
+ string,
170
+ (args: any) => Promise<unknown>
171
+ > = {
197
172
  wallet_info: async () => cr.walletInfo(),
198
173
  balance_native: async (a) => cr.balanceNative(a.address ?? null, a.network),
199
174
  balance_u: async (a) => cr.balanceU(a.address ?? null, a.network), // requires [u_token]
@@ -208,14 +183,11 @@ export const CHAIN_READ_FUNCTIONS: Record<string, (args: any) => Promise<unknown
208
183
 
209
184
  ### Generic
210
185
 
211
- For any framework that accepts a typed function + description, the pattern is
212
- identical — wrap each `cr.*` function in the framework's tool primitive and
213
- assemble a list. The emitted AI SDK files (`tools.ts` / `chainTools.ts`)
214
- already carry per-tool descriptions and zod input schemas you can copy from.
186
+ For any framework that accepts a typed function + description, the pattern is identical - wrap each `cr.*` function in the framework's tool primitive and assemble a list. The emitted AI SDK files (`tools.ts` / `chainTools.ts`) already carry per-tool descriptions and zod input schemas you can copy from.
215
187
 
216
188
  ---
217
189
 
218
- ## Step 4 Customize what the LLM sees
190
+ ## Step 4 - Customize what the LLM sees
219
191
 
220
192
  The recipe gives a sensible default; the user owns the file. Common edits:
221
193
 
@@ -223,7 +195,7 @@ The recipe gives a sensible default; the user owns the file. Common edits:
223
195
 
224
196
  ```ts
225
197
  export const LLM_READ_TOOLS: ToolSet = {
226
- balance_u: CHAIN_READ_TOOLS.balance_u, // only thing this agent really needs
198
+ balance_u: CHAIN_READ_TOOLS.balance_u, // only thing this agent really needs
227
199
  tx_status: CHAIN_READ_TOOLS.tx_status,
228
200
  };
229
201
  ```
@@ -234,41 +206,19 @@ export const LLM_READ_TOOLS: ToolSet = {
234
206
  pieverse_usage: ..., // requires [llm.provider=pieverse-llm]
235
207
  ```
236
208
 
237
- **Uncomment 8004 / 8183 reads** if the user added those sections to
238
- `studio.toml` after `bag init` (e.g., ran `bag erc8004 register` later).
209
+ **Uncomment 8004 / 8183 reads** if the user added those sections to `studio.toml` after `bag init` (e.g., ran `bag erc8004 register` later).
239
210
 
240
- **Never uncomment** `contract_call_view` without thinking it accepts any ABI
241
- signature and an LLM jailbreak / prompt injection can drain via reads from
242
- malicious contracts (or hammer expensive RPC). Keep commented unless the
243
- agent has a specific debug / introspection job and the user has read the
244
- tool description.
211
+ **Never uncomment** `contract_call_view` without thinking - it accepts any ABI signature and an LLM jailbreak / prompt injection can drain via reads from malicious contracts (or hammer expensive RPC). Keep commented unless the agent has a specific debug / introspection job and the user has read the tool description.
245
212
 
246
213
  ---
247
214
 
248
- ## Step 5 Write operations live in fixed code, NOT LLM tools
249
-
250
- Read tools (this skill) are safe-ish worst case the LLM gives wrong info.
251
- **Write operations** (quote-sign, submit, settle) are the whole point of the
252
- single seller model's signing boundary: they live as FIXED code in
253
- `app/agent/src/signing.ts`, are dispatched by A2A's `SellerCore` (in
254
- `app/agent/src/sellerCore.ts`, which `SellerAgentExecutor` inherits) or MCP's
255
- server tools (`negotiate`/`notify_funded`; `settle` is the manual `bag erc8183 settle`),
256
- and are **never** put in the LLM's `tools` set. The quote price is rule-based
257
- (fixed code reads the list `price`, clamps it to `[min,max]`, then signs — the
258
- LLM never touches the price); the LLM only PRODUCES the work text in `notify_funded` delivery —
259
- money never flows through a tool call.
260
-
261
- The one automatic signing path outside `signing.ts` is the budget-gated
262
- model-wrapper LLM-credit auto-renew hook (in the emitted
263
- `app/agent/src/model.ts`'s `buildModel()` factory, backed by
264
- `@bnbagent/studio-runtime/pieverse` `PieverseCreditEnsurer`) — also automatic,
265
- also **not** an LLM tool.
266
-
267
- The x402 buyer kernel (`@bnbagent/studio-runtime/x402`, the payment signer) is
268
- **not** an LLM tool either — in v1 it is reachable only as the Agent's
269
- automatic model-wrapper LLM-credit auto-renew (above), driven by fixed code,
270
- never the LLM. Do not wire it into the Agent's `tools` set. The SDK's
271
- `SigningPolicy` is the second-layer gate on every signature regardless.
215
+ ## Step 5 - Write operations live in fixed code, NOT LLM tools
216
+
217
+ Read tools (this skill) are safe-ish - worst case the LLM gives wrong info. **Write operations** (quote-sign, submit, settle) are the whole point of the single seller model's signing boundary: they live as FIXED code in `app/agent/src/signing.ts`, are dispatched by A2A's `SellerCore` (in `app/agent/src/sellerCore.ts`, which `SellerAgentExecutor` inherits) or MCP's server tools (`negotiate`/`notify_funded`; `settle` is the manual `bag erc8183 settle`), and are **never** put in the LLM's `tools` set. The quote price is rule-based (fixed code reads the list `price`, clamps it to `[min,max]`, then signs - the LLM never touches the price); the LLM only PRODUCES the work text in `notify_funded` delivery - money never flows through a tool call.
218
+
219
+ The one automatic signing path outside `signing.ts` is the budget-gated model-wrapper LLM-credit auto-renew hook (in the emitted `app/agent/src/model.ts`'s `buildModel()` factory, backed by `@bnbagent/studio-runtime/pieverse` `PieverseCreditEnsurer`) - also automatic, also **not** an LLM tool.
220
+
221
+ The x402 buyer kernel (`@bnbagent/studio-runtime/x402`, the payment signer) is **not** an LLM tool either - in v1 it is reachable only as the Agent's automatic model-wrapper LLM-credit auto-renew (above), driven by fixed code, never the LLM. Do not wire it into the Agent's `tools` set. The SDK's `SigningPolicy` is the second-layer gate on every signature regardless.
272
222
 
273
223
  ---
274
224
 
@@ -276,63 +226,34 @@ never the LLM. Do not wire it into the Agent's `tools` set. The SDK's
276
226
 
277
227
  **Q: Why isn't `app/agent/src/tools.ts` auto-synced with `app/agent/studio.toml` changes?**
278
228
 
279
- A: The recipe is emitted once at `bag init` time; the file is the user's. To
280
- refresh after configuring new features (e.g., enabling `[erc8183]` later):
229
+ A: The recipe is emitted once at `bag init` time; the file is the user's. To refresh after configuring new features (e.g., enabling `[erc8183]` later):
281
230
 
282
231
  ```bash
283
232
  bag recipe code tools-chain > app/agent/src/chainTools.ts.new
284
233
  diff app/agent/src/chainTools.ts app/agent/src/chainTools.ts.new
285
- # manually merge preserves any user customizations
234
+ # manually merge - preserves any user customizations
286
235
  ```
287
236
 
288
237
  **Q: Does this work in AgentCore deployment?**
289
238
 
290
- A: Yes. The functions only need `@bnbagent/studio-runtime` (already a
291
- dependency of the Agent sub-project via `app/agent/package.json`). No
292
- subprocess, no MCP transport — pure in-process calls. The deploy artifact
293
- ships the built `tools.ts` as part of the Agent that serves its selected
294
- A2A/MCP faces on AgentCore.
239
+ A: Yes. The functions only need `@bnbagent/studio-runtime` (already a dependency of the Agent sub-project via `app/agent/package.json`). No subprocess, no MCP transport - pure in-process calls. The deploy artifact ships the built `tools.ts` as part of the Agent that serves its selected A2A/MCP faces on AgentCore.
295
240
 
296
241
  **Q: Is this the same as `bag init --protocols MCP`?**
297
242
 
298
- A: No. `bag init --protocols MCP` selects an **external seller face**
299
- (streamable-HTTP `/mcp` for buyers). This skill wires read-only chain queries
300
- into the Agent's own LLM as in-process tools. v0.0.1 doesn't ship
301
- MCP-for-agent (the agent runtime consuming a subprocess MCP server as its LLM
302
- tools). MCP here is instead an *external seller face* (`bag init --protocols
303
- MCP` or `--protocols A2A,MCP`) — see `docs/design/decisions.md`. For
304
- now: in-process is simpler, faster, and matches commitment "agent code the
305
- user owns".
243
+ A: No. `bag init --protocols MCP` selects an **external seller face** (streamable-HTTP `/mcp` for buyers). This skill wires read-only chain queries into the Agent's own LLM as in-process tools. The current release does not ship MCP-for-agent (the agent runtime consuming a subprocess MCP server as its LLM tools). MCP here is instead an _external seller face_ (`bag init --protocols MCP` or `--protocols A2A,MCP`) - see `docs/design/decisions.md`. For now: in-process is simpler, faster, and matches commitment "agent code the user owns".
306
244
 
307
245
  **Q: How do I know if my `app/agent/src/tools.ts` is up to date?**
308
246
 
309
- A: Re-emit with `bag recipe code tools-chain > app/agent/src/chainTools.ts.new`
310
- and diff against your current file. If studio added new tools in a newer
311
- version, they'll appear in the emit; you decide whether to adopt.
247
+ A: Re-emit with `bag recipe code tools-chain > app/agent/src/chainTools.ts.new` and diff against your current file. If studio added new tools in a newer version, they'll appear in the emit; you decide whether to adopt.
312
248
 
313
249
  **Q: Can I reuse a Pieverse API key I created with a DIFFERENT wallet (BYOK)?**
314
250
 
315
- A: Yes, for inference with one caveat. The LLM-credit auto-renew hook
316
- (`PieverseCreditEnsurer`) authenticates to Pieverse with the **agent's signing
317
- wallet** and can only inspect/allocate keys **that wallet owns**. If you set
318
- `[llm.pieverse].key_hash` to a key created by another wallet (the owner is your
319
- day-to-day wallet, not the agent's throwaway signer), the hook can't see it: it
320
- detects the owner mismatch, prints one warning, **disables itself for that
321
- session, and lets inference run on the key's existing Bearer credit**. It does
322
- not crash the agent and does not repeat the check.
323
-
324
- Recommended BYOK setup — do NOT hand the owner wallet's private key to the
325
- agent (that would violate the "keys stay in the user's environment" boundary):
326
-
327
- 1. Put the key in the agent env: `PIEVERSE_LLM_API_KEY=sk-pv-…` in
328
- `.studio/.env.local`, plus `[llm.pieverse].key_hash = "0x…"` and `network`
329
- in `studio.toml`.
330
- 2. Turn off auto-renew so the hook doesn't try to allocate a key it can't own:
331
- `bag llm auto-renew llm off`.
332
- 3. Top the key up yourself in the Pieverse portal (or from the owner wallet)
333
- when it runs low — the agent will 402 upstream if the Bearer credit is
334
- exhausted.
335
-
336
- If you instead want the agent to auto-allocate/topup, activate a key the
337
- **agent's own** signing wallet owns with `bag llm activate` (zero-deposit is
338
- fine) and keep auto-renew on.
251
+ A: Yes, for inference - with one caveat. The LLM-credit auto-renew hook (`PieverseCreditEnsurer`) authenticates to Pieverse with the **agent's signing wallet** and can only inspect/allocate keys **that wallet owns**. If you set `[llm.pieverse].key_hash` to a key created by another wallet (the owner is your day-to-day wallet, not the agent's throwaway signer), the hook can't see it: it detects the owner mismatch, prints one warning, **disables itself for that session, and lets inference run on the key's existing Bearer credit**. It does not crash the agent and does not repeat the check.
252
+
253
+ Recommended BYOK setup - do NOT hand the owner wallet's private key to the agent (that would violate the "keys stay in the user's environment" boundary):
254
+
255
+ 1. Put the key in the agent env: `PIEVERSE_LLM_API_KEY=sk-pv-…` in `.studio/.env.local`, plus `[llm.pieverse].key_hash = "0x…"` and `network` in `studio.toml`.
256
+ 2. Turn off auto-renew so the hook doesn't try to allocate a key it can't own: `bag llm auto-renew llm off`.
257
+ 3. Top the key up yourself in the Pieverse portal (or from the owner wallet) when it runs low - the agent will 402 upstream if the Bearer credit is exhausted.
258
+
259
+ If you instead want the agent to auto-allocate/topup, activate a key the **agent's own** signing wallet owns with `bag llm activate` (zero-deposit is fine) and keep auto-renew on.