create-metamynd-agent 0.14.4 → 0.14.7
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/README.md +6 -3
- package/index.mjs +96 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -433,9 +433,12 @@ signed value only and ignores one in the context. Scaffolds pin `@metamynd/agent
|
|
|
433
433
|
|
|
434
434
|
The starter rules include a high-risk review. A request that sends **no** `riskLevel` (or an unrecognised one)
|
|
435
435
|
is no longer waved through: it is **escalated** (`CONTEXT_UNVERIFIABLE`) for a human, because an agent that omits
|
|
436
|
-
its risk is indistinguishable from one hiding it. The scaffolded
|
|
437
|
-
|
|
438
|
-
|
|
436
|
+
its risk is indistinguishable from one hiding it. The scaffolded examples pass the tool call's own `riskLevel`
|
|
437
|
+
through **unchanged** — there is no default, so a call that does not say is sent for review rather than treated as
|
|
438
|
+
`'low'` (the demo steps each state their risk explicitly). The neutral template passes your own `args` as the
|
|
439
|
+
context, so include it there. Either way `riskLevel` is **the agent's own claim**: it travels in the request
|
|
440
|
+
context, and even when the agent's key signs that context, the signature proves who said it, not that it is true —
|
|
441
|
+
nothing checks the value unless your owner configures provenance for it. A real integration should send an honest one — or, better, not depend on the agent at all: a mandate
|
|
439
442
|
permission can carry an owner-set `riskTier` that no claim can lower, and a gateway route can derive the risk
|
|
440
443
|
itself with `route.trustedContext` (`@metamynd/agentsafe-http-gateway` 0.10.0). See MAGP §6.3.
|
|
441
444
|
|
package/index.mjs
CHANGED
|
@@ -225,7 +225,8 @@ ${c.b('Options')}
|
|
|
225
225
|
--force, -f Scaffold into a non-empty directory, overwriting existing files
|
|
226
226
|
--api <url> API base (default ${DEFAULT_API})
|
|
227
227
|
--email <email> Owner login email
|
|
228
|
-
--password <pw> Owner password (prefer the interactive prompt or METAMYND_PASSWORD)
|
|
228
|
+
--password <pw> Owner password (prefer the interactive prompt or METAMYND_PASSWORD).
|
|
229
|
+
One session per account: logging in signs it out of the dashboard.
|
|
229
230
|
--name <name> Agent name (e.g. "Support Bot")
|
|
230
231
|
--scope <scope> Mandate action scope (e.g. flight-purchase)
|
|
231
232
|
--per-txn-max <n> Per-transaction cap (default 500)
|
|
@@ -374,6 +375,16 @@ function loadConfigFile(path) {
|
|
|
374
375
|
return json;
|
|
375
376
|
}
|
|
376
377
|
|
|
378
|
+
// Written into every financial scaffold's README. The generated code passes the tool call's riskLevel through
|
|
379
|
+
// unchanged (no `?? 'low'`): a missing one must reach the gate as missing, where it escalates by design.
|
|
380
|
+
const RISK_LEVEL_NOTE = `## Risk level: the agent's own claim
|
|
381
|
+
|
|
382
|
+
\`riskLevel\` is **the agent's own claim**. It travels in the request's context: the agent's key may sign that context,
|
|
383
|
+
which proves who said it, not that it is true, and nothing checks the value unless your owner configures provenance for it (an owner-set \`riskTier\` on the mandate permission, or a
|
|
384
|
+
gateway route's \`trustedContext\`). \`index.mjs\` passes the tool call's own \`riskLevel\` through unchanged —
|
|
385
|
+
there is **no default**. A call that does not state one (or states one the gate does not recognise) is **sent
|
|
386
|
+
for review** (\`CONTEXT_UNVERIFIABLE\`), never treated as \`low\`. The demo steps each state their risk explicitly.`;
|
|
387
|
+
|
|
377
388
|
// A rule needs `when.predicate` (the atom) and `then` (the decision the gate should return
|
|
378
389
|
// when it fires) — everything else is optional sugar. See backend's atom-catalog.ts for the
|
|
379
390
|
// full predicate list (amount-over, risk-at-or-above, jurisdiction-not-allowed, ...).
|
|
@@ -476,10 +487,27 @@ function defaultNeutralDemo() {
|
|
|
476
487
|
return demo;
|
|
477
488
|
}
|
|
478
489
|
|
|
490
|
+
/**
|
|
491
|
+
* Where an agent's rules are edited in the dashboard. SOPs belong to the legal entity, so the page is
|
|
492
|
+
* VeriFAI → Legal Entities (/dashboard/organization), SOPs tab; the AgentSafe sidebar group links the same
|
|
493
|
+
* tab as "SOPs". This said "Legal Entity → SOPs", a path no menu had (2026-10-02 eval, L-1).
|
|
494
|
+
*/
|
|
495
|
+
const SOPS_PATH = 'Dashboard → VeriFAI → Legal Entities → SOPs tab (also linked as AgentSafe → SOPs)';
|
|
496
|
+
/** The same path for the generated demo's console output, which stays ASCII. */
|
|
497
|
+
const SOPS_PATH_ASCII = 'Dashboard -> VeriFAI -> Legal Entities -> SOPs';
|
|
498
|
+
/**
|
|
499
|
+
* A --sandbox scaffold runs as the SHARED sandbox agent, which no user has dashboard access to, so "change
|
|
500
|
+
* the rules in the dashboard" sent them somewhere they could not go (L-7). Say how to get an agent whose
|
|
501
|
+
* rules they CAN change instead.
|
|
502
|
+
*/
|
|
503
|
+
const SANDBOX_RULES_FIXED = "This is the shared sandbox agent: its rules are fixed and nobody can edit them. To change the rules, provision your own agent — re-run without --sandbox (it signs you up and creates an agent whose SOPs you own, edited at " + SOPS_PATH + "), or use --harness for a free local agent whose rules you edit by hand.";
|
|
504
|
+
|
|
479
505
|
/** A --config file's rules cannot reach an agent the caller does not provision themselves: say so instead of implying they apply. */
|
|
480
|
-
function warnRulesNotApplied(fileConfig, where) {
|
|
506
|
+
function warnRulesNotApplied(fileConfig, where, { shared = false } = {}) {
|
|
481
507
|
if (policyMolecules(fileConfig).length === 0) return;
|
|
482
|
-
console.log(
|
|
508
|
+
console.log(shared
|
|
509
|
+
? ` ${c.yellow('!')} the rules in ${c.b('the config file')} are not applied to ${where} — its rules are the platform's defaults, and nobody can change them. Provision your own agent (drop this flag) to author them here.`
|
|
510
|
+
: ` ${c.yellow('!')} the rules in ${c.b('the config file')} are not applied to ${where} — its rules are the platform's defaults. Its owner sets them in the dashboard (${SOPS_PATH}), or provision your own agent (drop this flag) to author them here.`);
|
|
483
511
|
}
|
|
484
512
|
|
|
485
513
|
/**
|
|
@@ -1032,7 +1060,7 @@ function keepConfigAndFail(outDir, config, why) {
|
|
|
1032
1060
|
* it — the same shape of gap --harness's README documents. See exampleIndex() below, which is
|
|
1033
1061
|
* what the real (non-sandbox) flow scaffolds by default instead.
|
|
1034
1062
|
*/
|
|
1035
|
-
function exampleIndexNoGateway(scope, perTxnMax, currency, merchant) {
|
|
1063
|
+
function exampleIndexNoGateway(scope, perTxnMax, currency, merchant, sandbox = false) {
|
|
1036
1064
|
const under = Math.max(1, Math.round(perTxnMax * 0.5));
|
|
1037
1065
|
const over = Math.round(perTxnMax + 100);
|
|
1038
1066
|
return `// index.mjs — your agent, governed by MetaMynd/AgentSafe.
|
|
@@ -1061,7 +1089,10 @@ const gatedBookFlight = guard.guardTool(
|
|
|
1061
1089
|
amount: a.amount,
|
|
1062
1090
|
currency: '${currency}',
|
|
1063
1091
|
merchant: a.merchant,
|
|
1064
|
-
|
|
1092
|
+
// riskLevel is the agent's OWN claim: signing it proves who said it, not that it is true, and nothing checks it unless
|
|
1093
|
+
// the owner configures provenance. Passed through as-is: when the agent does not say, it stays absent and the gate sends
|
|
1094
|
+
// the action for review — never 'low'.
|
|
1095
|
+
context: { tool: 'book-flight', riskLevel: a.riskLevel },
|
|
1065
1096
|
}),
|
|
1066
1097
|
);
|
|
1067
1098
|
|
|
@@ -1176,8 +1207,12 @@ console.log(bold(' Without MetaMynd, you can be bypassed.') + ' bookFlight() ru
|
|
|
1176
1207
|
console.log(dim(' call it directly instead of gatedBookFlight and nothing above stops you.'));
|
|
1177
1208
|
console.log(dim(' Re-scaffold without --sandbox/--no-gateway for the default shape, which does.'));
|
|
1178
1209
|
console.log('');
|
|
1179
|
-
console.log('
|
|
1180
|
-
console.log(dim('
|
|
1210
|
+
${sandbox ? `console.log(' This is the SHARED sandbox agent: its rules are fixed and nobody can edit them.');
|
|
1211
|
+
console.log(dim(' To change the cap, provision your own agent: re-run create-metamynd-agent'));
|
|
1212
|
+
console.log(dim(' without --sandbox (it signs you up), then change the cap in your dashboard'));
|
|
1213
|
+
console.log(dim(' (${SOPS_PATH_ASCII}) and run again.'));
|
|
1214
|
+
console.log(dim(' The outcome changes. Your code does not. That is the point.'));` : `console.log(' Change the cap in the dashboard (${SOPS_PATH_ASCII}) and run again.');
|
|
1215
|
+
console.log(dim(' The outcome changes. This file does not. That is the point.'));`}
|
|
1181
1216
|
console.log('');
|
|
1182
1217
|
`;
|
|
1183
1218
|
}
|
|
@@ -1222,7 +1257,8 @@ async function bookFlightViaGateway(args, decision) {
|
|
|
1222
1257
|
amount: args.amount,
|
|
1223
1258
|
currency: args.currency ?? '${currency}',
|
|
1224
1259
|
merchant: args.merchant,
|
|
1225
|
-
|
|
1260
|
+
// Passed through as-is (never defaulted): a missing riskLevel must reach the gateway as missing.
|
|
1261
|
+
context: { tool: 'book-flight', riskLevel: args.riskLevel },
|
|
1226
1262
|
payload,
|
|
1227
1263
|
});
|
|
1228
1264
|
signed.authorizationId = decision?.authorizationId;
|
|
@@ -1250,7 +1286,10 @@ const gatedBookFlight = guard.guardTool(
|
|
|
1250
1286
|
amount: a.amount,
|
|
1251
1287
|
currency: a.currency ?? '${currency}',
|
|
1252
1288
|
merchant: a.merchant,
|
|
1253
|
-
|
|
1289
|
+
// riskLevel is the agent's OWN claim: signing it proves who said it, not that it is true, and nothing checks it unless
|
|
1290
|
+
// the owner configures provenance. Passed through as-is: when the agent does not say, it stays absent and the gate sends
|
|
1291
|
+
// the action for review — never 'low'.
|
|
1292
|
+
context: { tool: 'book-flight', riskLevel: a.riskLevel },
|
|
1254
1293
|
// The authorization is bound to the SAME body bookFlightViaGateway() sends, so the gate records what this agent
|
|
1255
1294
|
// signed and the gateway can prove it is running exactly that. Keep the two in step if you add a field.
|
|
1256
1295
|
payload: { amount: a.amount, merchant: a.merchant, currency: a.currency ?? '${currency}' },
|
|
@@ -1373,7 +1412,7 @@ console.log('');
|
|
|
1373
1412
|
console.log(bold(' With MetaMynd, you can\\'t be bypassed.') + ' ./gateway is why - it independently');
|
|
1374
1413
|
console.log(dim(' re-verified step 1 before running it, and holds the tool this file never can.'));
|
|
1375
1414
|
console.log('');
|
|
1376
|
-
console.log(' Change the cap in the dashboard (
|
|
1415
|
+
console.log(' Change the cap in the dashboard (${SOPS_PATH_ASCII}) and run again.');
|
|
1377
1416
|
console.log(dim(' The outcome changes. This file does not. That is the point.'));
|
|
1378
1417
|
console.log('');
|
|
1379
1418
|
`;
|
|
@@ -1406,7 +1445,7 @@ If a committed \`package-lock.json\` pins an older \`${GUARD_PKG}\` than this pr
|
|
|
1406
1445
|
* with `gatewayPort` the tool lives in a separate process (./gateway, the real enforcement
|
|
1407
1446
|
* boundary); without it (--no-gateway) the tool is a local function in this process.
|
|
1408
1447
|
*/
|
|
1409
|
-
function exampleIndexNeutral({ scope, gatewayPort, demo, merchant }) {
|
|
1448
|
+
function exampleIndexNeutral({ scope, gatewayPort, demo, merchant, sandbox = false }) {
|
|
1410
1449
|
const withGateway = gatewayPort != null;
|
|
1411
1450
|
const steps = [
|
|
1412
1451
|
...demo.cases,
|
|
@@ -1553,8 +1592,12 @@ console.log(bold(' Without MetaMynd, you can be bypassed.') + ' performAction()
|
|
|
1553
1592
|
console.log(dim(' call it directly instead of gatedAction and nothing above stops you.'));
|
|
1554
1593
|
console.log(dim(' Re-scaffold without --no-gateway for the default shape, which closes that.'));`}
|
|
1555
1594
|
console.log('');
|
|
1556
|
-
console.log('
|
|
1557
|
-
console.log(dim('
|
|
1595
|
+
${sandbox ? `console.log(' This is the SHARED sandbox agent: its rules are fixed and nobody can edit them.');
|
|
1596
|
+
console.log(dim(' To change them, provision your own agent: re-run create-metamynd-agent'));
|
|
1597
|
+
console.log(dim(' without --sandbox (it signs you up), then change its rules in your dashboard'));
|
|
1598
|
+
console.log(dim(' (${SOPS_PATH_ASCII}) and run again.'));
|
|
1599
|
+
console.log(dim(' The outcome changes. Your code does not. That is the point.'));` : `console.log(' Change your rules in the dashboard (${SOPS_PATH_ASCII}) and run again.');
|
|
1600
|
+
console.log(dim(' The outcome changes. This file does not. That is the point.'));`}
|
|
1558
1601
|
console.log('');
|
|
1559
1602
|
`;
|
|
1560
1603
|
}
|
|
@@ -1733,7 +1776,15 @@ Replace \`performAction()\` in \`server.mjs\` with your implementation and put a
|
|
|
1733
1776
|
}
|
|
1734
1777
|
|
|
1735
1778
|
/** The README for a non-financial hosted scaffold. `withGateway` selects the two-process shape. */
|
|
1736
|
-
|
|
1779
|
+
/** The generated README's "Change the rules" body: the dashboard path, or — for the shared sandbox agent — how to get an agent whose rules you can change. */
|
|
1780
|
+
function changeRulesSection(sandbox) {
|
|
1781
|
+
return sandbox
|
|
1782
|
+
? `${SANDBOX_RULES_FIXED} An \`escalate\` verdict is held for an owner to approve; poll \`guard.escalationStatus(id)\`.`
|
|
1783
|
+
: `Edit the agent's SOPs in the dashboard (${SOPS_PATH}). The agent's behaviour changes live —
|
|
1784
|
+
no redeploy. An \`escalate\` verdict is held for an owner to approve; poll \`guard.escalationStatus(id)\`.`;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
function exampleReadmeNeutral(slug, scope, withGateway, gatewayPort, daemonKey, demo, sandbox = false) {
|
|
1737
1788
|
const configLine = daemonKey
|
|
1738
1789
|
? `- \`agent.metamynd.json\` — your portable guard config (identity, mandate scope \`${scope}\`, issuer keys).
|
|
1739
1790
|
**Holds no secret key.** Signing goes through your already-running agentsafe-signer daemon instead.`
|
|
@@ -1812,8 +1863,7 @@ ${clonedFreshSection(daemonKey)}
|
|
|
1812
1863
|
|
|
1813
1864
|
## Change the rules
|
|
1814
1865
|
|
|
1815
|
-
|
|
1816
|
-
no redeploy. An \`escalate\` verdict is held for an owner to approve; poll \`guard.escalationStatus(id)\`.
|
|
1866
|
+
${changeRulesSection(sandbox)}
|
|
1817
1867
|
|
|
1818
1868
|
## What this is not
|
|
1819
1869
|
|
|
@@ -1850,7 +1900,7 @@ function examplePackageJson(slug, neutral = false) {
|
|
|
1850
1900
|
) + '\n';
|
|
1851
1901
|
}
|
|
1852
1902
|
|
|
1853
|
-
function exampleReadme(slug, scope, withGateway, gatewayPort, daemonKey = false) {
|
|
1903
|
+
function exampleReadme(slug, scope, withGateway, gatewayPort, daemonKey = false, sandbox = false) {
|
|
1854
1904
|
const configFileLine = daemonKey
|
|
1855
1905
|
? `- \`agent.metamynd.json\` — your portable guard config (identity, mandate scope \`${scope}\`, issuer keys).
|
|
1856
1906
|
**Holds no secret key.** Signing goes through your already-running agentsafe-signer daemon
|
|
@@ -1877,6 +1927,8 @@ You should see an ALLOW (fulfilled by \`./gateway\`), a BLOCK (over the per-tran
|
|
|
1877
1927
|
an ESCALATE (high risk). The BLOCK and ESCALATE never reach the gateway at all — this file's own
|
|
1878
1928
|
\`guard.guardTool()\` refuses them first. Only the ALLOW crosses into the other process.
|
|
1879
1929
|
|
|
1930
|
+
${RISK_LEVEL_NOTE}
|
|
1931
|
+
|
|
1880
1932
|
## Files
|
|
1881
1933
|
|
|
1882
1934
|
${configFileLine}
|
|
@@ -1898,6 +1950,8 @@ npm start
|
|
|
1898
1950
|
|
|
1899
1951
|
You should see an ALLOW, a BLOCK (over the per-transaction cap), and an ESCALATE (high risk).
|
|
1900
1952
|
|
|
1953
|
+
${RISK_LEVEL_NOTE}
|
|
1954
|
+
|
|
1901
1955
|
## Files
|
|
1902
1956
|
|
|
1903
1957
|
${configFileLine}
|
|
@@ -1940,8 +1994,7 @@ ${clonedFreshSection(daemonKey)}
|
|
|
1940
1994
|
|
|
1941
1995
|
## Change the rules
|
|
1942
1996
|
|
|
1943
|
-
|
|
1944
|
-
no redeploy. An \`escalate\` verdict is held for an owner to approve; poll \`guard.escalationStatus(id)\`.
|
|
1997
|
+
${changeRulesSection(sandbox)}
|
|
1945
1998
|
|
|
1946
1999
|
Full integration guide: \`docs/integration/INTEGRATE-WITH-METAMYND.md\`.
|
|
1947
2000
|
`;
|
|
@@ -2282,10 +2335,10 @@ function scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency = 'U
|
|
|
2282
2335
|
outDir,
|
|
2283
2336
|
'index.mjs',
|
|
2284
2337
|
neutral
|
|
2285
|
-
? exampleIndexNeutral({ scope, gatewayPort: withGateway ? gatewayPort : null, demo, merchant })
|
|
2338
|
+
? exampleIndexNeutral({ scope, gatewayPort: withGateway ? gatewayPort : null, demo, merchant, sandbox: !!sandbox })
|
|
2286
2339
|
: withGateway
|
|
2287
2340
|
? exampleIndex(scope, perTxnMax, gatewayPort, currency, paymentMerchant)
|
|
2288
|
-
: exampleIndexNoGateway(scope, perTxnMax, currency, paymentMerchant),
|
|
2341
|
+
: exampleIndexNoGateway(scope, perTxnMax, currency, paymentMerchant, !!sandbox),
|
|
2289
2342
|
force,
|
|
2290
2343
|
);
|
|
2291
2344
|
writeFileSafe(outDir, 'package.json', examplePackageJson(slug, neutral), force);
|
|
@@ -2294,8 +2347,8 @@ function scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency = 'U
|
|
|
2294
2347
|
outDir,
|
|
2295
2348
|
'README.md',
|
|
2296
2349
|
neutral
|
|
2297
|
-
? exampleReadmeNeutral(slug, scope, withGateway, gatewayPort, config.keyProvider === 'daemon', demo)
|
|
2298
|
-
: exampleReadme(slug, scope, withGateway, gatewayPort, config.keyProvider === 'daemon'),
|
|
2350
|
+
? exampleReadmeNeutral(slug, scope, withGateway, gatewayPort, config.keyProvider === 'daemon', demo, !!sandbox)
|
|
2351
|
+
: exampleReadme(slug, scope, withGateway, gatewayPort, config.keyProvider === 'daemon', !!sandbox),
|
|
2299
2352
|
force,
|
|
2300
2353
|
);
|
|
2301
2354
|
// `npm test` (agentsafe-guard verify --context) needs the request inputs of a compliant request:
|
|
@@ -2366,7 +2419,9 @@ function scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency = 'U
|
|
|
2366
2419
|
console.log(c.dim(' · BLOCK (the agent asking to raise its OWN limit)\n'));
|
|
2367
2420
|
}
|
|
2368
2421
|
console.log(c.cyan(` npm test`) + c.dim(' → assert it CANNOT exceed its mandate. Put this in CI.\n'));
|
|
2369
|
-
console.log(c.dim(
|
|
2422
|
+
console.log(c.dim(sandbox
|
|
2423
|
+
? ` ${SANDBOX_RULES_FIXED}\n`
|
|
2424
|
+
: ` Change the rules any time in the dashboard (${SOPS_PATH}) — no redeploy.\n`));
|
|
2370
2425
|
}
|
|
2371
2426
|
|
|
2372
2427
|
/** --sandbox: no login, no KYB — fetch the shared sandbox agent config and scaffold. */
|
|
@@ -2381,7 +2436,7 @@ async function runSandbox(args) {
|
|
|
2381
2436
|
const fileConfig = typeof args.config === 'string' ? loadConfigFile(args.config) : null;
|
|
2382
2437
|
if (fileConfig) console.log(` ${c.green('✓')} loaded policy config ${c.dim(args.config)}`);
|
|
2383
2438
|
const { financial } = announceFinancial(args, fileConfig);
|
|
2384
|
-
warnRulesNotApplied(fileConfig, 'the shared sandbox agent');
|
|
2439
|
+
warnRulesNotApplied(fileConfig, 'the shared sandbox agent', { shared: true });
|
|
2385
2440
|
if (!financial && typeof fileConfig?.scope === 'string' && fileConfig.scope !== 'perform-action') {
|
|
2386
2441
|
console.log(` ${c.yellow('!')} the scope "${fileConfig.scope}" in the config file is not used: the shared sandbox agent's scope is "perform-action".`);
|
|
2387
2442
|
}
|
|
@@ -3095,7 +3150,8 @@ async function callGateway(path, action, args) {
|
|
|
3095
3150
|
// The COMPLETE body the tool receives, signed as a payload (MAGP 8.3.9): the eight signed fields cover amount and merchant
|
|
3096
3151
|
// only, and this gateway refuses to run the tool on a body that is not exactly the one signed here.
|
|
3097
3152
|
const payload = { amount: args.amount, merchant: args.merchant, currency: args.currency ?? '${currency}' };
|
|
3098
|
-
|
|
3153
|
+
// riskLevel is passed through as-is (never defaulted): a missing one must reach the gateway as missing.
|
|
3154
|
+
const signed = await guard.buildSignedRequest({ action, amount: args.amount, currency: args.currency ?? '${currency}', merchant: args.merchant, context: { tool: '${scope}', riskLevel: args.riskLevel }, payload });
|
|
3099
3155
|
const res = await fetch(GATEWAY + path, { method: 'POST', headers: { 'content-type': 'application/json', 'x-magp-request': JSON.stringify(signed) }, body: JSON.stringify(payload) });
|
|
3100
3156
|
const body = await res.json().catch(() => null);
|
|
3101
3157
|
if (!res.ok) {
|
|
@@ -3120,7 +3176,10 @@ const gatedBookFlight = guard.guardToolLocal(
|
|
|
3120
3176
|
amount: a.amount,
|
|
3121
3177
|
currency: a.currency ?? '${currency}',
|
|
3122
3178
|
merchant: a.merchant,
|
|
3123
|
-
|
|
3179
|
+
// riskLevel is the agent's OWN claim: signing it proves who said it, not that it is true, and nothing checks it unless
|
|
3180
|
+
// the owner configures provenance. Passed through as-is: when the agent does not say, it stays absent and the gate sends
|
|
3181
|
+
// the action for review — never 'low'.
|
|
3182
|
+
context: { tool: 'book-flight', riskLevel: a.riskLevel },
|
|
3124
3183
|
}),
|
|
3125
3184
|
getBundle,
|
|
3126
3185
|
);
|
|
@@ -3474,7 +3533,9 @@ action outside the mandate entirely. Every step says what it expects and flags a
|
|
|
3474
3533
|
: `None of your rules could be staged in the demo (see below), so it shows only a BLOCK for an
|
|
3475
3534
|
action outside the mandate. Your rules are still enforced; see \`metamynd-rules.json\`.`)
|
|
3476
3535
|
: `You should see an ALLOW, a BLOCK (over the per-transaction cap), an ESCALATE (high risk —
|
|
3477
|
-
open the dashboard to approve it), and a BLOCK (an action outside the mandate entirely)
|
|
3536
|
+
open the dashboard to approve it), and a BLOCK (an action outside the mandate entirely).
|
|
3537
|
+
|
|
3538
|
+
${RISK_LEVEL_NOTE}`}
|
|
3478
3539
|
|
|
3479
3540
|
## Files
|
|
3480
3541
|
|
|
@@ -3704,9 +3765,15 @@ async function authFlow(args) {
|
|
|
3704
3765
|
const login = await apiPost(base, '/auth/login', { username: email, password }, null);
|
|
3705
3766
|
const token = login?.data?.accessToken;
|
|
3706
3767
|
if (!token) fail('Login succeeded but no access token was returned.');
|
|
3768
|
+
console.log(c.dim(` ${SESSION_REPLACED_NOTE}`));
|
|
3707
3769
|
return { base, token, email };
|
|
3708
3770
|
}
|
|
3709
3771
|
|
|
3772
|
+
// One session per account: a CLI login replaces the account's dashboard session (the dashboard then answers
|
|
3773
|
+
// SESSION_REPLACED and explains). Said up front so it is not a surprise (item 14 of the 2026-10-02 open items).
|
|
3774
|
+
const SESSION_REPLACED_NOTE =
|
|
3775
|
+
'Note: an account has one session at a time, so this login signs that account out of the MetaMynd dashboard in your browser. Sign in there again afterwards.';
|
|
3776
|
+
|
|
3710
3777
|
const REQUEST_STATE_FILE = 'metamynd-request.json';
|
|
3711
3778
|
|
|
3712
3779
|
// --request: a developer requests an agent for an owner's org (the owner approves in the dashboard).
|
|
@@ -3911,6 +3978,7 @@ async function main() {
|
|
|
3911
3978
|
const token = login?.data?.accessToken;
|
|
3912
3979
|
if (!token) { rl?.close(); fail('Login succeeded but no access token was returned.'); }
|
|
3913
3980
|
console.log(` ${c.green('✓')} authenticated as ${email}`);
|
|
3981
|
+
console.log(c.dim(` ${SESSION_REPLACED_NOTE}`));
|
|
3914
3982
|
|
|
3915
3983
|
// 2. Agent details — a --config file's fields are the default at every prompt/flag below.
|
|
3916
3984
|
const name = await pick('name', null, 'Agent name', fileConfig?.name ?? 'Support Bot');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-metamynd-agent",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.7",
|
|
4
4
|
"description": "Scaffold a MetaMynd/AgentSafe-governed AI agent in one command — logs in, provisions the agent (identity + mandate + SOP + Standards) in a single call, writes agent.metamynd.json plus a runnable agent + separate tool-gateway process that closes direct-call, confused-deputy, replay, and cumulative-spend bypasses. --harness scaffolds a free, local, zero-network governance harness instead.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|