@bnbagent/studio-cli 0.0.11-alpha.3 → 0.0.11-alpha.5

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/dist/bag.js CHANGED
@@ -47,10 +47,12 @@ import {
47
47
  whichBin,
48
48
  withDeployFiles,
49
49
  x402DeploySummary,
50
+ x402DeploySummaryFromSnapshot,
51
+ x402DeploymentSnapshot,
50
52
  x402SellerIsFree,
51
53
  x402SellerPricingState,
52
54
  x402SellerUsesB402
53
- } from "./chunk-MIYN6U2D.js";
55
+ } from "./chunk-XY6EZGQF.js";
54
56
  import {
55
57
  TWAK_CLI_MIN_VERSION,
56
58
  TWAK_CLI_VERSION,
@@ -228,7 +230,7 @@ import {
228
230
  var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
229
231
  var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
230
232
  async function fetchCampaignActive() {
231
- const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-AED2MLUB.js");
233
+ const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-OQICQCKT.js");
232
234
  const controller = new AbortController();
233
235
  const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
234
236
  try {
@@ -3363,6 +3365,21 @@ function protocolFaces(value) {
3363
3365
  return null;
3364
3366
  }
3365
3367
  }
3368
+ function recordedX402Snapshot(azure) {
3369
+ const status = text(azure.deployed_x402_status);
3370
+ const priceMode = text(azure.deployed_x402_price_mode);
3371
+ const credentialsComplete = azure.deployed_x402_credentials_complete;
3372
+ if (!["active", "free", "dormant"].includes(status ?? "") || !["paid", "free", "invalid"].includes(priceMode ?? "") || typeof credentialsComplete !== "boolean") {
3373
+ return null;
3374
+ }
3375
+ const expectedStatus = priceMode === "free" ? "free" : priceMode === "paid" && credentialsComplete ? "active" : "dormant";
3376
+ if (status !== expectedStatus) return null;
3377
+ return {
3378
+ status,
3379
+ priceMode,
3380
+ credentialsComplete
3381
+ };
3382
+ }
3366
3383
  function descriptorName(workspaceRoot) {
3367
3384
  try {
3368
3385
  const data = JSON.parse(
@@ -3420,6 +3437,7 @@ function discoverRecordedDeployments(root) {
3420
3437
  const azureEndpoint = text(azure.agent_endpoint);
3421
3438
  const azureDeploymentId = text(azure.deployment_id);
3422
3439
  const azureFaces = protocolFaces(azure.deployed_faces);
3440
+ const azureX402 = recordedX402Snapshot(azure);
3423
3441
  if (azureEndpoint || azureDeploymentId || text(azure.last_deploy_at)) {
3424
3442
  found.push({
3425
3443
  provider: "azure",
@@ -3428,6 +3446,7 @@ function discoverRecordedDeployments(root) {
3428
3446
  deploymentId: azureDeploymentId,
3429
3447
  endpoint: azureEndpoint,
3430
3448
  ...azureFaces ? { faces: azureFaces } : {},
3449
+ ...azureX402 ? { x402: azureX402 } : {},
3431
3450
  status: "active"
3432
3451
  });
3433
3452
  }
@@ -4175,9 +4194,13 @@ function recordAzureDeployment(root, data, endpoint) {
4175
4194
  if (agentRoot2 === null) return;
4176
4195
  const tomlPath = path16.join(agentRoot2, "studio.toml");
4177
4196
  let deployedFaces = null;
4197
+ let deployedX402 = null;
4178
4198
  try {
4179
4199
  const cfg = loadStudioCfg(deployWorkspaceRoot(root));
4180
4200
  deployedFaces = stackFaces(tableOf4(cfg, "stack"), tableOf4(cfg, "payments"));
4201
+ if (hasX402Face(deployedFaces)) {
4202
+ deployedX402 = x402DeploymentSnapshot(agentRoot2, "self");
4203
+ }
4181
4204
  } catch {
4182
4205
  }
4183
4206
  try {
@@ -4192,6 +4215,24 @@ function recordAzureDeployment(root, data, endpoint) {
4192
4215
  }
4193
4216
  if (deployedFaces) {
4194
4217
  patchTomlKv(tomlPath, "azure", "deployed_faces", deployedFaces);
4218
+ patchTomlKv(
4219
+ tomlPath,
4220
+ "azure",
4221
+ "deployed_x402_status",
4222
+ deployedX402?.status ?? ""
4223
+ );
4224
+ patchTomlKv(
4225
+ tomlPath,
4226
+ "azure",
4227
+ "deployed_x402_price_mode",
4228
+ deployedX402?.priceMode ?? ""
4229
+ );
4230
+ patchTomlKv(
4231
+ tomlPath,
4232
+ "azure",
4233
+ "deployed_x402_credentials_complete",
4234
+ deployedX402?.credentialsComplete ?? false
4235
+ );
4195
4236
  }
4196
4237
  patchTomlKv(tomlPath, "azure", "last_deploy_at", (/* @__PURE__ */ new Date()).toISOString());
4197
4238
  } catch {
@@ -4211,6 +4252,9 @@ function clearAzureEndpoint(root) {
4211
4252
  patchTomlKv(tomlPath, "azure", key, "");
4212
4253
  }
4213
4254
  patchTomlKv(tomlPath, "azure", "deployed_faces", []);
4255
+ patchTomlKv(tomlPath, "azure", "deployed_x402_status", "");
4256
+ patchTomlKv(tomlPath, "azure", "deployed_x402_price_mode", "");
4257
+ patchTomlKv(tomlPath, "azure", "deployed_x402_credentials_complete", false);
4214
4258
  } catch {
4215
4259
  }
4216
4260
  }
@@ -4270,6 +4314,7 @@ async function deployAzureFoundry(opts) {
4270
4314
  "deploy",
4271
4315
  "-f",
4272
4316
  files.configPath,
4317
+ ...opts.onboard ? ["--onboard"] : [],
4273
4318
  ...opts.skipSmoke ? [] : ["--smoke"],
4274
4319
  ...extra
4275
4320
  ],
@@ -7900,7 +7945,7 @@ function registerInit(program) {
7900
7945
  ).addOption(
7901
7946
  new Option2(
7902
7947
  "--protocols <faces>",
7903
- "Comma-separated public faces to expose; recorded in studio.toml [stack].protocols. Any non-empty combination of A2A, MCP, X402 (case-insensitive; default: A2A)."
7948
+ "Comma-separated public faces to expose; recorded in studio.toml [stack].protocols. Any non-empty combination of A2A, MCP, X402 (case-insensitive; default: A2A,X402)."
7904
7949
  )
7905
7950
  ).addOption(
7906
7951
  new Option2(
@@ -7910,7 +7955,7 @@ function registerInit(program) {
7910
7955
  ).addOption(
7911
7956
  new Option2(
7912
7957
  "--rails <rails>",
7913
- "Commerce rail(s) to scaffold: 8183 (default), b402, or both."
7958
+ "Commerce rail(s) to scaffold: 8183, b402, or both (default; Altana defaults to 8183)."
7914
7959
  ).choices(["8183", "b402", "both"])
7915
7960
  ).option(
7916
7961
  "--erc8183-price <base-units>",
@@ -8062,9 +8107,12 @@ async function cmdInitFlow(nameArg, opts) {
8062
8107
  printErr("error: pass either --protocols or --protocol, not both.");
8063
8108
  return 2;
8064
8109
  }
8110
+ const facesExplicit = opts.protocols !== void 0 || opts.protocol !== void 0;
8065
8111
  let faces;
8066
8112
  try {
8067
- faces = normalizeProtocolFaces(opts.protocols ?? opts.protocol ?? "A2A");
8113
+ faces = normalizeProtocolFaces(
8114
+ opts.protocols ?? opts.protocol ?? "A2A,X402"
8115
+ );
8068
8116
  if (opts.protocol !== void 0 && faces.length !== 1) {
8069
8117
  throw new Error("--protocol is a single-face alias; use --protocols");
8070
8118
  }
@@ -8100,7 +8148,13 @@ async function cmdInitFlow(nameArg, opts) {
8100
8148
  if (llmProvider === null) {
8101
8149
  return 2;
8102
8150
  }
8103
- let rails = await resolveRails(opts.rails, isTty);
8151
+ const inferredRails = opts.rails ?? (facesExplicit ? hasX402Face(faces) ? "both" : "8183" : walletKind2 === "altana" ? "8183" : void 0);
8152
+ let rails = await resolveRails(inferredRails, isTty);
8153
+ if (!facesExplicit) {
8154
+ faces = normalizeProtocolFaces(
8155
+ rails === "8183" ? ["A2A"] : ["A2A", "X402"]
8156
+ );
8157
+ }
8104
8158
  if (hasX402Face(faces) && rails === "8183") {
8105
8159
  rails = "both";
8106
8160
  } else if (hasX402Face(faces) && rails !== "both") {
@@ -8854,6 +8908,9 @@ function renderAzureSection(name, account, project) {
8854
8908
  [azure]
8855
8909
  # Hosted-Agents-supported region (eastus does NOT support Hosted Agents).
8856
8910
  location = "${DEFAULT_LOCATION}"
8911
+ # Optional Azure subscription id. Set it when the signed-in identity can access
8912
+ # more than one subscription so non-interactive deploy never guesses.
8913
+ subscription_id = ""
8857
8914
  # account_name MUST equal subdomain \u2014 the runtime derives the storage host
8858
8915
  # (https://{account_name}.services.ai.azure.com) from it; a mismatch is NXDOMAIN.
8859
8916
  account_name = "${azureName}"
@@ -9260,13 +9317,15 @@ async function resolveRails(flagValue, isTty) {
9260
9317
  if (flagValue === "8183" || flagValue === "b402" || flagValue === "both") {
9261
9318
  return flagValue;
9262
9319
  }
9263
- if (!isTty) return "8183";
9264
- const answer = (await promptUser("Commerce rails [8183/b402/both, Enter = 8183]: ")).trim().toLowerCase();
9265
- if (answer === "b402" || answer === "both") return answer;
9266
- if (answer !== "" && answer !== "8183") {
9267
- printErr(`hint: unknown commerce rail '${answer}' \u2014 using 8183.`);
9320
+ if (!isTty) return "both";
9321
+ const answer = (await promptUser("Commerce rails [8183/b402/both, Enter = both]: ")).trim().toLowerCase();
9322
+ if (answer === "8183" || answer === "b402" || answer === "both") {
9323
+ return answer;
9324
+ }
9325
+ if (answer !== "") {
9326
+ printErr(`hint: unknown commerce rail '${answer}' \u2014 using both.`);
9268
9327
  }
9269
- return "8183";
9328
+ return "both";
9270
9329
  }
9271
9330
  var DEFAULT_ERC8183_PRICE = "100000000000000000";
9272
9331
  async function resolveErc8183Price(flagValue, isTty) {
@@ -14390,6 +14449,7 @@ function utcStamp() {
14390
14449
  function buyerAccess(root) {
14391
14450
  const base = bnbPlatformApiUrl();
14392
14451
  const cfg = loadAgentCfg(root);
14452
+ const backend = platformCfg(root).backend === "azure" ? "azure" : "aws";
14393
14453
  const faces = stackFaces(tableOf12(cfg, "stack"), tableOf12(cfg, "payments"));
14394
14454
  const protocol = nativeProtocolOf(faces);
14395
14455
  const rawAgentId = platformCfg(root).agent_id;
@@ -14418,6 +14478,7 @@ function buyerAccess(root) {
14418
14478
  }
14419
14479
  return {
14420
14480
  base,
14481
+ backend,
14421
14482
  faces,
14422
14483
  protocol,
14423
14484
  agentId,
@@ -14838,7 +14899,6 @@ function printAgentClientPrompt(root, invokeUrl, status) {
14838
14899
  const base = access.base;
14839
14900
  const tokenUrl = access.tokenUrl;
14840
14901
  const deploymentId = String(platformCfg(root).deployment_id || "n/a");
14841
- const managedBackend = platformCfg(root).backend === "azure" ? "azure" : "aws";
14842
14902
  const selftestLine = "- Quick self-test (operator): run `bag deploy info --with-curl`";
14843
14903
  const rt = agentId ? `${base}/v1/rt/${agentId}` : `${base}/v1/rt/<agentId>`;
14844
14904
  const cardUrl = `${rt}/.well-known/agent-card.json`;
@@ -14918,7 +14978,7 @@ function printAgentClientPrompt(root, invokeUrl, status) {
14918
14978
  "- The anonymous x402 route does not use the OAuth2 token flow shown for ERC-8183."
14919
14979
  ],
14920
14980
  ...!x402Only && hasA2aFace(faces) ? [
14921
- managedBackend === "azure" ? '- A2A callers: Foundry incoming A2A is text-only. Send the payload as a JSON-string TEXT part \u2014 parts:[{"kind":"text","text":"{\\"skill\\":\\"negotiate\\",...}"}].' : '- A2A callers: send the payload as a DATA part, NOT text \u2014 parts:[{"kind":"data","data":{ ...payload above... }}]. A JSON string in a "text" part is rejected (the runtime only reads data parts, so no skill is parsed).'
14981
+ '- A2A callers: send the payload as a DATA part, NOT text \u2014 parts:[{"kind":"data","data":{ ...payload above... }}]. The managed gateway adapts this canonical buyer contract to the selected backend.'
14922
14982
  ] : [],
14923
14983
  "",
14924
14984
  "YOUR TASK",
@@ -15306,7 +15366,10 @@ function registerDeploy(program) {
15306
15366
  (opts) => cmdDestroy(opts)
15307
15367
  )
15308
15368
  );
15309
- p.command("logs").description("Show the selected deployment's logs via bnbagent-deploy.").option("--project-root <path>", "Override project root.").addOption(providerOption()).option("--since <dur>", "Lower bound, e.g. 5m/2h/1d (default 10m).", "10m").option("--follow", "Stream new lines (poll ~3s).").option("--limit <n>", "Number of recent lines (default 50).").option("--session <id>", "Container session id.").addOption(
15369
+ p.command("logs").description("Show the selected deployment's logs via bnbagent-deploy.").option("--project-root <path>", "Override project root.").addOption(providerOption()).option("--since <dur>", "Lower bound, e.g. 5m/2h/1d (default 10m).", "10m").option("--follow", "Stream new lines (poll ~3s).").option("--limit <n>", "Number of recent lines (default 50).").option(
15370
+ "--session <id>",
15371
+ "Managed Azure runtime session; capture x-agent-session-id from buyer response headers."
15372
+ ).addOption(
15310
15373
  new Option4(
15311
15374
  "--job <id>",
15312
15375
  "Deprecated Studio direct-CloudWatch filter."
@@ -16025,6 +16088,7 @@ async function cmdAgent(opts, agentcoreArgs) {
16025
16088
  rc = await deployAzureFoundry({
16026
16089
  projectRoot: root,
16027
16090
  extraArgs: stripLeadingDdash2(agentcoreArgs),
16091
+ onboard: Boolean(opts.yes),
16028
16092
  skipSmoke: opts.skipSmoke
16029
16093
  });
16030
16094
  if (rc !== 0) {
@@ -16697,12 +16761,24 @@ Quick-verify x402 endpoint:
16697
16761
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'`
16698
16762
  );
16699
16763
  } else {
16764
+ const captureAzureSession = access.backend === "azure";
16765
+ if (captureAzureSession) {
16766
+ printOut(" HDR=$(mktemp)");
16767
+ }
16700
16768
  printOut(
16701
- ` curl -X POST ${invokeUrl}/a2a \\
16769
+ ` curl ${captureAzureSession ? '-sS -D "$HDR" ' : ""}-X POST ${invokeUrl}/a2a \\
16702
16770
  -H "Authorization: Bearer $TOKEN" \\
16703
16771
  -H "Content-Type: application/json" \\
16704
16772
  -d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{"message":{"role":"user","messageId":"nego-1","parts":[{"kind":"data","data":{"skill":"negotiate","task_description":"Create a concise launch checklist","terms":{"deliverables":"A 5-item checklist","quality_standards":"Clear and actionable"}}}]}}}'`
16705
16773
  );
16774
+ if (captureAzureSession) {
16775
+ printOut(
16776
+ ` SESSION=$(awk 'tolower($1)=="x-agent-session-id:"{gsub(/\\r/,"",$2);print $2}' "$HDR")
16777
+ rm -f "$HDR"
16778
+ # Inspect this Azure buyer call's runtime logs when needed:
16779
+ bag deploy logs --provider bnb --session "$SESSION"`
16780
+ );
16781
+ }
16706
16782
  if (hasMcpFace(access.faces)) {
16707
16783
  printOut(
16708
16784
  ` # MCP is also published at ${invokeUrl}/mcp through the buffered platform gateway tunnel; initialize a streamable-HTTP session before tools/list.`
@@ -16742,6 +16818,12 @@ function azureX402CarrierBody() {
16742
16818
  function sameFaces(a, b) {
16743
16819
  return a.length === b.length && a.every((face, index) => face === b[index]);
16744
16820
  }
16821
+ function sameX402Snapshot(a, b) {
16822
+ if (a === null || a === void 0 || b === null || b === void 0) {
16823
+ return a === b;
16824
+ }
16825
+ return a.status === b.status && a.priceMode === b.priceMode && a.credentialsComplete === b.credentialsComplete;
16826
+ }
16745
16827
  function printAzureInfo(root, deployment, opts) {
16746
16828
  const endpoint = deployment.endpoint;
16747
16829
  if (!endpoint) {
@@ -16770,11 +16852,21 @@ function printAzureInfo(root, deployment, opts) {
16770
16852
  const currentFaces = agentFacesOf(agentRoot2);
16771
16853
  const faces = deployment.faces ?? currentFaces;
16772
16854
  const facesSource = deployment.faces ? "deployment-record" : "current-scaffold";
16773
- const configurationDrift = deployment.faces !== void 0 && !sameFaces(deployment.faces, currentFaces);
16855
+ const facesDrift = deployment.faces !== void 0 && !sameFaces(deployment.faces, currentFaces);
16774
16856
  const hasX402 = hasX402Face(faces);
16775
16857
  const hasA2a = hasA2aFace(faces);
16776
- const x402Summary = hasX402 ? x402DeploySummary(agentRoot2, "self", null) : "";
16777
- const x402Status = x402Summary.includes("ACTIVE in FREE mode") ? "free" : x402Summary.startsWith("x402 rail is ACTIVE") ? "active" : "dormant";
16858
+ const currentX402 = hasX402Face(currentFaces) ? x402DeploymentSnapshot(agentRoot2, "self") : null;
16859
+ const x402State = deployment.x402 ?? currentX402;
16860
+ const x402StateSource = deployment.x402 ? "deployment-record" : "current-scaffold";
16861
+ const x402Drift = deployment.x402 !== void 0 && !sameX402Snapshot(deployment.x402, currentX402);
16862
+ const configurationDrift = facesDrift || x402Drift;
16863
+ const x402Summary = hasX402 ? deployment.x402 ? x402DeploySummaryFromSnapshot(
16864
+ deployment.x402,
16865
+ "azure-foundry",
16866
+ "self",
16867
+ null
16868
+ ) : x402DeploySummary(agentRoot2, "self", null) : "";
16869
+ const x402Status = x402State?.status ?? (x402Summary.includes("ACTIVE in FREE mode") ? "free" : x402Summary.startsWith("x402 rail is ACTIVE") ? "active" : "dormant");
16778
16870
  const x402Body = hasX402 ? azureX402CarrierBody() : void 0;
16779
16871
  const body = hasA2a || x402Body === void 0 ? azureNegotiateQuickVerifyBody() : x402Body;
16780
16872
  const x402Info = hasX402 ? {
@@ -16784,6 +16876,7 @@ function printAzureInfo(root, deployment, opts) {
16784
16876
  carrier: "http-envelope-v1",
16785
16877
  gateway_guide: foundryX402GatewayGuideUrl(),
16786
16878
  summary: x402Summary || "x402 seller state is not available locally.",
16879
+ state_source: x402StateSource,
16787
16880
  ...x402Status === "dormant" ? {} : {
16788
16881
  request: {
16789
16882
  method: "POST",
@@ -16828,7 +16921,7 @@ function printAzureInfo(root, deployment, opts) {
16828
16921
  printOut(` deployed faces: ${faces.join(", ")} (${facesSource})`);
16829
16922
  if (configurationDrift) {
16830
16923
  printErr(
16831
- `warning: current scaffold faces (${currentFaces.join(", ")}) differ from the recorded deployment; redeploy before treating local config as live.`
16924
+ "warning: current scaffold/payment configuration differs from the recorded deployment; redeploy before treating local config as live."
16832
16925
  );
16833
16926
  }
16834
16927
  printOut(
@@ -686,8 +686,8 @@ function packageRoot() {
686
686
  }
687
687
  }
688
688
  function studioCliVersion() {
689
- if ("0.0.11-alpha.3") {
690
- return "0.0.11-alpha.3";
689
+ if ("0.0.11-alpha.5") {
690
+ return "0.0.11-alpha.5";
691
691
  }
692
692
  const file = path3.join(packageRoot(), "package.json");
693
693
  const pkg = JSON.parse(fs3.readFileSync(file, "utf-8"));
@@ -831,14 +831,47 @@ function loadDeployConfig(root) {
831
831
  return { agentRoot, cfg: {} };
832
832
  }
833
833
  }
834
- function x402DeploySummary(root, destination, publicUrl) {
834
+ function deploymentStatus(priceMode, credentialsComplete, runtime, destination) {
835
+ if (destination !== "platform" && !X402_CAPABLE_RUNTIMES.has(runtime)) {
836
+ return "dormant";
837
+ }
838
+ if (priceMode === "free") return "free";
839
+ if (priceMode === "paid" && credentialsComplete) return "active";
840
+ return "dormant";
841
+ }
842
+ function x402DeploymentSnapshot(root, destination) {
835
843
  const { agentRoot, cfg } = loadDeployConfig(root);
836
- if (!commerceRails(cfg).x402) return "";
844
+ if (!commerceRails(cfg).x402) return null;
837
845
  const seller = table3(table3(cfg.payments).x402_seller);
838
846
  const pricing = x402SellerPricingState(seller);
839
847
  const credentials = b402Credentials(agentRoot);
840
- const activation = `${B402_PAID_ONBOARDING_GUIDANCE} Then run the bnbagent-studio-selling-via-b402 skill, fill the four B402_* variables in .studio/.env.local, and redeploy.`;
848
+ const priceMode = pricing.kind;
841
849
  const runtime = String(table3(cfg.stack).runtime ?? "agentcore");
850
+ return {
851
+ status: deploymentStatus(
852
+ priceMode,
853
+ credentials.complete,
854
+ runtime,
855
+ destination
856
+ ),
857
+ priceMode,
858
+ credentialsComplete: credentials.complete
859
+ };
860
+ }
861
+ function x402DeploySummary(root, destination, publicUrl) {
862
+ const { cfg } = loadDeployConfig(root);
863
+ const snapshot = x402DeploymentSnapshot(root, destination);
864
+ if (snapshot === null) return "";
865
+ const runtime = String(table3(cfg.stack).runtime ?? "agentcore");
866
+ return x402DeploySummaryFromSnapshot(
867
+ snapshot,
868
+ runtime,
869
+ destination,
870
+ publicUrl
871
+ );
872
+ }
873
+ function x402DeploySummaryFromSnapshot(snapshot, runtime, destination, publicUrl) {
874
+ const activation = `${B402_PAID_ONBOARDING_GUIDANCE} Then run the bnbagent-studio-selling-via-b402 skill, fill the four B402_* variables in .studio/.env.local, and redeploy.`;
842
875
  if (destination !== "platform" && !X402_CAPABLE_RUNTIMES.has(runtime)) {
843
876
  return `x402 rail is FORCED DORMANT: the ${runtime} runtime has no x402 path. Deploy to AgentCore or Azure Foundry (managed platform or self-hosted) to activate the rail.`;
844
877
  }
@@ -846,10 +879,10 @@ function x402DeploySummary(root, destination, publicUrl) {
846
879
  const runtimeLabel = azure ? "Azure Foundry" : "AgentCore";
847
880
  const tunnelLine = azure ? 'The front wraps each request as envelope-v1 JSON, {"v":1,"method":"POST","path":"/x402","headers":{...},"body":"<base64>"}, inside an Entra-authenticated Foundry invocation (POST \u2026/agents/<name>/endpoint/protocols/invocations with an https://ai.azure.com bearer). Limits: 1 MiB request, 5 MiB response, no streaming.' : 'The front wraps each request as envelope-v1 JSON, {"v":1,"method":"POST","path":"/x402","headers":{...},"body":"<base64>"}, inside an authenticated AgentCore invocation. The default Bag self-deploy uses Cognito OAuth over HTTPS; IAM runtimes may use SDK/SigV4. Limits: 1 MiB request, 5 MiB response, no streaming.';
848
881
  const gatewayDocLine = azure ? `Gateway example: https://unpkg.com/@bnbagent/studio-cli@${studioCliVersion()}/skills/references/bnbagent-studio-use-azure-foundry.md#x402-external-gateway` : "Gateway example: https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/self-hosted-x402-gateway.md";
849
- if (pricing.kind === "invalid") {
882
+ if (snapshot.priceMode === "invalid") {
850
883
  return "x402 rail is DORMANT: price_usd is invalid; run `bag doctor`.";
851
884
  }
852
- if (pricing.kind === "free") {
885
+ if (snapshot.priceMode === "free") {
853
886
  if (destination !== "platform") {
854
887
  return [
855
888
  `x402 rail is ACTIVE in FREE mode (self-hosted ${runtimeLabel}).`,
@@ -867,7 +900,7 @@ function x402DeploySummary(root, destination, publicUrl) {
867
900
  "B402 verify/settle is bypassed; no credentials, token payment, or settlement audit is used."
868
901
  ].join("\n");
869
902
  }
870
- if (!credentials.complete) {
903
+ if (!snapshot.credentialsComplete) {
871
904
  return `x402 rail is DORMANT. To activate: ${activation}`;
872
905
  }
873
906
  const settlement = [
@@ -904,7 +937,7 @@ function isTable(value) {
904
937
  }
905
938
 
906
939
  // src/cli/_deploy/deployCli.ts
907
- var DEPLOY_CLI_VERSION = "0.5.10";
940
+ var DEPLOY_CLI_VERSION = "0.5.12";
908
941
  var DEPLOY_CLI_PACKAGE = `@bnbagent/deploy-cli@${DEPLOY_CLI_VERSION}`;
909
942
  var BNB_PLATFORM_API_URL = "https://bnbagent-api.bnbchain.world";
910
943
  var BNB_PLATFORM_API_URL_ENV = "BNBAGENT_API_URL";
@@ -936,7 +969,8 @@ var FOUNDRY_PASSTHROUGH_KEYS = /* @__PURE__ */ new Set([
936
969
  "project",
937
970
  "projectEndpoint",
938
971
  "protocol",
939
- "registry"
972
+ "registry",
973
+ "subscriptionId"
940
974
  ]);
941
975
  function tableOf(data, key) {
942
976
  const v = data[key];
@@ -1054,7 +1088,8 @@ function buildDeploySpec(root, opts) {
1054
1088
  ["account_name", "account"],
1055
1089
  ["project_name", "project"],
1056
1090
  ["project_endpoint", "projectEndpoint"],
1057
- ["location", "location"]
1091
+ ["location", "location"],
1092
+ ["subscription_id", "subscriptionId"]
1058
1093
  ]) {
1059
1094
  const value = String(azure[source] ?? "").trim();
1060
1095
  if (value) {
@@ -1261,7 +1296,10 @@ function trialFromDeployCliJson(data) {
1261
1296
  };
1262
1297
  }
1263
1298
  function bnbEnv() {
1264
- return { [BNB_PLATFORM_API_URL_ENV]: bnbPlatformApiUrl() };
1299
+ return {
1300
+ [BNB_PLATFORM_API_URL_ENV]: bnbPlatformApiUrl(),
1301
+ BNBAGENT_CLI_SURFACE: "studio"
1302
+ };
1265
1303
  }
1266
1304
  async function runPlatformAccountCommand(argv, opts = {}) {
1267
1305
  const run = async (args, cwd) => {
@@ -1333,7 +1371,9 @@ export {
1333
1371
  X402_CAPABLE_RUNTIMES,
1334
1372
  commerceRails,
1335
1373
  b402Credentials,
1374
+ x402DeploymentSnapshot,
1336
1375
  x402DeploySummary,
1376
+ x402DeploySummaryFromSnapshot,
1337
1377
  DEPLOY_CLI_VERSION,
1338
1378
  DEPLOY_CLI_PACKAGE,
1339
1379
  BNB_PLATFORM_API_URL,
@@ -18,7 +18,7 @@ import {
18
18
  runPlatformAccountCommand,
19
19
  trialFromDeployCliJson,
20
20
  withDeployFiles
21
- } from "./chunk-MIYN6U2D.js";
21
+ } from "./chunk-XY6EZGQF.js";
22
22
  import "./chunk-RO726HJG.js";
23
23
  export {
24
24
  BNB_PLATFORM_API_URL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bnbagent/studio-cli",
3
- "version": "0.0.11-alpha.3",
3
+ "version": "0.0.11-alpha.5",
4
4
  "description": "Skills-first toolkit and bag CLI for BNB Chain seller agents: ERC-8004 identity, ERC-8183 escrowed commerce, and x402 payments.",
5
5
  "keywords": [
6
6
  "bnb-chain",
@@ -54,7 +54,7 @@
54
54
  "tar": "^7.4.0",
55
55
  "viem": "^2.54.0",
56
56
  "yaml": "^2.9.0",
57
- "@bnbagent/studio-runtime": "0.0.11-alpha.3"
57
+ "@bnbagent/studio-runtime": "0.0.11-alpha.5"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@a2a-js/sdk": "^0.3.14",
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: bnbagent-studio
3
- description: The single entry point for bnbagent-studio - a TypeScript CLI (`bag`) for building a blockchain SELLER agent that earns $U on BNB Chain via ERC-8004 + ERC-8183 + x402 (Pieverse LLM inside). Load this skill whenever the user works in a bnbagent-studio / `bag` project, or wants to create/scaffold, deploy, run, debug, operate, or monetize such a seller agent (composable A2A, MCP, and X402 faces; BNB Chain trial or AWS AgentCore). All detailed playbooks ship as references/ files inside this skill - route via the decision tree in the body. When invoked with arguments, treat them as the user's intent and route the same way.
3
+ description: The single entry point for bnbagent-studio - a TypeScript CLI (`bag`) for building a blockchain SELLER agent that earns $U on BNB Chain via ERC-8004 + ERC-8183 + x402 (Pieverse LLM inside). Load this skill whenever the user works in a bnbagent-studio / `bag` project, or wants to create/scaffold, deploy, run, debug, operate, or monetize such a seller agent (composable A2A, MCP, and X402 faces; BNB Chain trial, AWS AgentCore, or Azure Foundry). All detailed playbooks ship as references/ files inside this skill - route via the decision tree in the body. When invoked with arguments, treat them as the user's intent and route the same way.
4
4
  ---
5
5
 
6
6
  # bnbagent-studio (the single entry point)
7
7
 
8
- `bnbagent-studio` (CLI: `bag`) wires the `@bnbagent/sdk` protocol layer (wallet / ERC-8004 / ERC-8183 / Pieverse LLM) into a TypeScript agent project, then deploys it as a **single blockchain seller runtime**. A2A, MCP, and X402 are composable public faces selected with `--protocols`; A2A is the default. `bag deploy` uses **scheme C**: every new deploy or redeploy explicitly selects BNB or AWS; a recorded deployment is used only to offer an explicit update action, never as a silent default. BNB is a 48h testnet trial and is disabled after expiry. AWS deploys into the user's own account. All cloud lifecycle mutations go through the pinned `@bnbagent/deploy-cli`; the optional AWS CLI is used only by the fail-open, read-only AgentCore quota check in `bag deploy prepare`. BNB/AWS share the agentcore scaffold. Treat an incompatible provider row as unavailable-do not force through it or mutate the scaffold during deploy.
8
+ `bnbagent-studio` (CLI: `bag`) wires the `@bnbagent/sdk` protocol layer (wallet / ERC-8004 / ERC-8183 / Pieverse LLM) into a TypeScript agent project, then deploys it as a **single blockchain seller runtime**. A2A, MCP, and X402 are composable public faces selected with `--protocols`; the default evm-local/twak scaffold serves A2A + X402 with both ERC-8183 and B402 rails, while Altana defaults to A2A + ERC-8183 because paid B402 is unsupported. `bag deploy` uses **scheme C**: every new deploy or redeploy explicitly selects BNB, AWS, or Azure; a recorded deployment is used only to offer an explicit update action, never as a silent default. BNB is a 48h testnet trial and is disabled after expiry. AWS and Azure self-deploy into the user's own account. All cloud lifecycle mutations go through the pinned `@bnbagent/deploy-cli`; the optional AWS CLI is used only by the fail-open, read-only AgentCore quota check in `bag deploy prepare`. AgentCore and Azure Foundry share the unified A2A/X402 entrypoint; Azure rejects MCP. Treat an incompatible provider row as unavailable-do not force through it or mutate the scaffold during deploy.
9
9
 
10
10
  Invoked as `/bnbagent-studio <ask>`? Treat `<ask>` as the user's intent and route it through the decision tree below, exactly like a natural-language ask.
11
11
 
@@ -24,7 +24,7 @@ One deployed runtime, one signer: a single valuable Agent serves the selected fa
24
24
  | Run / debug / dev / doctor / RPC / balance / incident triage | `references/bnbagent-studio-operating.md` |
25
25
  | Implement what the Agent sells, tune pricing, publish over A2A and/or MCP, defend disputes (seller flow) | `references/bnbagent-studio-selling-via-8183.md` |
26
26
  | Sell one paid or FREE HTTP request through the B402-backed x402 rail (pricing choice; paid merchant application, RSA key, credentials, IP allowlist, activation) | `references/bnbagent-studio-selling-via-b402.md` |
27
- | Deploy / redeploy / status / logs / destroy | Run `bag deploy` and explicitly choose a provider. Non-interactive deploy requires `--provider bnb\|aws --yes` (and `--allow-multiple` when keeping another provider active). Read `references/bnbagent-studio-use-bnb-trial.md` or `references/bnbagent-studio-use-aws-agentcore.md` for the selected provider. `bag deploy status` lists every recorded provider; multi-deployment logs/verify/destroy require `--provider`. |
27
+ | Deploy / redeploy / status / logs / destroy | Run `bag deploy` and explicitly choose a provider. Non-interactive deploy requires `--provider bnb\|aws\|azure --yes` (and `--allow-multiple` when keeping another provider active). Read `references/bnbagent-studio-use-bnb-trial.md`, `references/bnbagent-studio-use-aws-agentcore.md`, or `references/bnbagent-studio-use-azure-foundry.md` for the selected provider. `bag deploy status` lists every recorded provider; multi-deployment logs/verify/destroy require `--provider`. |
28
28
  | Wire chain-read tools into the Agent's LLM (AI SDK `tool()` wrappers, or any TS agent framework) | `references/bnbagent-studio-wiring-llm-tools.md` |
29
29
  | Buy a service from another ERC-8183 seller via CLI - incl. testing your own seller from the buyer side (v2/internal - NOT the v1 seller product flow) | `references/bnbagent-studio-buying-via-8183.md` |
30
30
  | Give the agent a PAID x402 capability - CMC market data / Binance Bazaar (B402) merchants / any pay-per-call API (`bag x402 trust`, x402-buyer recipe, 402 buyer errors) | `references/bnbagent-studio-buying-from-bazaar.md` |
@@ -53,7 +53,7 @@ Treat ERC-8183 amounts as decimal strings at CLI/config boundaries and `bigint`
53
53
 
54
54
  ## CLI groups at a glance
55
55
 
56
- `init`, `scan`, `recipe`, `skills`, `wallet`, `erc8004`, `erc8183`, `x402`, `agents`, `config`, `env`, `dev`, `doctor`, `audit`, `deploy`, `platform`, `llm`, `bundle`, `budget` - see `bag --help` for details. `bag deploy [--provider bnb\|aws] [--backend aws\|azure]` is the primary deploy command; `--backend` is valid only for provider `bnb` and confirms the recipe-derived managed backend. `prepare`, `verify`, `status`, `info`, `destroy`, `logs`, and `fix-gitignore` remain lifecycle subcommands (`deploy agent` is a deprecated compatibility alias). Provider deploy/status/logs/destroy and deploy-time credential validation are delegated to pinned `@bnbagent/deploy-cli@0.5.10`.
56
+ `init`, `scan`, `recipe`, `skills`, `wallet`, `erc8004`, `erc8183`, `x402`, `agents`, `config`, `env`, `dev`, `doctor`, `audit`, `deploy`, `platform`, `llm`, `bundle`, `budget` - see `bag --help` for details. `bag deploy [--provider bnb\|aws\|azure] [--backend aws\|azure]` is the primary deploy command; `--backend` is valid only for provider `bnb` and confirms the recipe-derived managed backend. `prepare`, `verify`, `status`, `info`, `destroy`, `logs`, and `fix-gitignore` remain lifecycle subcommands (`deploy agent` is a deprecated compatibility alias). Provider deploy/status/logs/destroy and deploy-time credential validation are delegated to pinned `@bnbagent/deploy-cli@0.5.12`.
57
57
 
58
58
  ## Tool surface
59
59
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bnbagent-studio-adding-to-project
3
- description: When the user wants to add bnbagent-studio's single ERC-8183 seller runtime (one valuable Agent on AWS Bedrock AgentCore that serves A2A by default or MCP optionally, holds the key, and signs in-process) to an existing TypeScript agent project.
3
+ description: When the user wants to add bnbagent-studio's single seller runtime (one valuable Agent on AWS Bedrock AgentCore that serves A2A + X402 with ERC-8183 + B402 by default, or another selected face/rail combination, holds the key, and signs in-process) to an existing TypeScript agent project.
4
4
  ---
5
5
 
6
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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bnbagent-studio-scaffolding-agent
3
- description: When the user wants to create a brand-new blockchain SELLER from zero - a single valuable Agent on AWS Bedrock AgentCore that serves A2A by default or MCP optionally, holds the key, and signs in-process - earning $U on BNB Chain via ERC-8004 + ERC-8183 + x402. Drives the full intake → todo-list → execute flow.
3
+ description: When the user wants to create a brand-new blockchain SELLER from zero - a single valuable Agent on AWS Bedrock AgentCore that serves A2A + X402 with ERC-8183 + B402 by default (or another selected face/rail combination), holds the key, and signs in-process. Drives the full intake → todo-list → execute flow.
4
4
  ---
5
5
 
6
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.
@@ -71,7 +71,7 @@ The fields (give the user all of them at once):
71
71
  | 3 | **LLM provider** | `pieverse-llm` / `openrouter` / `openai` / `anthropic` / `bedrock` | `pieverse-llm` |
72
72
  | 4 | **Wallet kind** (`--wallet-kind`) | `evm-local` (encrypted local keystore at the workspace root; `bag wallet new` creates it, `--private-key` imports an existing key; CodeZip deploy) / `twak` (**fully supported, opt in with `--wallet-kind twak`** - Trust Wallet Agent Kit CLI ≥0.20.0, self-custody encrypted mnemonic in a **project-dedicated** home `.studio/twak`, isolated from your main `~/.twak`; created manually with `HOME=<ws>/.studio/twak twak wallet create`, then `bag wallet new` adopts; container deploy. Reuse an existing wallet across agents with `--twak-home <path>`) / `altana` (bounded-session custody - admin keystore stays local, deploys ship ONLY the `ALTANA_SESSION` secret; zip deploy; not compatible with `pieverse-llm` or a paid b402 rail; flow: `references/bnbagent-studio-using-altana-wallet.md`) | `evm-local` |
73
73
  | 5 | **Storage** | `local` (file:// on disk, offline dev only, does **NOT** survive deploy) / `ipfs` (durable, public, deploy-ready; needs your pinning service's upload endpoint + write key as `STORAGE_API_URL` / `STORAGE_API_KEY` in `.studio/.env.local` **before the first real delivery** - see Step 6b) | `local` |
74
- | 6 | **Protocol faces** (`--protocols`) | any non-empty subset of `A2A`, `MCP`, `X402` | `A2A` |
74
+ | 6 | **Protocol faces** (`--protocols`) | any non-empty subset of `A2A`, `MCP`, `X402` | `A2A,X402` (`A2A` for Altana) |
75
75
  | 7 | **LLM model** | provider catalogue; for `pieverse-llm` the default `auto/free` runs at $0/token | `auto/free` |
76
76
  | 8 | **Auto-topup** | `enable` / `disable` - lets the Agent auto-pay $U from the wallet when LLM credits run low | deferred (non-interactive `bag init` records no `[budget]`; enable later with `bag budget enable`) |
77
77
  | 9 | **Scaffold destination** (`--destination`) | `self` (prepare the AgentCore scaffold for **your own** AWS account; runtime material stays under your cloud-account control) / `platform` (prepare for a 48h **testnet-only** trial on the BNB Chain managed platform - runs the _same_ agent in the **operator's** AWS, so a wallet key **leaves your control**; it hard-forces `[network].default = bsc-testnet`, pins runtime=`agentcore`, packages an artifact, and auth is GitHub device flow. Use a **throwaway** `bag wallet new`, never your main wallet). This is scaffold intent only; deploy still explicitly selects `--provider`. | `platform` while the trial campaign runs (bare init falls back to `self` once it ends, or when `--network bsc-mainnet` / a non-agentcore `--runtime` is passed) |
@@ -86,7 +86,7 @@ v1 is **seller-only** - there is no role to choose. `bag init` scaffolds the sin
86
86
  | --- | --- | --- |
87
87
  | **Agent stack** | AI SDK (`ai`) | The library the agent's brain is built with - the emitted `src/model.ts` factory returns an AI SDK `LanguageModel`, and `src/tools.ts` wraps the chain reads as AI SDK `tool()`s. (There is no `--framework` flag: the old framework axis folded into the runtime templates.) |
88
88
  | **Runtime** | `agentcore` | AWS Bedrock AgentCore - where the agent is hosted and served (`--runtime agentcore`). |
89
- | **Protocol faces** | selected above (`A2A` default; MCP/X402 composable) | A2A hosts agent card + JSON-RPC on `:9000`; MCP-only hosts `/mcp` on `:8000`; A2A+MCP uses A2A-native `dualMain.ts` on `:9000` and tunnels buffered MCP through the platform; X402 adds `/x402`, and X402-only suppresses protocol discovery. |
89
+ | **Protocol faces** | selected above (`A2A,X402` default for evm-local/twak; `A2A` for Altana; MCP composable) | A2A hosts agent card + JSON-RPC on `:9000`; MCP-only hosts `/mcp` on `:8000`; A2A+MCP uses A2A-native `dualMain.ts` on `:9000` and tunnels buffered MCP through the platform; X402 adds `/x402`, and X402-only suppresses protocol discovery. |
90
90
 
91
91
  **Not surfaced** (handled automatically, no need to show or ask):
92
92
 
@@ -138,7 +138,7 @@ Build a TodoWrite list. The shape depends on the `wallet kind`. The canonical 8-
138
138
 
139
139
  > **Onboarding note.** On a human TTY, `bag init` runs steps 3, 4 and 6 automatically (it prompts once for the wallet password, runs `bag wallet new`, zero-deposit-activates Pieverse, and prints faucet URLs). **You (Claude Code) drive `bag init` non-interactively**, so that auto-flow does NOT fire - keep steps 3/4/6 below. Pass `--no-onboard` to `bag init` to make this explicit and deterministic regardless of how the shell wires stdin.
140
140
 
141
- 1. `bag init <name> --llm-provider <p> --network <n> --storage-provider <s> --wallet-kind <k> --rails <8183|b402|both> [--erc8183-price <base-units>] [--b402-price <usd>] --no-onboard` - scaffold the current workspace. **`<name>` must start with a letter, use ASCII letters and digits only, and be at most 23 characters.** `bag init` rejects `-`, `_`, `.`, and overlong names instead of renaming them. Pass `--wallet-kind evm-local` (default) or `--wallet-kind twak` (twak is fully supported - pass the flag to opt in), and `--storage-provider local` (default) or `ipfs`, per the Stage-1 choices; for twak, add `--twak-home <path>` ONLY if the user wants to reuse an existing wallet (otherwise omit - a project-dedicated `.studio/twak` is the safe default). add `--protocols <comma-list>` when the user chose non-default or multiple faces (omit for A2A default; `--protocol <one>` is only a legacy alias), add `--model <m>` only if the user overrode the provider default, and `--enable-auto-topup` / `--no-auto-topup` only if they made an explicit choice (otherwise omit - consent stays deferred). Pass `--erc8183-price 0` only when the user explicitly chose FREE; omitting the flag preserves the paid 0.1 U default. The canonical stack supports FREE; if a custom deployment is selected, set all three `ERC8183_COMMERCE_ADDRESS`, `ERC8183_ROUTER_ADDRESS`, and `ERC8183_POLICY_ADDRESS` values from that same stack. For B402, pass `--b402-price 0` only after the user explicitly accepts an unrestricted anonymous FREE `/x402` endpoint. FREE bypasses B402 verify/settle and needs no merchant credentials; a positive price keeps the `$0.01` default and requires the paid onboarding playbook. **Destination:** while the trial campaign runs, bare `bag init` (no `--destination`) defaults to `platform` - so pass `--destination self` **explicitly** whenever the user chose their own AWS, otherwise studio.toml silently records `platform` and the confirmation block you echoed no longer matches what was written. Omit `--destination` only when the user actually wants the `platform` 48h testnet trial (the campaign default) - do NOT treat that default as a mistake or re-confirm it; it is the intended behavior while the campaign is open. (Bare init also resolves to `self` once the campaign ends, or when `--network bsc-mainnet` / a non-agentcore `--runtime` is passed.) On the `platform` path `bag init` hard-forces `bsc-testnet`, pins `--runtime agentcore` + packages an artifact (a zip for the default evm-local and altana wallets, a container for twak). For evm-local a wallet key will later leave your machine, so pair it with a throwaway `bag wallet new`; for altana only the bounded session ships - do NOT create a new wallet (full flow: `docs/guides/platform-deploy.md`). Defaults `--runtime agentcore` (the only advertised runtime; the Preview `azure-foundry` runtime remains explicitly selectable but is outside this playbook; there is no `--framework` flag because the AI SDK model/tools story is part of the runtime templates). Creates `<name>/` workspace root + `<name>/app/agent/` (the single sub-project: A2A emits `src/unifiedMain.ts` (the express + A2A entrypoint, one code set for both deploy clouds) + `src/sellerCore.ts` (the protocol-neutral core; executor inherits it) + `src/executor.ts` + `src/agentCard.ts`; MCP emits `src/mcpMain.ts`; both include `src/signing.ts` + `src/tools.ts` + `src/model.ts` + their own `studio.toml` + `package.json` + `tsconfig.json`) + `<name>/agentcore/` (`agentcore.json` + `aws-targets.json`, self-rendered - no agentcore CLI needed at init). The workspace root holds the `agentcore/` deploy descriptor, the `.studio/wallets/` keystore, a thin `package.json` + `pnpm-workspace.yaml`, README, and `.gitignore`. (v1 is seller-only - no `--role`.)
141
+ 1. `bag init <name> --llm-provider <p> --network <n> --storage-provider <s> --wallet-kind <k> [--protocols <comma-list>] [--rails <8183|b402|both>] [--erc8183-price <base-units>] [--b402-price <usd>] --no-onboard` - scaffold the current workspace. **`<name>` must start with a letter, use ASCII letters and digits only, and be at most 23 characters.** `bag init` rejects `-`, `_`, `.`, and overlong names instead of renaming them. Pass `--wallet-kind evm-local` (default) or `--wallet-kind twak` (twak is fully supported - pass the flag to opt in), and `--storage-provider local` (default) or `ipfs`, per the Stage-1 choices; for twak, add `--twak-home <path>` ONLY if the user wants to reuse an existing wallet (otherwise omit - a project-dedicated `.studio/twak` is the safe default). Omit `--protocols` and `--rails` for the default A2A + X402 faces with both ERC-8183 and B402 rails; Altana instead defaults to A2A + ERC-8183 because paid B402 is unsupported. Pass either flag when the user chose another face/rail combination (`--protocol <one>` is only a legacy alias), add `--model <m>` only if the user overrode the provider default, and `--enable-auto-topup` / `--no-auto-topup` only if they made an explicit choice (otherwise omit - consent stays deferred). Pass `--erc8183-price 0` only when the user explicitly chose FREE; omitting the flag preserves the paid 0.1 U default. The canonical stack supports FREE; if a custom deployment is selected, set all three `ERC8183_COMMERCE_ADDRESS`, `ERC8183_ROUTER_ADDRESS`, and `ERC8183_POLICY_ADDRESS` values from that same stack. For B402, pass `--b402-price 0` only after the user explicitly accepts an unrestricted anonymous FREE `/x402` endpoint. FREE bypasses B402 verify/settle and needs no merchant credentials; a positive price keeps the `$0.01` default and requires the paid onboarding playbook. **Destination:** while the trial campaign runs, bare `bag init` (no `--destination`) defaults to `platform` - so pass `--destination self` **explicitly** whenever the user chose their own AWS, otherwise studio.toml silently records `platform` and the confirmation block you echoed no longer matches what was written. Omit `--destination` only when the user actually wants the `platform` 48h testnet trial (the campaign default) - do NOT treat that default as a mistake or re-confirm it; it is the intended behavior while the campaign is open. (Bare init also resolves to `self` once the campaign ends, or when `--network bsc-mainnet` / a non-agentcore `--runtime` is passed.) On the `platform` path `bag init` hard-forces `bsc-testnet`, pins `--runtime agentcore` + packages an artifact (a zip for the default evm-local and altana wallets, a container for twak). For evm-local a wallet key will later leave your machine, so pair it with a throwaway `bag wallet new`; for altana only the bounded session ships - do NOT create a new wallet (full flow: `docs/guides/platform-deploy.md`). Defaults `--runtime agentcore` (the only advertised runtime; the Preview `azure-foundry` runtime remains explicitly selectable but is outside this playbook; there is no `--framework` flag because the AI SDK model/tools story is part of the runtime templates). Creates `<name>/` workspace root + `<name>/app/agent/` (the single sub-project: A2A emits `src/unifiedMain.ts` (the express + A2A entrypoint, one code set for both deploy clouds) + `src/sellerCore.ts` (the protocol-neutral core; executor inherits it) + `src/executor.ts` + `src/agentCard.ts`; MCP emits `src/mcpMain.ts`; both include `src/signing.ts` + `src/tools.ts` + `src/model.ts` + their own `studio.toml` + `package.json` + `tsconfig.json`) + `<name>/agentcore/` (`agentcore.json` + `aws-targets.json`, self-rendered - no agentcore CLI needed at init). The workspace root holds the `agentcore/` deploy descriptor, the `.studio/wallets/` keystore, a thin `package.json` + `pnpm-workspace.yaml`, README, and `.gitignore`. (v1 is seller-only - no `--role`.)
142
142
  > **Altana + custom contracts:** Altana sessions remain bound to the canonical ERC-8183 targets. Use `evm-local` for a custom Commerce/Router/Policy stack; doctor and deploy readiness reject this unsupported combination when the ERC-8183 rail is active.
143
143
 
144
144
  2. `cd <name>`, then make sure the dependencies are installed. `bag init` already runs the install by default (skip only if it was scaffolded with `--no-install`); the manual equivalent from the workspace root is:
@@ -7,7 +7,7 @@ description: When the user is acting as an ERC-8183 seller on the single selecte
7
7
 
8
8
  # bnbagent-studio-selling-via-8183
9
9
 
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).
10
+ Procedure for the **single seller flow**: implement the value your Agent produces, deploy it to AgentCore (where the default scaffold serves A2A + X402, while ERC-8183 remains available through A2A or an explicitly selected MCP face), 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).
11
11
 
12
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).
13
13
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bnbagent-studio-use-aws-agentcore
3
- description: When the user wants to deploy or operate a bnbagent-studio project on AWS Bedrock AgentCore - deploy with `bag deploy --provider aws` (all cloud lifecycle mutations are delegated to pinned `@bnbagent/deploy-cli@0.5.10`), inspect with `bag deploy status` / `logs --provider aws` / `verify --provider aws`, and tear down with `bag deploy destroy --provider aws --execute [--purge]`. Also covers AWS credential prerequisites, the optional read-only quota probe, and the runtime-secret channel.
3
+ description: When the user wants to deploy or operate a bnbagent-studio project on AWS Bedrock AgentCore - deploy with `bag deploy --provider aws` (all cloud lifecycle mutations are delegated to pinned `@bnbagent/deploy-cli@0.5.12`), inspect with `bag deploy status` / `logs --provider aws` / `verify --provider aws`, and tear down with `bag deploy destroy --provider aws --execute [--purge]`. Also covers AWS credential prerequisites, the optional read-only quota probe, and the runtime-secret channel.
4
4
  ---
5
5
 
6
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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bnbagent-studio-use-azure-foundry
3
- description: When the user wants to deploy or operate a bnbagent-studio project on Azure AI Foundry Hosted Agents - scaffold with `bag init --runtime azure-foundry`, deploy either to the managed platform with `bag deploy --provider bnb --backend azure` or directly with `bag deploy --provider azure`; all cloud lifecycle execution is delegated to pinned `@bnbagent/deploy-cli@0.5.10`. Native MCP is not supported on Azure; use AgentCore for MCP.
3
+ description: When the user wants to deploy or operate a bnbagent-studio project on Azure AI Foundry Hosted Agents - scaffold with `bag init --runtime azure-foundry`, deploy either to the managed platform with `bag deploy --provider bnb --backend azure` or directly with `bag deploy --provider azure`; all cloud lifecycle execution is delegated to pinned `@bnbagent/deploy-cli@0.5.12`. Native MCP is not supported on Azure; use AgentCore for MCP.
4
4
  ---
5
5
 
6
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.
@@ -16,7 +16,7 @@ Procedure for deploying and operating the seller Agent on **Azure AI Foundry Hos
16
16
  ```
17
17
  <workspace>/
18
18
  ├── app/agent/ # the deployed code (src/unifiedMain.ts host + Dockerfile here)
19
- │ ├── studio.toml # [azure] block: location / account_name / subdomain / project_name / agent_endpoint
19
+ │ ├── studio.toml # [azure] block: location / subscription_id / account_name / subdomain / project_name / agent_endpoint
20
20
  │ └── Dockerfile # the container image bnbagent-deploy builds + pushes
21
21
  └── .studio/ # secrets + wallets (workspace root - never in the image)
22
22
  ```
@@ -31,7 +31,7 @@ Procedure for deploying and operating the seller Agent on **Azure AI Foundry Hos
31
31
 
32
32
  1. **Bun 1.3+ (`bunx`) on PATH** - the pinned `@bnbagent/deploy-cli` runs through it.
33
33
  2. **Docker running** - the image is built locally (linux/amd64) before push.
34
- 3. **An Azure subscription** the operator may provision in (Foundry account/project, container registry, hosted agent). Before a local self-deploy, run `bunx --bun @bnbagent/deploy-cli@0.5.10 login --provider azure`; use OIDC/service-principal credentials in CI.
34
+ 3. **An Azure subscription** the operator may provision in (Foundry account/project, container registry, hosted agent). Before a local self-deploy, run `bunx --bun @bnbagent/deploy-cli@0.5.12 login --provider azure`; use OIDC/service-principal credentials in CI.
35
35
 
36
36
  ## ⚠️ Foundry gotchas (read before deploying)
37
37
 
@@ -49,7 +49,7 @@ Procedure for deploying and operating the seller Agent on **Azure AI Foundry Hos
49
49
 
50
50
  > The encrypted keystore (`.studio/wallets/`) stays at the workspace root and rides only that secret channel - never baked into the image.
51
51
 
52
- Provider-native overrides go in the optional `studio.toml [deploy.foundry]` table (verbatim deploy-spec keys; deploy-cli 0.5.10 consumes `account`, `cpu`, `location`, `memory`, `project`, `projectEndpoint`, `protocol`, `registry` and warns about anything else). The `[azure]` block's `account_name` / `project_name` / `project_endpoint` / `location` win over conflicting `[deploy.foundry]` keys.
52
+ Provider-native overrides go in the optional `studio.toml [deploy.foundry]` table (verbatim deploy-spec keys; deploy-cli 0.5.12 consumes `account`, `cpu`, `location`, `memory`, `project`, `projectEndpoint`, `protocol`, `registry`, `subscriptionId` and warns about anything else). The `[azure]` block's `subscription_id` / `account_name` / `project_name` / `project_endpoint` / `location` win over conflicting `[deploy.foundry]` keys.
53
53
 
54
54
  ## Typical workflow
55
55
 
@@ -74,6 +74,12 @@ bag deploy --provider azure # delegated: onboard → build+push
74
74
 
75
75
  `bag deploy --provider azure` runs an HTTP contract smoke by default (pass `--skip-smoke` to omit it) and captures the Foundry endpoint into `app/agent/studio.toml [azure].agent_endpoint`. If Foundry creates the resource but that post-create check fails, Studio still records the discovered endpoint so `status`, `logs`, and `destroy` can manage the resource; the deploy command continues to return non-zero.
76
76
 
77
+ For a first deploy in non-interactive automation, pass `--yes`. Studio treats
78
+ that as confirmation of the full deployment plan and delegates explicit
79
+ Foundry project onboarding. Configure `[azure].subscription_id` and
80
+ `account_name` when several candidates are accessible so no prompt or guess is
81
+ required.
82
+
77
83
  ### C. Validate / operate
78
84
 
79
85
  ```bash
@@ -133,6 +139,6 @@ Azure Foundry is an alternate runtime for the whole seller agent. There is no se
133
139
  ## Reference
134
140
 
135
141
  - `bag deploy --help` / `bag deploy <command> --help` (authoritative for commands + flags)
136
- - `app/agent/studio.toml [azure]` - location / account_name / subdomain / project_name / agent_endpoint
142
+ - `app/agent/studio.toml [azure]` - location / subscription_id / account_name / subdomain / project_name / agent_endpoint
137
143
  - `app/agent/studio.toml [deploy.foundry]` - provider-native deploy-spec passthrough
138
144
  - `BNBAGENT_DEPLOY_COMMAND` - override the pinned `bunx --bun @bnbagent/deploy-cli@<pin>` invocation (E2E/dev)
@@ -9,7 +9,7 @@ description: Use when deploying or operating a bnbagent-studio seller on the BNB
9
9
 
10
10
  Treat this provider as a temporary testnet sandbox. Require a throwaway wallet, keep `bsc-testnet`, and explain that the runtime signing material is transmitted to the operator's managed secret store for the trial. Never use a mainnet key. Exception: `wallet.kind='altana'` ships only the bounded, budget-limited, revocable session - the throwaway-wallet advice does not apply; tighten the session instead (`bag wallet session grant --force --budget-u <small> --expiry-days <short>`) and never run `bag wallet new` on an altana project (it breaks the session's `[wallet].address` anchor).
11
11
 
12
- All auth and cloud lifecycle work must cross the pinned `@bnbagent/deploy-cli@0.5.10` boundary. Do not call a cloud CLI or platform REST routes directly. The managed backend is recipe-derived: `agentcore` uses AWS; `azure-foundry` uses Azure. For headless managed Azure, confirm with `bag deploy --provider bnb --backend azure --yes`; never treat `--backend` as a cross-cloud recipe converter.
12
+ All auth and cloud lifecycle work must cross the pinned `@bnbagent/deploy-cli@0.5.12` boundary. Do not call a cloud CLI or platform REST routes directly. The managed backend is recipe-derived: `agentcore` uses AWS; `azure-foundry` uses Azure. For headless managed Azure, confirm with `bag deploy --provider bnb --backend azure --yes`; never treat `--backend` as a cross-cloud recipe converter.
13
13
 
14
14
  ## Select and authenticate
15
15