@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.
- package/DISCLAIMER.md +6 -27
- package/README.md +6 -13
- package/dist/bag.js +1121 -795
- package/dist/{chunk-VEOOFDSF.js → chunk-JZAW6HMV.js} +74 -5
- package/dist/{deployCli-EEK75T67.js → deployCli-AJ25A4VK.js} +1 -1
- package/package.json +2 -2
- package/recipes/providers/pieverse-llm/skills/funding-pieverse-llm.md +32 -64
- package/skills/bnbagent-studio.md +29 -74
- package/skills/references/bnbagent-studio-adding-to-project.md +58 -169
- package/skills/references/bnbagent-studio-buying-from-bazaar.md +43 -104
- package/skills/references/bnbagent-studio-buying-via-8183.md +38 -112
- package/skills/references/bnbagent-studio-extending-signing.md +47 -50
- package/skills/references/bnbagent-studio-operating.md +58 -111
- package/skills/references/bnbagent-studio-scaffolding-agent.md +136 -403
- package/skills/references/bnbagent-studio-selling-via-8183.md +87 -172
- package/skills/references/bnbagent-studio-selling-via-b402.md +39 -131
- package/skills/references/bnbagent-studio-use-aws-agentcore.md +43 -144
- package/skills/references/bnbagent-studio-use-azure-foundry.md +34 -95
- package/skills/references/bnbagent-studio-use-bnb-trial.md +12 -36
- package/skills/references/bnbagent-studio-using-altana-wallet.md +11 -28
- package/skills/references/bnbagent-studio-using-twak-wallet.md +102 -210
- package/skills/references/bnbagent-studio-wiring-llm-tools.md +71 -150
|
@@ -1,291 +1,206 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bnbagent-studio-selling-via-8183
|
|
3
|
-
description: When the user is acting as an ERC-8183 seller on the single selected-protocol AgentCore runtime
|
|
3
|
+
description: When the user is acting as an ERC-8183 seller on the single selected-protocol AgentCore runtime - implementing the value `notify_funded` produces, tuning the deterministic rule-based quote price (fixed list price, clamp + sign - no LLM in the negotiate path), understanding A2A async delivery vs MCP synchronous delivery, handling submitted jobs, defending against buyer disputes, and ensuring LLM credit continuity during long jobs. Owns the seller-side decision tree for the entire job lifecycle.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
> **Reference file** of the `bnbagent-studio` router skill
|
|
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-selling-via-8183
|
|
9
9
|
|
|
10
|
-
Procedure for the **single seller flow**: implement the value your Agent
|
|
11
|
-
produces, deploy it to AgentCore (where it serves A2A by default or MCP
|
|
12
|
-
optionally and signs in-process), and handle the job lifecycle (Agent quotes →
|
|
13
|
-
buyer funds → buyer calls `notify_funded` → Agent delivers → buyer reads the
|
|
14
|
-
result from the chain → buyer settles or disputes).
|
|
10
|
+
Procedure for the **single seller flow**: implement the value your Agent produces, deploy it to AgentCore (where it serves A2A by default or MCP optionally and signs in-process), and handle the job lifecycle (Agent quotes → buyer funds → buyer calls `notify_funded` → Agent delivers → buyer reads the result from the chain → buyer settles or disputes).
|
|
15
11
|
|
|
16
|
-
Audience: Claude Code in a working repo with a funded wallet (tBNB + U) and an
|
|
17
|
-
Agent that produces some valuable output (text, classification, image — whatever).
|
|
12
|
+
Audience: Claude Code in a working repo with a funded wallet (tBNB + U) and an Agent that produces some valuable output (text, classification, image - whatever).
|
|
18
13
|
|
|
19
14
|
**Different from**:
|
|
20
|
-
|
|
21
|
-
- `bnbagent-studio-
|
|
22
|
-
- `bnbagent-studio-
|
|
15
|
+
|
|
16
|
+
- `bnbagent-studio-scaffolding-agent.md` (same directory) - creates the project (this playbook runs after)
|
|
17
|
+
- `bnbagent-studio-adding-to-project.md` (in this same references/ directory) - wires the seller runtime into an existing project (the static setup, not the runtime behavior)
|
|
18
|
+
- `bnbagent-studio-operating.md` (same directory) - generic ops (dev / doctor / balance); jumps here for seller-specific decisions
|
|
23
19
|
|
|
24
20
|
This skill owns: **implement the `notify_funded` value → deploy the agent → defend disputes**.
|
|
25
21
|
|
|
26
22
|
## The single seller runtime (one workspace sub-project)
|
|
27
23
|
|
|
28
|
-
A v1 seller ships as **one runtime**: a single valuable Agent on AWS Bedrock
|
|
29
|
-
AgentCore that **serves its selected protocol directly** (A2A:
|
|
30
|
-
`0.0.0.0:9000`; MCP: `0.0.0.0:8000/mcp`), holds the key, and signs in-process.
|
|
31
|
-
It exposes two fixed-code commerce operations — `negotiate` and `notify_funded`
|
|
32
|
-
— as A2A skills on `SellerAgentExecutor` or tools on the MCP server, behind a
|
|
33
|
-
mandatory Cognito OAuth2 authorizer. There is no separate forwarding service.
|
|
24
|
+
A v1 seller ships as **one runtime**: a single valuable Agent on AWS Bedrock AgentCore that **serves its selected protocol directly** (A2A: `0.0.0.0:9000`; MCP: `0.0.0.0:8000/mcp`), holds the key, and signs in-process. It exposes two fixed-code commerce operations - `negotiate` and `notify_funded` - as A2A skills on `SellerAgentExecutor` or tools on the MCP server, behind a mandatory Cognito OAuth2 authorizer. There is no separate forwarding service.
|
|
34
25
|
|
|
35
26
|
| Sub-project | Role |
|
|
36
|
-
|
|
37
|
-
| `<workspace>/app/agent/` | The value (LLM/memory/tools/KB) AND the **sole signer**, deployed to AgentCore and serving the selected protocol. A2A uses `SellerAgentExecutor` in `<workspace>/app/agent/src/executor.ts`, which reads the inbound A2A message's data part and dispatches on its `"skill"` (`negotiate` / `notify_funded`); MCP uses `src/mcpMain.ts` tools with the same bounded operations. ALL signing is fixed `<workspace>/app/agent/src/signing.ts` code
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `<workspace>/app/agent/` | The value (LLM/memory/tools/KB) AND the **sole signer**, deployed to AgentCore and serving the selected protocol. A2A uses `SellerAgentExecutor` in `<workspace>/app/agent/src/executor.ts`, which reads the inbound A2A message's data part and dispatches on its `"skill"` (`negotiate` / `notify_funded`); MCP uses `src/mcpMain.ts` tools with the same bounded operations. ALL signing is fixed `<workspace>/app/agent/src/signing.ts` code - never an LLM tool. Keystore lives at the WORKSPACE root `<workspace>/.studio/wallets/` (outside the AgentCore codeLocation, so no deploy packaging path can bundle it; the Agent is its sole reader via `[wallet].keystore_dir`). At deploy the keystore is injected via AWS Secrets Manager (`WALLET_KEYSTORE_JSON`) and reconstructed at cold start by the entrypoint's `loadRuntimeSecrets()`. Config in `<workspace>/app/agent/studio.toml`. |
|
|
38
29
|
|
|
39
|
-
> The earlier two-layer model (an invoke-only Agent plus a public keyless EC2
|
|
40
|
-
> service relaying via `InvokeAgentRuntime`) is **removed**. Once AgentCore could
|
|
41
|
-
> serve the protocol surface on a public HTTPS endpoint, the agent became its own
|
|
42
|
-
> public surface and the relay disappeared. See `docs/design/single-seller-agent.md`
|
|
43
|
-
> for the A2A decision history.
|
|
30
|
+
> The earlier two-layer model (an invoke-only Agent plus a public keyless EC2 service relaying via `InvokeAgentRuntime`) is **removed**. Once AgentCore could serve the protocol surface on a public HTTPS endpoint, the agent became its own public surface and the relay disappeared. See `docs/design/single-seller-agent.md` for the A2A decision history.
|
|
44
31
|
|
|
45
32
|
## Preconditions
|
|
46
33
|
|
|
47
|
-
- `bag doctor` is clean (or only warns on optional checks)
|
|
34
|
+
- `bag doctor` is clean (or only warns on optional checks) - run from workspace root
|
|
48
35
|
- Wallet has ≥ 0.05 tBNB (gas to submit deliverables) and ≥ 0 U (sellers receive U, don't spend)
|
|
49
36
|
- The agent sub-project is emitted (`<workspace>/app/agent/src/main.ts` for A2A or `src/mcpMain.ts` for MCP, plus `src/signing.ts`). If not, run `bag init` or read the `bnbagent-studio-adding-to-project.md` reference first.
|
|
50
37
|
- For LLM-using sellers: `[llm].provider` configured in `app/agent/studio.toml` + (if Pieverse) `bag llm activate` has been run
|
|
51
38
|
|
|
52
|
-
## Stage 1
|
|
39
|
+
## Stage 1 - Implement the `notify_funded` value (the `runWork` hook)
|
|
53
40
|
|
|
54
|
-
The valuable work lives in the `notify_funded` path. When a buyer calls
|
|
55
|
-
`notify_funded` for a `job_id`, the runtime first synchronously re-verifies the
|
|
56
|
-
job is genuinely FUNDED + ours on-chain (`signing.ts` `verifySignedJob`). In A2A
|
|
57
|
-
mode, the executor **acks `accepted`** at once and then runs the LLM work +
|
|
58
|
-
`signing.ts` `submitResult` (which SIGNS + broadcasts the deliverable) in a
|
|
59
|
-
**background task**. In MCP mode, the tool call verifies, runs the LLM work, and
|
|
60
|
-
submits synchronously, reporting progress while it runs. The block to specialise
|
|
61
|
-
is the **developer hook** — the work function that produces the deliverable text:
|
|
41
|
+
The valuable work lives in the `notify_funded` path. When a buyer calls `notify_funded` for a `job_id`, the runtime first synchronously re-verifies the job is genuinely FUNDED + ours on-chain (`signing.ts` `verifySignedJob`). In A2A mode, the executor **acks `accepted`** at once and then runs the LLM work + `signing.ts` `submitResult` (which SIGNS + broadcasts the deliverable) in a **background task**. In MCP mode, the tool call verifies, runs the LLM work, and submits synchronously, reporting progress while it runs. The block to specialise is the **developer hook** - the work function that produces the deliverable text:
|
|
62
42
|
|
|
63
43
|
```ts
|
|
64
|
-
async function runWork(
|
|
65
|
-
|
|
44
|
+
async function runWork(
|
|
45
|
+
prompt: string,
|
|
46
|
+
opts: { sessionId: string },
|
|
47
|
+
): Promise<string> {
|
|
48
|
+
// DEVELOPER HOOK - replace the generic LLM passthrough with your real work:
|
|
66
49
|
// call domain tools, hit your APIs, run a pipeline, use the KB.
|
|
67
|
-
// Return the deliverable TEXT
|
|
50
|
+
// Return the deliverable TEXT - the executor handles submit + on-chain signing.
|
|
68
51
|
const { text } = await generateText({ model, tools: LLM_READ_TOOLS, prompt });
|
|
69
52
|
return text;
|
|
70
53
|
}
|
|
71
54
|
```
|
|
72
55
|
|
|
73
56
|
**Hard rules**:
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
The quote path is **deterministic policy
|
|
82
|
-
|
|
83
|
-
1. Fixed code reads the configured **list price** from `[payments.erc8183].price`
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
2. **Fixed code CLAMPS** the list price to `[min_price, max_price]`
|
|
87
|
-
(`signing.ts` `clampPrice()`) — a misconfigured or hostile request can never sign
|
|
88
|
-
out of bounds. For per-task pricing, compute the price from the request in the
|
|
89
|
-
quote path *before* clamping; it stays deterministic code, not an LLM decision.
|
|
90
|
-
3. `signing.ts` `signQuote` does the **EIP-191 sign** with a short TTL (returns the
|
|
91
|
-
SDK `NegotiationResult` envelope verbatim — price, currency, negotiation_hash,
|
|
92
|
-
provider_sig), which the executor returns directly to the buyer over A2A.
|
|
93
|
-
`chain_id` + `verifying_contract` are bound into the signature, so the quote
|
|
94
|
-
cannot be replayed on another chain/contract. **Money is never in the LLM.**
|
|
57
|
+
|
|
58
|
+
- The `notify_funded` work must finish before the on-chain `submitDeadline` - keep it bounded (A2A also has to land within the session max-lifetime, ≤8h).
|
|
59
|
+
- Don't raise unhandled exceptions through `submitResult`. A permanently-bad job is rejected synchronously. In A2A, once accepted, a background delivery FAILURE leaves the job FUNDED (never reaching SUBMITTED) and is surfaced in CloudWatch - not the A2A reply. Let work errors surface so the job simply doesn't get a deliverable and the buyer can dispute cleanly; don't fake a deliverable.
|
|
60
|
+
- All chain WRITES go through `app/agent/src/signing.ts` (fixed code). In the `notify_funded` work the LLM only PRODUCES work text - it never signs, and it never sets the price (the quote price is rule-based; see Stage 2).
|
|
61
|
+
|
|
62
|
+
## Stage 2 - Rule-based pricing (fixed list price, clamp + sign - no LLM)
|
|
63
|
+
|
|
64
|
+
A `negotiate` skill message hits the executor, which dispatches to the quote path. The quote path is **deterministic policy - no LLM, no tools**:
|
|
65
|
+
|
|
66
|
+
1. Fixed code reads the configured **list price** from `[payments.erc8183].price` (`signing.ts` `listPrice()`). The LLM is never invoked in the negotiate path and never proposes or touches the price.
|
|
67
|
+
2. **Fixed code CLAMPS** the list price to `[min_price, max_price]` (`signing.ts` `clampPrice()`) - a misconfigured or hostile request can never sign out of bounds. For per-task pricing, compute the price from the request in the quote path _before_ clamping; it stays deterministic code, not an LLM decision.
|
|
68
|
+
3. `signing.ts` `signQuote` does the **EIP-191 sign** with a short TTL (returns the SDK `NegotiationResult` envelope verbatim - price, currency, negotiation_hash, provider_sig), which the executor returns directly to the buyer over A2A. `chain_id` + `verifying_contract` are bound into the signature, so the quote cannot be replayed on another chain/contract. **Money is never in the LLM.**
|
|
95
69
|
|
|
96
70
|
Tune the clamp in `<workspace>/app/agent/studio.toml`:
|
|
97
71
|
|
|
98
72
|
```toml
|
|
99
73
|
# app/agent/studio.toml
|
|
100
74
|
[payments.erc8183]
|
|
101
|
-
currency = "0x..." # $U token
|
|
102
|
-
price = "0" # raw wei
|
|
103
|
-
min_price = "0" # raw wei
|
|
104
|
-
max_price = "0" # raw wei
|
|
75
|
+
currency = "0x..." # $U token - prefilled by `bag init` from [network].default; rarely changed
|
|
76
|
+
price = "0" # raw wei - the asking list price the quote signs
|
|
77
|
+
min_price = "0" # raw wei - clamp floor
|
|
78
|
+
max_price = "0" # raw wei - clamp ceiling (set > 0 to enforce)
|
|
105
79
|
quote_ttl_seconds = 300
|
|
106
80
|
default_estimated_completion_seconds = 600
|
|
107
81
|
```
|
|
108
82
|
|
|
109
|
-
An explicit `price = "0"` opts into free jobs when the selected ERC-8183
|
|
110
|
-
contract supports zero-price funding. Keep `currency` configured because it
|
|
111
|
-
remains part of the signed quote.
|
|
83
|
+
An explicit `price = "0"` opts into free jobs when the selected ERC-8183 contract supports zero-price funding. Keep `currency` configured because it remains part of the signed quote.
|
|
112
84
|
|
|
113
|
-
Prefer the CLI so the zero-price choice is visible and remains a decimal
|
|
114
|
-
string:
|
|
85
|
+
Prefer the CLI so the zero-price choice is visible and remains a decimal string:
|
|
115
86
|
|
|
116
87
|
```bash
|
|
117
88
|
bag config set payments.erc8183.price 0
|
|
118
|
-
bag env set ERC8183_COMMERCE_ADDRESS
|
|
119
|
-
bag env set ERC8183_ROUTER_ADDRESS
|
|
120
|
-
bag env set ERC8183_POLICY_ADDRESS
|
|
89
|
+
bag env set ERC8183_COMMERCE_ADDRESS '0x...'
|
|
90
|
+
bag env set ERC8183_ROUTER_ADDRESS '0x...'
|
|
91
|
+
bag env set ERC8183_POLICY_ADDRESS '0x...'
|
|
121
92
|
bag doctor
|
|
122
93
|
bag deploy prepare
|
|
123
94
|
```
|
|
124
95
|
|
|
125
|
-
Take all three addresses from the same compatible custom deployment.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
If `[llm].provider = "pieverse-llm"`, the Agent's emitted
|
|
132
|
-
`app/agent/src/model.ts` `buildModel()` factory returns an AI SDK model wrapped
|
|
133
|
-
with credit-ensure middleware (the stack-neutral credit logic lives in
|
|
134
|
-
`@bnbagent/studio-runtime/pieverse` `PieverseCreditEnsurer`; the AI-SDK shell
|
|
135
|
-
is the emitted file). Its **automatic, budget-gated auto-renew hook** tops up
|
|
136
|
-
the active Pieverse key before an LLM call when the cached balance is below
|
|
137
|
-
the floor. It fires **only in `notify_funded` work** (the `negotiate` path
|
|
138
|
-
runs no LLM, so it never triggers there). This is the **only automatic signing
|
|
139
|
-
path outside `signing.ts`**; it rides on the hardened x402 buyer kernel
|
|
140
|
-
(`@bnbagent/studio-runtime/x402`, the payment signer) but is **NOT an LLM
|
|
141
|
-
tool** — the Agent (the sole key-holder) does it transparently inside the
|
|
142
|
-
model wrapper.
|
|
96
|
+
Take all three addresses from the same compatible custom deployment. Doctor/prepare reject canonical or partial contract selection for FREE and announce `zero token escrow` only when the complete custom stack is selected.
|
|
97
|
+
|
|
98
|
+
## Stage 3 - LLM credit continuity (Pieverse projects only)
|
|
99
|
+
|
|
100
|
+
If `[llm].provider = "pieverse-llm"`, the Agent's emitted `app/agent/src/model.ts` `buildModel()` factory returns an AI SDK model wrapped with credit-ensure middleware (the stack-neutral credit logic lives in `@bnbagent/studio-runtime/pieverse` `PieverseCreditEnsurer`; the AI-SDK shell is the emitted file). Its **automatic, budget-gated auto-renew hook** tops up the active Pieverse key before an LLM call when the cached balance is below the floor. It fires **only in `notify_funded` work** (the `negotiate` path runs no LLM, so it never triggers there). This is the **only automatic signing path outside `signing.ts`**; it rides on the hardened x402 buyer kernel (`@bnbagent/studio-runtime/x402`, the payment signer) but is **NOT an LLM tool** - the Agent (the sole key-holder) does it transparently inside the model wrapper.
|
|
143
101
|
|
|
144
102
|
| Layer | Mechanism | When it fires |
|
|
145
|
-
|
|
103
|
+
| --- | --- | --- |
|
|
146
104
|
| **Per-call auto-renew hook** | The emitted managed-model wrapper checks key balance before each LLM call | Cache miss (60s default) or balance < `min_balance_usd` |
|
|
147
105
|
|
|
148
|
-
If `[budget].enabled = true` (opt-in), the hook auto-tops-up from the
|
|
149
|
-
wallet within the 6-gate budget; otherwise it raises
|
|
150
|
-
`PieverseAccountBalanceExhaustedError` and the executor's `notify_funded`
|
|
151
|
-
work should:
|
|
106
|
+
If `[budget].enabled = true` (opt-in), the hook auto-tops-up from the wallet within the 6-gate budget; otherwise it raises `PieverseAccountBalanceExhaustedError` and the executor's `notify_funded` work should:
|
|
152
107
|
|
|
153
108
|
1. Let the error surface in the background task so the job stays FUNDED (never reaches SUBMITTED) and the buyer can dispute (don't silently fake a deliverable). The job was already acked `accepted`, so the failure is visible on-chain + in CloudWatch, not in the A2A reply.
|
|
154
|
-
2. **Don't** retry
|
|
109
|
+
2. **Don't** retry - the buyer's deadline keeps ticking
|
|
155
110
|
3. The owner sees the error in CloudWatch logs + should run `bag llm topup` to refill (or `bag budget enable`)
|
|
156
111
|
|
|
157
112
|
Full Pieverse credit decisions live in `funding-pieverse-llm` (project-scope skill in Pieverse projects).
|
|
158
113
|
|
|
159
|
-
## Stage 4
|
|
114
|
+
## Stage 4 - Deploy + register (announce to buyers)
|
|
160
115
|
|
|
161
|
-
ERC-8183 / ERC-8004 registration is a **deploy-time** concern: the public
|
|
162
|
-
AgentCore endpoint must exist before you register, so register **last**. The
|
|
163
|
-
agent endpoint has no anonymous mode, so you must provision the Cognito OAuth2
|
|
164
|
-
authorizer first.
|
|
116
|
+
ERC-8183 / ERC-8004 registration is a **deploy-time** concern: the public AgentCore endpoint must exist before you register, so register **last**. The agent endpoint has no anonymous mode; `bag deploy` provisions the Cognito OAuth2 authorizer as part of the deploy.
|
|
165
117
|
|
|
166
118
|
```bash
|
|
167
119
|
bag deploy prepare # readiness sweep
|
|
168
|
-
bag deploy provision-cognito # emit the Cognito CDK app; run `cdk deploy`, wire discoveryUrl/clientId
|
|
169
120
|
bag deploy --provider aws # ship the agent to AgentCore (selected protocol)
|
|
170
121
|
bag deploy verify --provider aws # delegated status + reconcile ERC-8004 identity
|
|
171
122
|
```
|
|
172
123
|
|
|
173
|
-
ERC-8004 identity is registered with the **AgentCore endpoint**: A2A uses
|
|
174
|
-
`AgentEndpoint.a2a(baseUrl, "0.3.0")` (normalizing to
|
|
175
|
-
`/.well-known/agent-card.json`), while MCP records the `/mcp` endpoint plus access
|
|
176
|
-
metadata. Buyers reach the agent directly. `bag deploy verify --provider aws`
|
|
177
|
-
asks bnbagent-deploy for live status first, then performs the reconcile.
|
|
124
|
+
ERC-8004 identity is registered with the **AgentCore endpoint**: A2A uses `AgentEndpoint.a2a(baseUrl, "0.3.0")` (normalizing to `/.well-known/agent-card.json`), while MCP records the `/mcp` endpoint plus access metadata. Buyers reach the agent directly. `bag deploy verify --provider aws` asks bnbagent-deploy for live status first, then performs the reconcile.
|
|
178
125
|
|
|
179
126
|
**Hard rules**:
|
|
127
|
+
|
|
180
128
|
- The endpoint must be **reachable** when registered. For A2A, smoke test the normalized card URL directly, for example `curl <agentcore-invocations-url>/.well-known/agent-card.json` (or `curl <already-registered-card-url>` if the endpoint already includes `/.well-known/agent-card.json`). For MCP, connect an MCP client to the deployed `/mcp` URL. Chain doesn't verify reachability, but buyers will see failures.
|
|
181
|
-
-
|
|
182
|
-
- Price bounds (`min_price`/`max_price`) live with the Agent
|
|
183
|
-
|
|
184
|
-
## Stage 5
|
|
185
|
-
|
|
186
|
-
There is **no background poll loop** in v1. Delivery is triggered by
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
on-chain → job → SUBMITTED. The buyer **polls the chain** for the result (it
|
|
196
|
-
does not wait on the ack), then approves or disputes within `dispute_window`
|
|
197
|
-
(24h on testnet). While any background delivery is in flight the runtime
|
|
198
|
-
reports `/ping` `HEALTHY_BUSY` (AgentCore's long-running async pattern), so the
|
|
199
|
-
scale-to-zero runtime stays warm until the work lands — bounded by the session
|
|
200
|
-
max-lifetime (≤8h).
|
|
201
|
-
2. **A2A in-process sweep (the fallback):** on every accepted `notify_funded`, the
|
|
202
|
-
executor opportunistically sweeps (in the background)
|
|
203
|
-
`ERC8183JobOps.getPendingJobs()` for other FUNDED jobs assigned to this
|
|
204
|
-
provider and delivers them too. This catches jobs whose buyer funded on-chain
|
|
205
|
-
but never pushed `notify_funded`. The sweep is **deduped** (a job already being
|
|
206
|
-
delivered — by the notification or a concurrent sweep — is skipped via an
|
|
207
|
-
in-flight set, so notify + sweep never double-deliver the same job),
|
|
208
|
-
**idempotent** (`verifySignedJob` returns non-OK for an already-SUBMITTED
|
|
209
|
-
job, so there is no state file), and **best-effort** (one bad job never aborts
|
|
210
|
-
the sweep, and a sweep failure never affects the ack).
|
|
211
|
-
3. **MCP synchronous delivery:** buyer negotiates through the `negotiate` MCP
|
|
212
|
-
tool, funds on-chain, then calls `notify_funded`; the tool verifies, runs the
|
|
213
|
-
work, and signs + submits before returning, with progress heartbeats. There is
|
|
214
|
-
no background ack/sweep path in MCP.
|
|
215
|
-
|
|
216
|
-
Because the sweep runs only when *someone* invokes `notify_funded` (and only while
|
|
217
|
-
the runtime is warm), a totally idle, scaled-to-zero agent will not deliver during
|
|
218
|
-
the cold window until the next notify. A periodic Lambda poller is the v2
|
|
219
|
-
robustness path that closes it. The full line protocol is in
|
|
220
|
-
`docs/design/erc8183-buyer-push.md`.
|
|
221
|
-
|
|
222
|
-
Manual override (rare — only the agent holds the key):
|
|
129
|
+
- `bag deploy --provider aws` provisions the Cognito user pool + buyer M2M client and prints the token URL, client id, and scope. Hand those to each buyer (the client secret is retrieved read-only from the AWS Console - studio never stores it). `bag deploy provision-cognito` is deprecated; its CDK pool is never used by a deploy.
|
|
130
|
+
- Price bounds (`min_price`/`max_price`) live with the Agent - it clamps + signs the quote.
|
|
131
|
+
|
|
132
|
+
## Stage 5 - How a SUBMITTED job happens
|
|
133
|
+
|
|
134
|
+
There is **no background poll loop** in v1. Delivery is triggered by `notify_funded`; the execution model depends on the selected protocol:
|
|
135
|
+
|
|
136
|
+
1. **A2A buyer push (the prompt path):** buyer negotiates over A2A (`negotiate` skill) → buyer anchors the signed quote on-chain (`createJob` → `register` → `setBudget` → `fund`, provider = the agent address) → buyer pushes a `notify_funded` A2A message for the `job_id` → the executor synchronously re-verifies (`verifySignedJob`) and **acks `accepted`** at once, then in a **background task** does the LLM work and SIGNS + submits the deliverable on-chain → job → SUBMITTED. The buyer **polls the chain** for the result (it does not wait on the ack), then approves or disputes within `dispute_window` (24h on testnet). While any background delivery is in flight the runtime reports `/ping` `HEALTHY_BUSY` (AgentCore's long-running async pattern), so the scale-to-zero runtime stays warm until the work lands - bounded by the session max-lifetime (≤8h).
|
|
137
|
+
2. **A2A in-process sweep (the fallback):** on every accepted `notify_funded`, the executor opportunistically sweeps (in the background) `ERC8183JobOps.getPendingJobs()` for other FUNDED jobs assigned to this provider and delivers them too. This catches jobs whose buyer funded on-chain but never pushed `notify_funded`. The sweep is **deduped** (a job already being delivered - by the notification or a concurrent sweep - is skipped via an in-flight set, so notify + sweep never double-deliver the same job), **idempotent** (`verifySignedJob` returns non-OK for an already-SUBMITTED job, so there is no state file), and **best-effort** (one bad job never aborts the sweep, and a sweep failure never affects the ack).
|
|
138
|
+
3. **MCP synchronous delivery:** buyer negotiates through the `negotiate` MCP tool, funds on-chain, then calls `notify_funded`; the tool verifies, runs the work, and signs + submits before returning, with progress heartbeats. There is no background ack/sweep path in MCP.
|
|
139
|
+
|
|
140
|
+
Because the sweep runs only when _someone_ invokes `notify_funded` (and only while the runtime is warm), a totally idle, scaled-to-zero agent will not deliver during the cold window until the next notify. A periodic Lambda poller is the v2 robustness path that closes it. The full line protocol is in `docs/design/erc8183-buyer-push.md`.
|
|
141
|
+
|
|
142
|
+
Manual override (rare - only the agent holds the key):
|
|
223
143
|
|
|
224
144
|
```bash
|
|
225
145
|
bag erc8183 submit <job_id> "<deliverable text>" [--metadata-json '{...}']
|
|
226
146
|
```
|
|
227
147
|
|
|
228
|
-
Use only if the Agent produced a deliverable out-of-band and you need to attach it
|
|
229
|
-
manually.
|
|
148
|
+
Use only if the Agent produced a deliverable out-of-band and you need to attach it manually.
|
|
230
149
|
|
|
231
|
-
## Stage 6
|
|
150
|
+
## Stage 6 - Defending against disputes
|
|
232
151
|
|
|
233
152
|
Buyer can `settle --action dispute` within `dispute_window`. Seller responses:
|
|
234
153
|
|
|
235
154
|
| Symptom | Diagnosis | Action |
|
|
236
|
-
|
|
155
|
+
| --- | --- | --- |
|
|
237
156
|
| Buyer disputed within 24h | Their right; goes to quorum vote | Provide evidence via the off-chain governance flow; don't argue on-chain |
|
|
238
157
|
| `0x17be5b7b` revert when buyer tried to `approve` | Buyer tried to approve before 24h passed | This is buyer's mistake, not yours; they'll need to wait or use `dispute` |
|
|
239
158
|
| `Submission deadline has passed` when you tried to submit | Buyer set too-short `expiredAt` on the job | You can't submit late; politely tell buyer to re-buy with longer deadline |
|
|
240
159
|
| Job stuck `FUNDED` for >24h | Nobody pushed `notify_funded` (and the agent stayed idle, so the sweep never ran) or the background `runWork` crashed (the job was acked `accepted` but never reached SUBMITTED) | Inspect CloudWatch logs; push a `notify_funded` to wake the agent, or submit work manually if a deliverable exists but submit failed |
|
|
241
160
|
|
|
242
161
|
**Hard rules**:
|
|
162
|
+
|
|
243
163
|
- Never tamper with quorum vote signals (no fake validators / no spam-disputes).
|
|
244
|
-
- If you produced a defective deliverable, **don't dispute**
|
|
164
|
+
- If you produced a defective deliverable, **don't dispute** - accept the buyer's reject; chain reputation is real.
|
|
245
165
|
- Keep the agent's logs (it prints redacted audit events to stdout → CloudWatch).
|
|
246
166
|
|
|
247
|
-
## Stage 7
|
|
167
|
+
## Stage 7 - Buyer settlement and seller payout
|
|
248
168
|
|
|
249
|
-
`settle` is the **
|
|
250
|
-
v1 (no long-running process to run it). After the dispute window elapses:
|
|
169
|
+
`settle` is the **buyer's** manual step; a quorum voter may also reject or resolve a dispute. There is no in-runtime auto-settle in the current single-runtime seller. After the dispute window elapses, the buyer can approve:
|
|
251
170
|
|
|
252
171
|
```bash
|
|
253
|
-
bag erc8183 settle <job_id> # default --action approve
|
|
172
|
+
bag erc8183 settle <job_id> # buyer wallet; default --action approve
|
|
254
173
|
bag erc8183 status <job_id> # confirm COMPLETED
|
|
255
174
|
# Funds auto-transfer on COMPLETED in the current contract; no manual withdraw needed.
|
|
256
175
|
```
|
|
257
176
|
|
|
258
|
-
Older contracts may have required a manual `withdraw`
|
|
259
|
-
deployed commerce contract's behavior.
|
|
177
|
+
Older contracts may have required a manual `withdraw` - confirm against the deployed commerce contract's behavior.
|
|
260
178
|
|
|
261
179
|
## How a buyer reads the deliverable
|
|
262
180
|
|
|
263
|
-
The agent serves **no** job-query endpoint. The buyer reads the deliverable back
|
|
264
|
-
from the on-chain submission (the `submit` tx carries the deterministic
|
|
265
|
-
`deliverable_url`) / the IPFS object. This is by design — the chain is the shared
|
|
266
|
-
source of truth, and the agent stays a thin A2A surface.
|
|
181
|
+
The agent serves **no** job-query endpoint. The buyer reads the deliverable back from the on-chain submission (the `submit` tx carries the deterministic `deliverable_url`) / the IPFS object. This is by design - the chain is the shared source of truth, and the agent stays a thin A2A surface.
|
|
267
182
|
|
|
268
183
|
## Common errors + remediation
|
|
269
184
|
|
|
270
185
|
| Error | Cause | Fix |
|
|
271
|
-
|
|
272
|
-
| A2A job acked `accepted` but never reaches SUBMITTED | background `runWork` / `submitResult` raised (the failure is NOT in the A2A reply
|
|
186
|
+
| --- | --- | --- |
|
|
187
|
+
| A2A job acked `accepted` but never reaches SUBMITTED | background `runWork` / `submitResult` raised (the failure is NOT in the A2A reply - the ack already went out) | Inspect CloudWatch logs; wrap LLM/domain calls; let the error surface so the buyer can dispute, don't fake a deliverable |
|
|
273
188
|
| `notify_funded` reply `{ "status": "rejected", "reason": ... }` | synchronous verify failed (not our signature, tampered terms, underfunded, expired) or malformed `job_id` | Confirm the buyer funded the exact signed quote against this provider; re-quote if terms changed |
|
|
274
|
-
| `submit_work reverts gas estimation` | Job already SUBMITTED (idempotency violation) | Check `bag erc8183 status <id>` before retry
|
|
189
|
+
| `submit_work reverts gas estimation` | Job already SUBMITTED (idempotency violation) | Check `bag erc8183 status <id>` before retry - the sweep already handles this idempotently |
|
|
275
190
|
| `PieverseAccountBalanceExhaustedError` mid-job | Agent's LLM credit ran out | Let it surface; run `bag llm topup`; consider `bag budget enable` |
|
|
276
191
|
| Agent unreachable (buyer reports) | AgentCore runtime is down, DNS wrong, or the OAuth2 bearer is missing/expired | `bag deploy status` / `bag deploy logs --provider aws` to inspect; redeploy via `bag deploy --provider aws` |
|
|
277
192
|
|
|
278
193
|
## Hard rules (security boundary)
|
|
279
194
|
|
|
280
195
|
- Don't store buyer-supplied data outside the request lifecycle (privacy + storage cost).
|
|
281
|
-
- The Agent signs only
|
|
282
|
-
- The key lives ONLY in the agent at the workspace root `.studio/wallets/` (outside every codeLocation, so no packaging path can bundle it) and is injected into the agent via AWS Secrets Manager at deploy
|
|
283
|
-
- Inbound auth is mandatory Cognito OAuth2
|
|
284
|
-
- LLM model name selection (paid vs free) is a per-project decision
|
|
196
|
+
- The Agent signs only its own quote and submit actions; the buyer or quorum signs settlement actions.
|
|
197
|
+
- The key lives ONLY in the agent at the workspace root `.studio/wallets/` (outside every codeLocation, so no packaging path can bundle it) and is injected into the agent via AWS Secrets Manager at deploy - never inlined into the code artifact (mainnet refuses the envvars fallback). Never log API keys / PII into stdout (the agent's audit events are redacted before they hit CloudWatch).
|
|
198
|
+
- Inbound auth is mandatory Cognito OAuth2 - buyers send plain HTTPS + a Bearer (no AWS SigV4). An unauthorized request is rejected 401; there is no anonymous mode.
|
|
199
|
+
- LLM model name selection (paid vs free) is a per-project decision - load `funding-pieverse-llm` if user is unsure which model to use for paid services.
|
|
285
200
|
|
|
286
201
|
## Reference
|
|
287
202
|
|
|
288
203
|
- `docs/design/single-seller-agent.md` (the A2A deploy model and history)
|
|
289
204
|
- `docs/design/erc8183-buyer-push.md` (the negotiate → fund → notify_funded line protocol)
|
|
290
|
-
- `docs/design/architecture.md` §2.5 (the single seller runtime
|
|
291
|
-
- the `bnbagent-studio-wiring-llm-tools.md` reference (in this same references/ directory)
|
|
205
|
+
- `docs/design/architecture.md` §2.5 (the single seller runtime - as-built)
|
|
206
|
+
- the `bnbagent-studio-wiring-llm-tools.md` reference (in this same references/ directory) - wiring read-only chain tools into the Agent's LLM
|