@bnbagent/studio-cli 0.0.6-alpha.1

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.
Files changed (55) hide show
  1. package/DISCLAIMER.md +48 -0
  2. package/LICENSE +201 -0
  3. package/dist/_agentcoreName-DZDWEYD3.js +7 -0
  4. package/dist/_twak-5XQMOFUC.js +25 -0
  5. package/dist/bag.js +19358 -0
  6. package/dist/chunk-7RAKL4AS.js +172 -0
  7. package/dist/chunk-M3ODFCA7.js +1053 -0
  8. package/dist/chunk-U7IDQ3K5.js +14 -0
  9. package/dist/deployCli-N6TPN6XA.js +40 -0
  10. package/package.json +64 -0
  11. package/recipes/agent/code/{{PKG}}/signing.ts.tmpl +287 -0
  12. package/recipes/agent/recipe.toml +35 -0
  13. package/recipes/providers/pieverse-llm/recipe.toml +16 -0
  14. package/recipes/providers/pieverse-llm/skills/funding-pieverse-llm.md +203 -0
  15. package/recipes/runtimes/agentcore/code/{{PKG}}/.dockerignore.tmpl +8 -0
  16. package/recipes/runtimes/agentcore/code/{{PKG}}/Dockerfile.tmpl +50 -0
  17. package/recipes/runtimes/agentcore/code/{{PKG}}/agentCard.ts.tmpl +135 -0
  18. package/recipes/runtimes/agentcore/code/{{PKG}}/dualMain.ts.tmpl +402 -0
  19. package/recipes/runtimes/agentcore/code/{{PKG}}/executor.ts.tmpl +147 -0
  20. package/recipes/runtimes/agentcore/code/{{PKG}}/main.ts.tmpl +344 -0
  21. package/recipes/runtimes/agentcore/code/{{PKG}}/mcpMain.ts.tmpl +677 -0
  22. package/recipes/runtimes/agentcore/code/{{PKG}}/model.ts.tmpl +117 -0
  23. package/recipes/runtimes/agentcore/code/{{PKG}}/sellerCore.ts.tmpl +503 -0
  24. package/recipes/runtimes/agentcore/code/{{PKG}}/tools.ts.tmpl +157 -0
  25. package/recipes/runtimes/agentcore/recipe.toml +97 -0
  26. package/recipes/runtimes/azure-foundry/code/{{PKG}}/.dockerignore.tmpl +8 -0
  27. package/recipes/runtimes/azure-foundry/code/{{PKG}}/Dockerfile.tmpl +47 -0
  28. package/recipes/runtimes/azure-foundry/code/{{PKG}}/agentCard.ts.tmpl +131 -0
  29. package/recipes/runtimes/azure-foundry/code/{{PKG}}/executor.ts.tmpl +504 -0
  30. package/recipes/runtimes/azure-foundry/code/{{PKG}}/foundryMain.ts.tmpl +300 -0
  31. package/recipes/runtimes/azure-foundry/code/{{PKG}}/main.ts.tmpl +196 -0
  32. package/recipes/runtimes/azure-foundry/code/{{PKG}}/mcpMain.ts.tmpl +562 -0
  33. package/recipes/runtimes/azure-foundry/code/{{PKG}}/model.ts.tmpl +117 -0
  34. package/recipes/runtimes/azure-foundry/code/{{PKG}}/tools.ts.tmpl +157 -0
  35. package/recipes/runtimes/azure-foundry/recipe.toml +88 -0
  36. package/recipes/tools-chain/code/{{PKG}}/chainTools.ts.tmpl +166 -0
  37. package/recipes/tools-chain/recipe.toml +11 -0
  38. package/recipes/wallet/recipe.toml +20 -0
  39. package/recipes/x402-buyer/code/{{PKG}}/x402Buyer.ts.tmpl +175 -0
  40. package/recipes/x402-buyer/recipe.toml +15 -0
  41. package/skills/bnbagent-studio.md +107 -0
  42. package/skills/references/bnbagent-studio-adding-to-project.md +241 -0
  43. package/skills/references/bnbagent-studio-buying-from-bazaar.md +169 -0
  44. package/skills/references/bnbagent-studio-buying-via-8183.md +222 -0
  45. package/skills/references/bnbagent-studio-extending-signing.md +227 -0
  46. package/skills/references/bnbagent-studio-operating.md +211 -0
  47. package/skills/references/bnbagent-studio-scaffolding-agent.md +536 -0
  48. package/skills/references/bnbagent-studio-selling-via-8183.md +271 -0
  49. package/skills/references/bnbagent-studio-selling-via-b402.md +194 -0
  50. package/skills/references/bnbagent-studio-use-aws-agentcore.md +208 -0
  51. package/skills/references/bnbagent-studio-use-azure-foundry.md +164 -0
  52. package/skills/references/bnbagent-studio-use-bnb-trial.md +92 -0
  53. package/skills/references/bnbagent-studio-using-altana-wallet.md +68 -0
  54. package/skills/references/bnbagent-studio-using-twak-wallet.md +260 -0
  55. package/skills/references/bnbagent-studio-wiring-llm-tools.md +338 -0
@@ -0,0 +1,222 @@
1
+ ---
2
+ name: bnbagent-studio-buying-via-8183
3
+ description: When the user is acting as ERC-8183 buyer — finding a provider, getting a quote, buying a service, fetching the deliverable, and deciding to approve / dispute / reject the work. Owns the buyer-side decision tree for the entire job lifecycle including settle-window timing (24h dispute window), dispute governance flow, and `Submission deadline has passed` recovery.
4
+ ---
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.
7
+
8
+ # bnbagent-studio-buying-via-8183
9
+
10
+ > **v1 scope note:** v1 is **seller-only** — buyer flows are **NOT**
11
+ > the main v1 payment path. The x402 buyer kernel survives only as the Agent's
12
+ > *automatic* LLM top-up (`@bnbagent/studio-runtime/x402`, budget-gated, not an LLM tool),
13
+ > and the erc8183 `buyWorkflow` survives as an **underlying capability** still
14
+ > reachable via the `bag erc8183 buy/status/fetch/settle` CLI. Full buyer-side
15
+ > *product* flows (a buyer agent, buyer-side negotiation wrapping) are deferred
16
+ > to v2. The CLI procedure below still works for manual / testing use.
17
+
18
+ Procedure for **buyer-side flow**: have your agent (or you directly via CLI)
19
+ purchase a service from another ERC-8183 seller, verify the deliverable, and
20
+ close out the job with the right `settle` action.
21
+
22
+ Audience: Claude Code in a v0.0.x workspace with a funded wallet (tBNB + U).
23
+ The buying CLI (`bag erc8183 buy/status/fetch/settle`) targets the **Agent
24
+ sub-project's** wallet — these commands resolve to `<workspace>/app/agent/`
25
+ automatically when run from the workspace root.
26
+
27
+ > **Protocol facts** (independent of the local filesystem layout): 24h dispute
28
+ > window, `0x17be5b7b` revert, `expired_at` arithmetic.
29
+
30
+ **Different from**:
31
+ - `bnbagent-studio-operating.md` (same directory) — generic ops (dev / doctor / balance / RPC); jumps here for buyer-specific decisions
32
+ - `bnbagent-studio-adding-to-project` — covers wiring a buyer tool set into an existing project (the static setup, not the runtime decisions)
33
+ - `bnbagent-studio-selling-via-8183.md` (same directory) — the mirror playbook for the seller side (`on_job`, dispute defense)
34
+
35
+ This skill owns: **buy → fetch → approve/dispute/reject loop**, whether
36
+ driven via CLI or the agent's LLM calling `erc8183_buyer_set` tools.
37
+
38
+ ## Buyer settle decision tree (load this skill when the user hits any of these)
39
+
40
+ `SUBMITTED` job → buyer has three options, **time-gated by the on-chain dispute window**:
41
+
42
+ | Action | Allowed | What happens |
43
+ |---|---|---|
44
+ | `bag erc8183 settle <id> --action approve` | **After 24h dispute_window has passed** (chain enforces; reverts with `0x17be5b7b` if early) | Job → `COMPLETED`; seller receives U |
45
+ | `bag erc8183 settle <id> --action dispute` | **Within dispute_window** | Opens governance flow; quorum vote decides; refund possible |
46
+ | `bag erc8183 settle <id> --action reject` | **Only if you're a quorum voter, not the buyer** | Job → `REJECTED` via governance |
47
+
48
+ If the buyer agent (or LLM) is about to call `settle --action approve` and it's
49
+ been <24h since SUBMITTED, **wait** or use `dispute`. Don't try to retry
50
+ through the revert — read the error and pick the right action.
51
+
52
+ Common error: `Submission deadline has passed` → buyer set `expiredAt` too
53
+ short (< dispute_window). Fix: re-buy with `--deadline-min ≥ 1` (the buy
54
+ flow now auto-adds dispute_window).
55
+
56
+ ## Preconditions
57
+
58
+ - `bag doctor` is clean (or only warns on LLM key)
59
+ - Wallet has ≥ 0.05 tBNB (gas) and ≥ 0.2 U (token + slack). On BSC testnet the
60
+ ERC-8183 kernel writes (`createJob` / `fund` deposit / `settle` …) are
61
+ gas-sponsored via the SDK's MegaFuel paymaster, so you spend far less tBNB than
62
+ that — but **not zero**: `fund` sends an ERC-20 `approve` (a token call, not
63
+ sponsored) when the token allowance is too low — typically just the first fund,
64
+ since studio approves a floored cap that later jobs reuse. Keep a little tBNB for
65
+ it. (Mainnet is never sponsored.)
66
+ - You know the **provider's wallet address** (the seller agent's address)
67
+ - The seller is **reachable** (its A2A agent is deployed somewhere); discoverable
68
+ via the provider's `bag erc8004 resolve <agent_id>` endpoint URI
69
+
70
+ ## Stage 1 — Pre-flight checks
71
+
72
+ ```bash
73
+ # 1. Confirm wallet + balances
74
+ bag wallet show
75
+ bag doctor # tBNB + U checks should be PASS
76
+
77
+ # 2. Confirm the provider's 8004 record (optional but recommended)
78
+ bag erc8004 resolve <provider_agent_id>
79
+ # → returns the agent_uri; decode it (base64 data: URI) to verify the endpoint URL
80
+ ```
81
+
82
+ If the provider's endpoint URL points somewhere reachable (e.g. an `https://`
83
+ AgentCore runtime URL), proceed. If it's `http://localhost:...`, that means you
84
+ must be on the same host.
85
+
86
+ ## Stage 2 — (Optional) Negotiate price
87
+
88
+ **v0.0.x**: `@bnbagent/studio-runtime` *does* wrap the buyer-side negotiation
89
+ handshake (`@bnbagent/studio-runtime/erc8183` `negotiateWithSeller`, wired into
90
+ the buy workflow). It fires automatically when you buy by `--agent-id` (resolves
91
+ the seller's endpoint from its ERC-8004 record, then POSTs `/negotiate`); pass
92
+ `--no-negotiate` to skip it. When you buy by `--provider <addr>` you supply the
93
+ budget directly and assume the price was agreed off-chain.
94
+
95
+ If you want to talk to the seller manually, the seller now exposes its
96
+ `negotiate` skill over **A2A** (the seller's ERC-8004 endpoint URI is an A2A base
97
+ URL): send an A2A `message/send` JSON-RPC call carrying a `DataPart`
98
+ `{"skill": "negotiate", "task_description": "...", "terms": {...}}` (+ the seller's
99
+ OAuth2 Bearer when deployed). The reply data part is the signed `NegotiationResult`
100
+ quote. But you don't need this for v0.0.x — go straight to buy.
101
+
102
+ ## Stage 3 — Buy
103
+
104
+ ```bash
105
+ bag erc8183 buy --provider <provider_addr> "<task description>" \
106
+ --budget-u <amount> \ # capped by policy.budget_cap_u
107
+ --deadline-min <minutes> \ # default 30; this is the seller's submission window
108
+ --network bsc-testnet
109
+ # provider is a REQUIRED flag (--provider <addr> OR --agent-id <id>), not a positional;
110
+ # `--agent-id` resolves the endpoint + negotiates first.
111
+ ```
112
+
113
+ > **Task can be passed two ways** (both accepted): as a positional argument
114
+ > `bag erc8183 buy --provider <addr> "<task>"` OR via the flag
115
+ > `bag erc8183 buy --provider <addr> --task "<task>"`. Pass it once — supplying
116
+ > both at the same time is an error.
117
+
118
+ The 4 on-chain steps run sequentially:
119
+
120
+ 1. `createJob(provider, expiredAt, description)` → returns `job_id`
121
+ 2. `registerJob(jobId)`
122
+ 3. `setBudget(jobId, rawBudget)`
123
+ 4. `fund(jobId, rawBudget, approveFloor=rawBudget)` — auto-approves U
124
+
125
+ Output prints 4 tx hashes + `job_id`. Note the `job_id` for later.
126
+
127
+ **Gotcha**: `expired_at = now + deadline_minutes*60 + dispute_window` (24h). This
128
+ is intentional — the chain enforces that submission must happen before
129
+ `expired_at - dispute_window`. If you set `deadline_minutes=30`, the seller has
130
+ 30 min to submit (then a 24h dispute window starts).
131
+
132
+ ## Stage 4 — Wait for SUBMITTED
133
+
134
+ The single seller runtime has **no standalone poller** — after funding, send a
135
+ `notify_funded` A2A message to the seller ("I funded job X, please deliver"). The
136
+ seller **acks `accepted` immediately and delivers in the background**, so you do
137
+ **not** get the deliverable in the A2A reply — you poll the chain for it. The
138
+ seller also sweeps other funded jobs on each `notify_funded` (in the background,
139
+ deduped). Check status:
140
+
141
+ ```bash
142
+ bag erc8183 status <job_id>
143
+ ```
144
+
145
+ Statuses:
146
+
147
+ - `OPEN` → not yet funded (shouldn't see this after Step 3)
148
+ - `FUNDED` → waiting for seller to pick up + submit
149
+ - `SUBMITTED` → ready to fetch + settle
150
+ - `EXPIRED` → seller missed the deadline; use `bag erc8183 settle --action ...` or
151
+ the SDK's `mark_expired` / `claim_refund`
152
+
153
+ Delivery is no longer instant: because the seller works in the background, the
154
+ wait is however long its work takes (seconds to minutes). Poll until `SUBMITTED`,
155
+ then read `deliverable_url` (Stage 5). If it stays `FUNDED`, either no one sent
156
+ `notify_funded` (and the sweep hasn't run — the seller may be scaled to zero), or
157
+ the seller's background work failed or hasn't finished yet — re-send
158
+ `notify_funded` to nudge it while the runtime is warm. (Also possible: a config
159
+ mismatch, most often `expired_at` too soon — but the workflow auto-fixes this now.)
160
+
161
+ ## Stage 5 — Fetch the deliverable
162
+
163
+ The single seller runtime serves **no** job-query endpoint — the deliverable is read
164
+ back from the on-chain submission (the `submit` tx carries the `deliverable_url`,
165
+ typically `ipfs://...`) and the IPFS object. Get the URL via CLI:
166
+
167
+ ```bash
168
+ bag erc8183 fetch <job_id>
169
+ ```
170
+
171
+ Prints the `deliverable_url`. Fetch it yourself (e.g. via an IPFS gateway) to read
172
+ the `DeliverableManifest`: `{"chain_id", "contracts", "job_id", "response": {"content": ..., "content_type": ...}, "metadata": {...}}`.
173
+
174
+ ## Stage 6 — Settle
175
+
176
+ ```bash
177
+ # Happy path: accept the deliverable. NOTE: must wait 24h dispute_window first.
178
+ bag erc8183 settle <job_id> --action approve
179
+
180
+ # Bad deliverable: dispute (within dispute_window, no wait needed)
181
+ bag erc8183 settle <job_id> --action dispute
182
+
183
+ # (rare) you're a quorum voter and want to reject:
184
+ bag erc8183 settle <job_id> --action reject
185
+ ```
186
+
187
+ Returns a tx hash. Verify on BscScan.
188
+
189
+ **On `--action approve` revert with `0x17be5b7b`**: chain refuses because
190
+ `submitted_at + dispute_window > now`. Either wait the remaining time or
191
+ use `--action dispute` for immediate effect.
192
+
193
+ ## Stage 7 — Verify on-chain settlement
194
+
195
+ ```bash
196
+ bag erc8183 status <job_id>
197
+ # Expect: status COMPLETED (after approve) or unchanged SUBMITTED (after dispute, until voters resolve)
198
+ ```
199
+
200
+ Check seller's U balance increased (minus platform fee — see `CommerceClient.platform_fee_bp()`).
201
+
202
+ ## End-to-end smoke (one-shot, for testing your setup)
203
+
204
+ ```bash
205
+ # Buyer side (this assumes the seller's A2A agent is already deployed somewhere)
206
+ PROVIDER=<seller_address>
207
+ JOB=$(bag erc8183 buy --provider $PROVIDER "test task" --budget-u 0.5 | awk -F': *' '/job_id:/{print $2; exit}')
208
+ # send a `notify_funded` A2A message to the seller for that JOB (buyer-push),
209
+ # then poll the chain (the seller acks at once and delivers in the background):
210
+ sleep 60
211
+ bag erc8183 status $JOB
212
+ bag erc8183 settle $JOB --action dispute
213
+ ```
214
+
215
+ This is the exact end-to-end flow used to validate real-chain buying. See the
216
+ references below for the canonical picture.
217
+
218
+ ## Reference
219
+
220
+ - `docs/design/erc8183-reference.md` (SDK surface map / negotiation envelope)
221
+ - `docs/design/single-seller-agent.md` + `docs/design/erc8183-buyer-push.md` (the v1 single-agent model + buyer-push flow)
222
+ - `docs/guides/verification.md` (manual on-chain verification)
@@ -0,0 +1,227 @@
1
+ ---
2
+ name: bnbagent-studio-extending-signing
3
+ description: When the user wants the agent's wallet to sign EIP-712 typed data for anything beyond BSC U-token transfers — e.g. integrate a new x402 service, custom commerce contract, or any TypedData primary type beyond TransferWithAuthorization/ReceiveWithAuthorization. Also covers diagnosing `PolicyViolation` / `X402PolicyError` at runtime and how to safely extend `[wallet.signing]` extra_domains / extra_primary_types in studio.toml.
4
+ ---
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.
7
+
8
+ # bnbagent-studio-extending-signing
9
+
10
+ Procedure for **extending the EIP-712 signing allowlist** in a bnbagent-studio project.
11
+ Audience: Claude Code helping a user who hit `PolicyViolation` or wants to integrate a non-default x402 service / custom contract.
12
+
13
+ > **v0.0.1 path note**: signing is an **Agent-only** concern. `signing.ts` lives
14
+ > at `<workspace>/app/agent/src/signing.ts` and is called by the
15
+ > `SellerAgentExecutor` skills (`negotiate` / `notify_funded`) — it is **never** an
16
+ > LLM-callable tool. The `[wallet.signing]` config lives in
17
+ > `<workspace>/app/agent/studio.toml`. The workspace is a thin root plus the one
18
+ > `app/agent/` sub-project; every command and edit below targets `app/agent/`.
19
+
20
+ **Different from**:
21
+ - `-operating` — general ops & doctor / balance / job status
22
+ - `funding-pieverse-llm` — Pieverse LLM credit lifecycle (the money)
23
+ - `-adding-to-project` — adds capabilities (`bnbagent-sdk` modules)
24
+
25
+ This skill is specifically the **signing-permission** axis. Funding is "do I have the money"; signing policy is "is the wallet allowed to sign this".
26
+
27
+ ## Mental model (defense in depth)
28
+
29
+ Every EIP-712 signature goes through SDK `SigningPolicy.strictDefault()`. By default the wallet only signs:
30
+
31
+ | Allowed | Domain | Primary types |
32
+ |---|---|---|
33
+ | U-token mainnet | chain `56`, `0xcE24439F2D9C6a2289F741120FE202248B666666` | `TransferWithAuthorization`, `ReceiveWithAuthorization` |
34
+ | U-token testnet | chain `97`, `0xc70B8741B8B07A6d61E54fd4B20f22Fa648E5565` | (same) |
35
+
36
+ Everything else (`Permit`, `PermitSingle`, `PermitBatch`, foreign contracts, foreign chains, custom primary types) is **refused with `PolicyViolation`** at sign-time.
37
+
38
+ Two layers wrap this:
39
+
40
+ | Layer | What it gates | Where configured | Can agent change at runtime? |
41
+ |---|---|---|---|
42
+ | L2 — HTTP host | which servers the x402 buyer is allowed to fetch from | `[payments.x402].allowed_hosts` in `app/agent/studio.toml` | ⚠️ Only by editing toml + restart |
43
+ | L3 — SigningPolicy | which `(chain_id, contract)` + primary type the wallet will sign | `[wallet.signing]` in `app/agent/studio.toml` (additive over SDK strictDefault) | ⚠️ Only by editing toml + restart |
44
+
45
+ **Both layers must permit a request** for it to succeed. Adding only one half won't work — see Section A.
46
+
47
+ EIP-191 SIWE (the `pieverse_usage` MCP tool / `bag llm activate`) uses a **separate** hardcoded allowlist `{"llm.pieverse.io"}` and is not configurable.
48
+
49
+ ## Quick triage decision tree
50
+
51
+ | User said... | Section |
52
+ |---|---|
53
+ | "buy X service via x402" (X is not Pieverse) | A — new x402 service |
54
+ | "sign for custom commerce contract / order / quote" | B — custom primary type |
55
+ | `PolicyViolation` / `X402PolicyError` at runtime | C — diagnosing the rejection |
56
+ | "agent needs to approve unlimited USDC" / Permit / Permit2 | D — refuse the request |
57
+ | "expand the 600s validity window" | E — validity overrides |
58
+
59
+ ## A. Integrate a new x402 service
60
+
61
+ The user wants the agent to pay e.g. `api.example.com` via x402.
62
+
63
+ **Pre-flight checks (must be true in v0.0.1 — refuse and explain if not):**
64
+
65
+ 1. The service accepts payment on **BSC chain 56 or 97**. v0.0.1 wallets are BSC-only; a service on Base/Ethereum/Polygon won't work until v0.2 multi-chain support lands.
66
+ 2. The service uses **EIP-3009 `TransferWithAuthorization`** (or `ReceiveWithAuthorization`). If it uses Permit2 or a custom primary type → goes to Section B.
67
+ 3. The token contract address on BSC is known and the user can confirm it. Don't guess from a token symbol — look up the deployed address.
68
+
69
+ If any of (1)–(3) fail, **stop and tell the user**. v0.0.1 cannot integrate cross-chain services or non-EIP-3009 payment rails. Don't try to work around it; the SigningPolicy will refuse and the failure will be confusing.
70
+
71
+ **Steps when (1)–(3) all pass:**
72
+
73
+ ```bash
74
+ # 1. Edit app/agent/studio.toml — both gates. `bag config` resolves the app/agent/
75
+ # sub-project automatically from the workspace root
76
+ # (there is NO --side flag); pass --project-root app/agent to be explicit.
77
+ bag config set payments.x402.allowed_hosts '["llm.pieverse.io", "api.example.com"]'
78
+
79
+ # 2. Add the EIP-712 domain to wallet.signing (additive)
80
+ # bag config does not yet handle nested array-of-arrays elegantly; edit the
81
+ # toml directly with this snippet (targets app/agent/studio.toml only):
82
+ cat >> app/agent/studio.toml <<'EOF'
83
+
84
+ [wallet.signing]
85
+ extra_domains = [
86
+ [56, "0xAbcdef0123456789abcdef0123456789abcdef01"], # api.example.com token on mainnet
87
+ [97, "0x1234567890abcdef1234567890abcdef12345678"], # same on testnet
88
+ ]
89
+ EOF
90
+
91
+ # 3. Verify the policy reflects both allowlists
92
+ bag wallet policy show
93
+ # expect 3 entries in domain_allowlist: U mainnet, U testnet, your new contract
94
+
95
+ # 4. Restart the agent process for the new policy to take effect.
96
+ # SigningPolicy is read at wallet construction; running `bag dev` again
97
+ # is enough.
98
+ ```
99
+
100
+ **Hard rules**:
101
+ - Do not add a contract to `extra_domains` without verifying its address on a block explorer. The SigningPolicy treats `(chain_id, contract)` as a unit; the wrong address = signing into a phishing contract.
102
+ - Do not silently widen `daily_cap_usd` or `max_per_request_usd` to make the new service "fit". The caps are budget guardrails; surface the proposed values to the user before editing.
103
+
104
+ ## B. Custom typed-data primary type
105
+
106
+ If the new service or contract requires the wallet to sign a non-standard primary type (e.g. `"MyOrder"`, `"BondQuote"`, `"NegotiateAgreement"`), edit `<workspace>/app/agent/studio.toml`:
107
+
108
+ ```toml
109
+ # app/agent/studio.toml
110
+ [wallet.signing]
111
+ extra_domains = [
112
+ [56, "0xContractAddress..."],
113
+ ]
114
+ extra_primary_types = ["MyOrder", "BondQuote"]
115
+ ```
116
+
117
+ **Both must be added** — adding a primary type without the matching domain is useless (the contract still gets rejected) and adding the domain without the type still rejects the signature (primary_type allowlist).
118
+
119
+ **Hard rules**:
120
+ - The SDK denylist (`Permit`, `PermitSingle`, `PermitBatch`) **always wins** over `extra_primary_types`. Listing them does not enable them.
121
+ - Custom primary types bypass studio's known semantic checks. Be extra careful that the typed data structure matches what the contract expects; an attacker controlling the contract or the LLM input can construct unfavorable messages.
122
+
123
+ ## C. Diagnosing PolicyViolation / X402PolicyError at runtime
124
+
125
+ User reports an error from `bag dev` / agent runtime. Map the message → fix:
126
+
127
+ ```
128
+ PolicyViolation: unknown (chain_id, verifyingContract): (56, 0xAbc...)
129
+ → L3 SigningPolicy rejection
130
+ → Section A or B: add to [wallet.signing].extra_domains, then restart
131
+
132
+ PolicyViolation: primary type 'Permit' is denylisted
133
+ → Section D: refuse — do not work around
134
+
135
+ PolicyViolation: primary type 'MyOrder' not in allowlist
136
+ → Section B: add to extra_primary_types
137
+
138
+ PolicyViolation: validity window 7200s exceeds max 600
139
+ → Section E: max_validity_window_seconds in [wallet.signing]
140
+
141
+ X402HostNotAllowedError: x402 buyer refusing 'api.example.com' — not in allowed_hosts
142
+ → L2 HTTP gate (exact hosts only — wildcard entries are not supported)
143
+ → bag config set payments.x402.allowed_hosts '[..., "api.example.com"]'
144
+ → (L3 may also need updating per Section A)
145
+
146
+ X402BudgetExhaustedError: x402 402 demands $1.50 > max_usd=$1.00
147
+ → Budget cap; user must explicitly raise via studio.toml.
148
+ → DON'T silently widen — tell the user.
149
+ ```
150
+
151
+ Confirm the current state before editing:
152
+
153
+ ```bash
154
+ bag wallet policy show # L3 SigningPolicy (reads app/agent/studio.toml)
155
+ bag config get payments.x402 # L2 allowed_hosts + caps (auto-resolves app/agent/)
156
+ ```
157
+
158
+ ## D. Refuse: Permit / Permit2 unbounded allowance
159
+
160
+ If the user (or, more dangerously, the LLM) asks the agent to sign `Permit`, `PermitSingle`, or `PermitBatch`:
161
+
162
+ **Stop. Refuse. Explain why.**
163
+
164
+ These primary types grant unbounded ERC-20 spend authority to a third party. The denylist exists exactly to prevent LLMs being talked into signing one. Even if the user insists, the SDK will refuse with `PolicyViolation` and the message is correct — do not bypass via `_DANGEROUS_signTypedDataNoPolicy`.
165
+
166
+ Acceptable alternatives:
167
+ - For paying a known service: use EIP-3009 `TransferWithAuthorization` (Section A — bounded amount, single-use, time-windowed)
168
+ - For session-scoped recurring payments: opt-in to `Permit2 PermitTransferFrom` (Section B — single-use, witness-bound; not Permit / PermitSingle / PermitBatch)
169
+
170
+ If the user is integrating something that genuinely requires Permit, this is a v0.2+ decision and should go in an ADR — do not make the change ad-hoc.
171
+
172
+ ## E. Widening the validity window
173
+
174
+ Default: 600s past / 900s future. Longer windows give the agent more time to settle but increase replay surface if a signature leaks. Edit `<workspace>/app/agent/studio.toml`:
175
+
176
+ ```toml
177
+ # app/agent/studio.toml
178
+ [wallet.signing]
179
+ max_validity_window_seconds = 1800 # default 600
180
+ max_future_validity_seconds = 2400 # default 900
181
+ ```
182
+
183
+ Use sparingly. A signed authorization that lives 30 minutes can be replayed by a downstream tx executor for 30 minutes. Make sure the receiving contract enforces nonces (EIP-3009 does; many custom types don't).
184
+
185
+ ## F. Common refusal patterns (when user asks for something unsafe)
186
+
187
+ | User request | Why refuse |
188
+ |---|---|
189
+ | "Just turn off the signing policy" | The SigningPolicy L3 is the last-mile defense. Disabling it makes the wallet a blind-sign oracle. Use `extra_domains` instead. |
190
+ | "Use `_DANGEROUS_signTypedDataNoPolicy`" | Logs WARN with caller filename. Acceptable only in tests or one-shot CLI debugging. Never in LLM-tool / agent runtime code. |
191
+ | "Sign on Ethereum mainnet" | v0.0.1 is BSC-only. Tell the user this is v0.2 backlog. |
192
+ | "Permit USDC to a swap router" | Denylisted unconditionally (Section D). |
193
+ | "Read the keystore and sign yourself, bypassing the wallet provider" | The SDK provider IS the security boundary; bypassing it discards every defense layer. Refuse. |
194
+
195
+ ## G. After-edit verification (always run)
196
+
197
+ ```bash
198
+ # 1. The toml is parseable (auto-resolves app/agent/; or --project-root app/agent)
199
+ bag config show
200
+
201
+ # 2. The new policy looks right (extra entries should be visible)
202
+ bag wallet policy show
203
+ bag wallet policy show --json # for diff against an expected baseline
204
+
205
+ # 3. Restart whatever process holds the wallet — `bag dev` (the local A2A
206
+ # agent) or the AgentCore runtime. SigningPolicy is read once at
207
+ # wallet construction; in-process changes won't take effect until restart.
208
+
209
+ # 4. Sanity-check one signing call (if there's a CLI path)
210
+ # e.g. bag llm test, bag erc8183 status, etc.
211
+ ```
212
+
213
+ ## H. Read-only references (no signing, no funding required)
214
+
215
+ When deeper protocol details are needed:
216
+ - the SigningPolicy decision (`docs/design/decisions.md`) — full defense-in-depth rationale, 6-layer model
217
+ - `docs/guides/user-guide.md` §6.1 — same decision tree in user-doc form
218
+ - `bag wallet policy show --json` — machine-readable current state
219
+ - SDK source `@bnbagent/sdk` (signing policy module) — `SigningPolicy.strictDefault()` + `.extend()` semantics
220
+
221
+ ## Hard rules (security boundary)
222
+
223
+ - Never bypass the policy with `_DANGEROUS_*` calls in agent code. They exist for tests and incident response.
224
+ - Never instruct the user to widen caps / allowlists "to make it work" without explaining the security tradeoff.
225
+ - Never persist the wallet password or signed payloads anywhere outside the keystore.
226
+ - Always run `bag wallet policy show` after editing `[wallet.signing]` to confirm the change took effect.
227
+ - Always restart the process — SigningPolicy is captured at wallet construction.
@@ -0,0 +1,211 @@
1
+ ---
2
+ name: bnbagent-studio-operating
3
+ description: When the user wants to run, debug, diagnose, or operate a bnbagent-studio agent project. Covers dev server, doctor checks, balance/RPC queries, job status reads, and incident triage — including the delegated deploy lifecycle (`bag deploy status` / `logs` / `verify` / `destroy`), twak-wallet issues, and `PolicyViolation` / `X402PolicyError` signing-policy errors (deep-dive playbooks for those ship as references of the `bnbagent-studio` router skill; read them on demand).
4
+ ---
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.
7
+
8
+ # bnbagent-studio-operating
9
+
10
+ Procedure for **day-to-day operation** of an existing bnbagent-studio project.
11
+ Audience: Claude Code in a v0.0.1 workspace (thin root with the `agentcore/`
12
+ config dir + the workspace-root `.studio/wallets/` + funded wallet, plus the
13
+ single sub-project `app/agent/` holding `studio.toml` + `src/main.ts` /
14
+ `src/sellerCore.ts` / `src/executor.ts` / `src/agentCard.ts` /
15
+ `src/signing.ts`). Most commands run from the workspace root; the v0.0.1
16
+ project-root fallback locates the `app/agent/` sub-project automatically for
17
+ wallet/LLM/budget ops.
18
+
19
+ **Different from**:
20
+ - `bnbagent-studio-scaffolding-agent.md` (in this same references/ directory) — creates a brand new project
21
+ - `bnbagent-studio-selling-via-8183.md` (in this same references/ directory) — seller flow (`runWork` value, rule-based quote pricing, dispute defense)
22
+ - `funding-pieverse-llm` (project-scope skill, Pieverse projects only) — Pieverse credit lifecycle / topup decisions
23
+
24
+ **Deep-dive references** — plain markdown files in this SAME references/
25
+ directory (Claude Code: `~/.claude/skills/bnbagent-studio/references/`; Cursor:
26
+ `bnbagent-studio/references/` beside the `.mdc` rules). READ
27
+ the file when the topic comes up — don't answer from memory:
28
+ - `bnbagent-studio-use-aws-agentcore.md` — the delegated AgentCore lifecycle (`bag deploy --provider aws` / `status` / `logs` / `verify` / `destroy`, `provision-cognito`) + AWS prerequisites
29
+ - `bnbagent-studio-use-bnb-trial.md` — GitHub device login, 48h eligibility, staging verification, and the delegated BNB trial lifecycle
30
+ - `bnbagent-studio-use-azure-foundry.md` — the delegated Azure Foundry lifecycle (`bag deploy --provider azure`; no `az`/`azd` CLI)
31
+ - `bnbagent-studio-using-twak-wallet.md` — `[wallet].kind = "twak"` create / fund / SIWE-bind / container deploy / limitations
32
+ - `bnbagent-studio-extending-signing.md` — `PolicyViolation` / `X402PolicyError` diagnosis + extending the EIP-712 allowlist
33
+ - `bnbagent-studio-adding-to-project.md` — adding the seller runtime to an existing TypeScript project
34
+ - `bnbagent-studio-buying-via-8183.md` — buyer flow (find provider → buy → fetch → settle)
35
+
36
+ This playbook covers **generic ops**: dev / doctor / balances / RPC / incident triage.
37
+ For seller job-lifecycle decisions (settle / submit / dispute defense), read
38
+ `bnbagent-studio-selling-via-8183.md` (same directory); for the buyer side, read the buying reference.
39
+
40
+ ## Quick triage decision tree
41
+
42
+ | User said... | Run first |
43
+ |---|---|
44
+ | "is it healthy?" / "doctor" | `bag doctor` (scans the `app/agent/` sub-project from the workspace root) |
45
+ | "run locally" / "start it" / "dev" | `bag dev` (serves the selected protocol: A2A on `:9000`, MCP on `:8000/mcp` — same for any destination) |
46
+ | "what's my balance?" / "how much U?" | `bag wallet balance` (native + U; `--network X` / `--all` available. `--address X` is **v0.2 backlog — not in v0.0.x**) |
47
+ | "send X tBNB / U to another address" | ⚠️ **v0.2 backlog — `bag wallet transfer` does not exist in v0.0.x.** No transfer CLI yet; move funds with an external wallet |
48
+ | "approve commerce contract to spend U" | ⚠️ **v0.2 backlog — `bag erc20` group does not exist in v0.0.x** (funding flows auto-approve U; no manual approve CLI) |
49
+ | "how much have I approved 0x... for?" | ⚠️ **v0.2 backlog — `bag erc20 allowance` does not exist in v0.0.x** |
50
+ | "is my agent registered?" | `bag erc8004 show` (note: registration is normally automatic at `bag deploy verify` — manual `bag erc8004 register` only if you need an identity before deploy) |
51
+ | "what's the status of job X?" | `bag erc8183 status <id>` (read-only — neutral) |
52
+ | "settle job X" | `bag erc8183 settle <id> --action approve\|reject\|dispute` (default `approve`) — **seller's manual step** after the dispute window; deeper context in `bnbagent-studio-selling-via-8183.md` (same directory) |
53
+ | "submit work for job X" | **seller action** — read `bnbagent-studio-selling-via-8183.md` (same directory) for the submit/dispute flow |
54
+ | "tx not confirming" | Read BscScan link from prior tx output + check `eth_getTransactionCount` |
55
+ | "wallet balance is wrong" | Check both tBNB (gas) and U (token); see balance section |
56
+ | "is it deployed?" / "deploy status" | `bag deploy status` lists every locally recorded BNB/AWS/Azure deployment and asks `bnbagent-deploy` for live state; add `--no-probe` for record-only output |
57
+ | "deploy logs" / "verify" / "tear it down" | With one recorded deployment, `bag deploy {logs,verify,destroy}` selects it automatically. With multiple, choose interactively or pass `--provider bnb\|aws\|azure` in automation. Cloud calls always go through `bnbagent-deploy`. `bag platform credit` shows the BNB trial countdown. |
58
+
59
+ ## Common ops procedures
60
+
61
+ ### A. Run the agent locally (the default)
62
+
63
+ ```bash
64
+ # Configure secrets (idempotent — does NOT duplicate existing keys).
65
+ # These write into .studio/.env.local (the Agent's secrets):
66
+ bag env set WALLET_PASSWORD <your password>
67
+ bag env set OPENROUTER_API_KEY <your key> # or whichever provider app/agent/studio.toml [llm] uses
68
+
69
+ # From the workspace root — `bag dev` serves the selected protocol:
70
+ bag dev # A2A agent on :9000, MCP on :8000/mcp (same for any destination)
71
+ bag dev --port 9100 # override the port
72
+ ```
73
+
74
+ `bag dev` sets `STORAGE_LOCAL_PATH=~/.bag/deliverables/<workspace-name>/` for the
75
+ agent subprocess and runs it **without** Cognito env, so the local endpoint is
76
+ reachable without a token (Cognito is mandatory only on the deployed AgentCore
77
+ runtime). For A2A projects, the agent
78
+ (`app/agent/src/main.ts`) exposes `/.well-known/agent-card.json` +
79
+ JSON-RPC `message/send` + `GET /ping` on `:9000`. Smoke-test the card with curl:
80
+
81
+ ```bash
82
+ curl http://localhost:9000/.well-known/agent-card.json
83
+ ```
84
+
85
+ Expect the agent card with its two skills (`negotiate`, `notify_funded`).
86
+ For MCP projects, connect an MCP client to `http://localhost:8000/mcp`.
87
+
88
+ > ⚠️ **The AgentCore inspector chat box cannot test a seller agent.** A seller's
89
+ > skills are structured A2A `DataPart`s (`message/send`), but the inspector chat
90
+ > box can only send plain text — it can never construct a `{"skill":"negotiate", …}`
91
+ > part, so it can't reach the agent's real product surface (and its streaming view
92
+ > expects Task events, not the `message` reply the agent emits). **Test locally
93
+ > with curl or an A2A client sending a `DataPart`**, not the chat box.
94
+
95
+ Drive a sale by sending the skills directly (`negotiate` `terms` MUST include
96
+ `deliverables` + `quality_standards`, else the quote is rejected `reason_code 0x04`):
97
+
98
+ ```bash
99
+ # negotiate → signed quote envelope
100
+ curl -s -X POST http://localhost:9000/ -H "Content-Type: application/json" -d '{
101
+ "jsonrpc":"2.0","id":1,"method":"message/send",
102
+ "params":{"message":{"role":"user","parts":[{"kind":"data","data":{
103
+ "skill":"negotiate",
104
+ "task_description":"...",
105
+ "terms":{"deliverables":"...","quality_standards":"..."}
106
+ }}],"messageId":"nego-1"}}}'
107
+
108
+ # notify_funded → ack (then background delivery; poll the chain for the result)
109
+ curl -s -X POST http://localhost:9000/ -H "Content-Type: application/json" -d '{
110
+ "jsonrpc":"2.0","id":2,"method":"message/send",
111
+ "params":{"message":{"role":"user","parts":[{"kind":"data","data":{
112
+ "skill":"notify_funded","job_id":<int>
113
+ }}],"messageId":"notify-1"}}}'
114
+ ```
115
+
116
+ See `erc8183-buyer-push.md` for the full line protocol. Ctrl-C to stop.
117
+
118
+ ### B. Doctor — full project health
119
+
120
+ ```bash
121
+ bag doctor
122
+ ```
123
+
124
+ Returns a rich table of checks across the `app/agent/` sub-project:
125
+
126
+ | Check | What FAIL means | Fix |
127
+ |---|---|---|
128
+ | app/agent/studio.toml parseable | Missing or syntax error | `bag init` to regenerate, or hand-fix TOML |
129
+ | Agent entrypoint imports | Protocol entrypoint raises on load (`src/main.ts` for A2A, `src/mcpMain.ts` for MCP) | Fix the error printed by the check (often a missing env var or a broken import) |
130
+ | wallet keystore | No `<workspace>/.studio/wallets/*.json` | `bag wallet new` (writes to the workspace root keystore dir) |
131
+ | WALLET_PASSWORD env | Not in `.studio/.env.local` / not exported | `bag env set WALLET_PASSWORD ...` (targets .studio/.env.local) |
132
+ | LLM provider key | API key env not set | Edit `.studio/.env.local` or export the right `*_API_KEY` |
133
+ | Network reachable | RPC down/wrong URL | Override via `STUDIO_BSC_TESTNET_RPC=...` (testnet) / `STUDIO_BSC_RPC=...` (mainnet) — per-network env vars read by `@bnbagent/studio-runtime/networks` `getNetwork` |
134
+ | Wallet tBNB balance | 0 tBNB | Faucet: testnet.bnbchain.org/faucet-smart |
135
+ | Wallet U balance | 0 U | Transfer from holder, or ask for sponsor U |
136
+ | 8004 registered | Not registered | Normally registered automatically at `bag deploy verify`. Manual: `bag erc8004 register --endpoint <url>` (only if you need an on-chain identity before deploy). WARN-only in `bag doctor` — it doesn't block local dev. |
137
+ | Cognito authorizer (W9) | External-buyer readiness: `agentcore.json` carries no `authorizerConfiguration` / protocol metadata has placeholder `OAUTH_*` values | WARN-only (does NOT block) — needed to serve **external** buyers, not to deploy. With no authorizer the runtime is IAM/SigV4 owner-only (never anonymous). To open it to buyers: `bag deploy provision-cognito` → `cdk deploy --outputs-file cdk-outputs.json` → `bag deploy provision-cognito --wire`. |
138
+
139
+ WARN-only items don't block; FAIL items do (exit 1).
140
+
141
+ ### C. Balance / wallet inspection
142
+
143
+ ```bash
144
+ bag wallet show # local view: address + keystore path (workspace root .studio/wallets/)
145
+ bag wallet list # all keystores in <workspace>/.studio/wallets/
146
+ ```
147
+
148
+ For on-chain balance of the configured wallet (BNB + U):
149
+
150
+ ```bash
151
+ bag wallet balance # [network].default — BNB + U
152
+ bag wallet balance --network bsc-mainnet # override to a specific network
153
+ bag wallet balance --all # both [network].default AND [llm.pieverse].network
154
+ ```
155
+
156
+ The `--all` form is the right move when `app/agent/studio.toml`'s
157
+ `[network].default = bsc-testnet` and `[llm].provider = pieverse-llm`:
158
+ testnet U pays ERC-8183 jobs, mainnet U pays the Pieverse LLM auto-renew.
159
+ Same wallet address on both chains.
160
+
161
+ > ⚠️ **v0.2 backlog — not in v0.0.x.** There is **no** `bag wallet transfer`,
162
+ > no `bag erc20 approve/allowance` group, and no `bag wallet balance --address`
163
+ > / `--token` flag in v0.0.x — running any of them errors with
164
+ > `invalid choice` / `unrecognized arguments`. To move funds or set allowances
165
+ > today, use an external wallet; ERC-8183 funding auto-approves U as part of the
166
+ > buy flow. These CLIs are planned for v0.2.
167
+
168
+ For programmatic access from inside an agent's code, the MCP tools (when wired
169
+ into Claude Code) provide `balance_u` / `balance_native` as well — but the CLI
170
+ is the fastest path during dev.
171
+
172
+ ### D. Job state inspection (8183)
173
+
174
+ ```bash
175
+ bag erc8183 list --mine # all jobs where I'm the client
176
+ bag erc8183 list --provider 0xPROV # jobs I could serve as seller
177
+ bag erc8183 status <job_id> # one job's full record
178
+ ```
179
+
180
+ JobStatus enum: `OPEN` (0) → `FUNDED` (1) → `SUBMITTED` (2) → `COMPLETED` (3) /
181
+ `REJECTED` (4) / `EXPIRED` (5).
182
+
183
+ `FUNDED` jobs are what the deployed agent delivers — either when the buyer sends a
184
+ `notify_funded` A2A message (the agent acks then delivers in the **background**;
185
+ read the result from the chain) or via the deduped background sweep on the next
186
+ notify (see `erc8183-buyer-push.md`). While background work is in flight the
187
+ runtime stays warm via `/ping` `HEALTHY_BUSY`; a scaled-to-zero idle agent won't
188
+ deliver until the next notify (a v2 Lambda poller closes that cold window).
189
+ `SUBMITTED` jobs trigger the **buyer decision
190
+ tree** (approve / dispute / reject within the dispute window) — full flow in the
191
+ `bnbagent-studio-buying-via-8183.md` reference (see the Deep-dive references
192
+ list above). From the seller side, defending a dispute is
193
+ covered in `bnbagent-studio-selling-via-8183.md` (same directory).
194
+
195
+ ### E. Common errors + remediation
196
+
197
+ | Error pattern | Cause | Fix |
198
+ |---|---|---|
199
+ | `Submission deadline has passed` | Buyer set `expiredAt` too soon (< dispute_window) | Use `--deadline-min` ≥ 1 (workflow auto-adds dispute_window now) |
200
+ | `Transaction would revert: ('0x17be5b7b', ...)` | Trying to `settle approve` before dispute_window | Wait 24h or use `--action dispute` |
201
+ | `notify_funded` replies `{"status":"rejected","reason":...}` | `verifySignedJob` failed synchronously in the ack — a **permanent** failure | `reason` names it: not our signature / tampered terms / underfunded / expired (or `error` for a malformed `job_id`). The job is refused outright; re-fund/re-notify with a correct, fully-funded job |
202
+ | Job stays `FUNDED`, never reaches `SUBMITTED` after an `accepted` ack | Background delivery failed (`runWork` / `submitResult` raised) — **not** visible in the A2A reply | The ack only confirms verify passed; delivery runs in the background. Observe the failure via the chain (job never leaves `FUNDED`) + CloudWatch logs; a later `notify_funded` re-attempts it via the sweep |
203
+ | `ERC8183JobOps` has no such export from `@bnbagent/sdk` | package.json pinned an old `@bnbagent/sdk` (missing class) | Bump the dependency and reinstall |
204
+ | `OPENROUTER_API_KEY env var is required` | Loading the entrypoint triggers the emitted `buildModel()` factory | Set the env var even for `bag dev --help` smoke |
205
+ | RPC `limit exceeded` | Public RPC throttle | Retry, or set `STUDIO_BSC_TESTNET_RPC=<private rpc>` |
206
+
207
+ ## Reference
208
+
209
+ - `docs/design/single-seller-agent.md` (the A2A deploy model and history)
210
+ - `docs/design/erc8183-buyer-push.md` (how a buyer drives an A2A sale)
211
+ - `docs/design/architecture.md §2.5` (the single seller runtime — as-built truth)