@vectros-ai/cli 0.26.0 → 0.27.0

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/AUTHORING.md CHANGED
@@ -50,7 +50,7 @@ A name must be 2–50 chars: a lowercase letter, then lowercase letters / digits
50
50
  `validate` runs three layers and exits non-zero on any failure:
51
51
 
52
52
  1. **Structural** — the file parses against the blueprint schema (readable
53
- `path: message` errors, e.g. `schemas[0].fields[1].fieldType: Required`).
53
+ `path: message` errors, e.g. `schemas[0].fields[1].fieldType: Invalid input: expected string, received undefined`).
54
54
  2. **Scope + capability gates** — the requested `allowedActions` are data-plane
55
55
  only. This is the trust boundary: `keys`/`users`/`admin`/`app-contexts`/
56
56
  `namespaces` and the `*` wildcard are **hard-rejected, no override**.
@@ -175,9 +175,10 @@ vectros blueprint-test task-management --keep # leave the graph in pl
175
175
  Teardown is the default and runs even if an assertion fails. It is **created-only** — a pre-apply
176
176
  snapshot means it never deletes a schema or AccessProfile that already existed, so it's safe to point at
177
177
  a tenant other people use. (It does **not** delete the app-context: that's idempotent and reused.) Exit
178
- `0` = applied + every assertion passed; `1` = an assertion failed or apply errored; `2` = no credential,
179
- or the blueprint asked for control-plane scope (the same gate `validate` enforces). Run this before you
180
- ship a blueprint — it catches an unusable or mis-scoped credential that the offline checks can't.
178
+ `0` = applied + every assertion passed; `1` = an assertion failed, apply errored, or an agent the run created could not be retired or purged; `130`/`143` = stopped by SIGINT (^C) / SIGTERM; `2` = no credential,
179
+ or the blueprint asked for control-plane scope (the same gate `validate` enforces), or an agent name is too long
180
+ to take the run's suffix. Run this before you ship a blueprint — it catches an unusable or mis-scoped credential
181
+ that the offline checks can't. A blueprint that declares `agents:` runs under agent names of its own: see *Agents*.
181
182
 
182
183
  ## The format, field by field
183
184
 
@@ -230,7 +231,7 @@ accessProfile:
230
231
  # A SEPARATE gated dimension from allowedActions — named platform effects a
231
232
  # resource:ops verb can't express (e.g. creating/removing an identity in
232
233
  # your tenant). 'member-lifecycle' and 'delegate-principal-stamp' are
233
- # admitted today; every other name is hard-rejected, same posture as the
234
+ # admitted; every other name is hard-rejected, same posture as the
234
235
  # scope gate. See "Capabilities" below.
235
236
  #
236
237
  # Instead of allowedActions (+ optional dataScope/capabilities), accessProfile
@@ -575,10 +576,82 @@ Full field grammar, including the byte caps on `source` and
575
576
  `declaredInputContract` and the `manifest` verb vocabulary:
576
577
  [`@vectros-ai/blueprints`](https://www.npmjs.com/package/@vectros-ai/blueprints).
577
578
 
579
+ ### Agents — stored model definitions
580
+
581
+ A blueprint can declare the agents it needs. The block needs `formatVersion: 2`, so a CLI that predates the
582
+ format refuses the file instead of misreading it.
583
+
584
+ ```yaml
585
+ formatVersion: 2
586
+ agents:
587
+ intake-triage: # the key is the agent's name: 1-64 letters, digits, '_' and '-'
588
+ description: Summarises a new intake record and flags missing fields.
589
+ model: claude-sonnet-5-5
590
+ system: You triage intake records. Be concise.
591
+ tools:
592
+ - { name: records_get }
593
+ - { name: records_create, allowWrites: true } # a tool that changes data needs allowWrites ...
594
+ limits: { maxToolCalls: 10, maxWrites: 2 } # ... and limits.maxWrites of at least 1
595
+ budget: { maxInferenceCents: 100 }
596
+ ```
597
+
598
+ `apply` and `bootstrap` create each agent in the blueprint's context, after the roles, scripts and triggers and
599
+ before any key is minted, and `plan` lists one step per agent. The write is convergent, and the platform does the
600
+ comparing: a new name is created at version 1, an identical definition writes nothing, and a changed definition
601
+ becomes the next version. Nothing is edited in place, so every earlier version stays readable. The apply summary
602
+ names what it did to each agent (`created at version 1`, `unchanged at version 2`, `version 2 -> 3`, or `adopted`).
603
+
604
+ - **The applying credential needs `agents:c`**, and `agents:u` and `agents:r` as well whenever the agent already exists, even
605
+ when its definition is unchanged (the platform checks `u` before it compares, and without `r` it cannot show the existing agent
606
+ and answers that the name is in use). A re-apply with only `agents:c` is refused, and the error says which scopes are missing.
607
+ A principal without them gets a `403`, and the apply stops with an error that names the scope and the context.
608
+ Agents are written before the key, so a refused apply mints none. This is a grant on the credential that applies
609
+ the blueprint, not something to put in the blueprint's `accessProfile`: `agents` is a control-plane resource, so
610
+ the scope gate refuses it there.
611
+ - **Each agent is marked as this blueprint's.** Another blueprint's agent of the same name is refused, not rewritten, so two
612
+ blueprints cannot declare one name, and renaming a blueprint that already created agents strands them: the new name is
613
+ refused for them. The mark is set once and cannot change. It is the blueprint's own `name`, which the file declares
614
+ for itself (the same trust as for scripts and triggers): any file that declares `name: X` rewrites the agents marked
615
+ `X`, so the adoption flag below guards unmarked agents only.
616
+ - **An agent made by hand under the same name is refused unless you pass `--allow-agent-adoption`** (to `apply` or `bootstrap`; a
617
+ flag only the operator can give, never something the blueprint declares). Adopting marks it as this blueprint's and writes the
618
+ declared definition as its next version if that differs, so every run that uses the agent's latest version changes; earlier
619
+ versions stay readable. Nothing is written to a refused agent. Once adopted it is an ordinary managed agent and later applies
620
+ need no flag. This is how you bring agents you created by hand under a blueprint. It is checked per agent as the agents are
621
+ written, partway through the apply, so what an earlier agent or section already wrote stays.
622
+ - **Hand edits to a managed agent do not last.** A version written with `vectros agents version` (or the API) on an agent a
623
+ blueprint declares is replaced by the declared definition at the next apply, as another version. Change the blueprint.
624
+ - **A retired agent that the blueprint still declares fails the apply** (`409`), after the sections before it are written. Restore it
625
+ with `vectros agents version <id> --restore --file <definition>`, or remove the entry; a purged agent cannot be restored.
626
+ - **Removing an entry deletes nothing.** The agent stays stored and runnable. Retire it deliberately through the
627
+ API (`DELETE /v1/agents/{id}`); a retired agent keeps its name, so the same name cannot be created again.
628
+ - **`blueprint-test` runs a blueprint that declares agents, under names of their own.** A retired or purged agent keeps
629
+ its name for good, so the test applies a copy of your blueprint whose agent names carry a suffix unique to the run
630
+ (`triage` becomes `triage-t1a2b3c4d`; the report lists each), then retires and purges exactly the agents it created,
631
+ even when an assertion failed. Agents that exist under your declared names are never touched, and the file you wrote is
632
+ not changed. Because the suffix takes 10 characters, a name can be at most 54 characters long here (exit `2`, before any
633
+ write). The credential needs `agents:d` as well as the scopes an apply needs; if a retire is refused the agent stays active, the report names the API call that retires it, and the run exits
634
+ `1` (a teardown failure on any other resource is still reported without changing the exit code). **^C, SIGINT and SIGTERM.** Once the apply has begun, only the agent step has a stop point (a signal during context provisioning or the snapshot ends the run before the apply starts). After the first signal the run writes no further agents and skips
635
+ the assertions if they have not begun, but the rest of the apply still runs to its end (schemas, roles, the profile, the scoped-key mint,
636
+ seed records, the index poll), so a request in progress or a long seed delays the stop. Then the same teardown as after a failed run
637
+ removes what the apply's result lists (never the context, the service principal or namespaces), the report is printed, and the exit
638
+ code is `130` (SIGINT) or `143` (SIGTERM); a run stopped this way never passes, and these codes win over `1` (the report still names
639
+ an agent that could not be removed). A step that never answers holds the run until you send the signal again. That second signal starts no
640
+ teardown: it prints the id of each agent this run created with the calls that retire and erase it, names a create that was sent and never
641
+ answered, notes that other things the run wrote are not listed, and leaves at once. With `--keep` nothing is torn down. A process manager that
642
+ follows SIGTERM with SIGKILL after a grace period ends the process wherever it is, and SIGKILL cannot be handled: what was written so far
643
+ stays. A create of a tracked agent is sent with no client retries, so a single 429 or 5xx fails that create (the run reports it and tears
644
+ down) instead of being retried; a create that may have gone through is searched for by name. Each run leaves one purged row per declared agent (the name stays reserved), which
645
+ `agents list --include-retired` shows. With `--keep` the agents stay, under their run names.
646
+ - `authority` is `CALLER` (the default and the only value the platform accepts): a run calls tools with the identity
647
+ and permissions of whoever starts it, further limited by the tool whitelist.
648
+
649
+ The same API is available directly as `vectros agents list|get|create|version`; see the README.
650
+
578
651
  ### The scope gate — what you can and can't request
579
652
 
580
653
  The gate allows only **data-plane** resources:
581
- `records`, `schemas`, `search`, `documents`, `folders`, `inference`, `entities`
654
+ `records`, `schemas`, `search`, `documents`, `folders`, `inference`, `entities`, `runs`
582
655
  (per-namespace identity-entity CRUD — `org`/`client`/any namespace you
583
656
  registered — ownership-gated the same way as `records`; it grants no
584
657
  authority over the namespace *registry* itself, which stays root-key-only).
@@ -618,7 +691,7 @@ An `accessProfile` or role clause may also declare `capabilities: [...]` —
618
691
  named platform effects (like creating or removing an identity in your tenant)
619
692
  that a `resource:ops` scope token can't express. This rides its own field,
620
693
  separate from `allowedActions`, and has its own allowlist: **`member-lifecycle`
621
- and `delegate-principal-stamp` are admitted today.** Every other capability
694
+ and `delegate-principal-stamp` are admitted.** Every other capability
622
695
  name — including ones the platform's own registry recognizes — is refused,
623
696
  the same fail-closed, deliberately-narrow posture as the scope gate above. `validate`,
624
697
  `plan`, `blueprint-test` and `bootstrap` all report a rejected capability the
@@ -706,6 +779,11 @@ stays, because there is no second, principal-shaped factor to safely gate a
706
779
  DELETE the way a trigger row's provenance marker does. Remove one deliberately
707
780
  with `vectros scripts delete`.
708
781
 
782
+ **A FOURTH qualification, and here the platform does the comparing: an `agents:` entry is idempotent server-side,
783
+ and a change adds a version.** For an agent that exists, the loader first makes a plain create call to see the agent's mark and
784
+ version, then an upsert, which compares the declared definition with the stored latest (after defaults are filled in) and writes
785
+ nothing when they are identical. The two versions give the exact outcome. See *Agents*, including `--allow-agent-adoption`.
786
+
709
787
  ## Distribution
710
788
 
711
789
  - **Bundled** — reviewed, versioned blueprints shipped in the library
package/CHANGELOG.md CHANGED
@@ -3,6 +3,44 @@
3
3
  All notable changes to `@vectros-ai/cli` are documented here.
4
4
  This project adheres to [Semantic Versioning](https://semver.org).
5
5
 
6
+ ## 0.27.0 — 2026-11-07
7
+
8
+ ### Added
9
+
10
+ - **`vectros blueprint apply` and `bootstrap` create the agents of a blueprint's `agents` section** (it needs `formatVersion: 2`), after the
11
+ roles, scripts and triggers and before any key is minted. `blueprint plan` lists one step per agent (model, tools, limits, budget,
12
+ prompt size). A new name is created at version 1, an unchanged definition writes nothing, a changed one becomes a new version; the
13
+ summary says which (`created at version 1`, `unchanged at version 2`, `version 2 -> 3`).
14
+ - **Agents are marked as the blueprint's own.** Another blueprint's agent of the same name is refused, and an agent made by hand is
15
+ refused unless you pass `--allow-agent-adoption` (adopting it writes the declared definition as a new version, which changes every
16
+ run that uses the latest version). Removing an entry from the blueprint deletes nothing.
17
+ - **Scopes:** the applying credential needs `agents:c`, and `agents:u` and `agents:r` as well when the agent already exists, even if
18
+ its definition is unchanged. On a `403` the apply stops, names the agent, scope and context, and mints no key.
19
+ - **`vectros agents list|get|create|version`.** `--context` is required and `--tenant test|live` is accepted. `create` takes a name
20
+ (1 to 64 letters, digits, `_` or `-`) and a JSON or YAML definition file. `version` takes the agent's id and a file, writes a new
21
+ version as a full replacement, and takes `--expected-version` (refuse the write if someone else got there first) and `--restore`
22
+ (bring a retired agent back). `list` takes `--include-retired`; `get` takes the id and `--at-version`. There is no `delete` verb:
23
+ retire an agent through the API.
24
+ - **A blueprint can grant `runs:c` and `runs:r`.** A trigger cannot be granted `runs`, directly or through a role.
25
+ - **`blueprint validate` and `plan` warn about a schema field named `externalId`, `partnerUserId`, `scopes` or `userId`** (the platform
26
+ reserves them; exit `0`); a lookup field with one of those names is an error (exit `2`).
27
+ - **A blueprint's names, labels and descriptions with more invisible characters are refused.**
28
+
29
+ ### Changed
30
+
31
+ - **`vectros --version` reports SDK 0.49.0.**
32
+ - **`apply` and `bootstrap` ask before reusing a trigger's service principal that this blueprint did not mark:** a prompt, or
33
+ `--confirm-existing-principal` in a pipeline (exit `3` without it, before anything is written). Principals from earlier releases
34
+ carry no mark, so the first re-apply of a blueprint with triggers needs the confirmation once per trigger; marking needs `users:u`.
35
+ - **`vectros blueprint-test` runs a blueprint with agents.** Agent names get a per-run suffix (a declared name over 54 characters exits
36
+ `2`), the test retires and purges only the agents it created, and the credential needs `agents:d`. `^C` or SIGTERM during the run
37
+ tears down what the apply listed and exits `130` or `143`. Each run leaves one purged row per agent, and `--keep` leaves the agents.
38
+ - **Text from blueprint files, agent definitions and the platform reaches the terminal without control, invisible or bidirectional
39
+ characters,** cut at 200 lines or 20,000 characters (`[truncated]`). YAML parser warnings are no longer printed.
40
+ - **Blueprint validation runs on zod 4.** An integer beyond JavaScript's safe-integer range and `Infinity` are refused, a string length
41
+ counts characters, and a wrong-typed value stops the checks that depend on it. zod's own messages are reworded (a missing field reads
42
+ `Invalid input: expected string, received undefined`): match on the field path, not on the text.
43
+
6
44
  ## 0.26.0 — 2026-10-25
7
45
 
8
46
  ### Added
package/README.md CHANGED
@@ -20,6 +20,7 @@ The Vectros provisioning CLI — the `vectros` binary:
20
20
  - **`vectros role`** — define reusable, context-scoped access rules.
21
21
  - **`vectros scripts`** — push, list, inspect, and delete the versioned script source a trigger
22
22
  fires, or your own app executes directly.
23
+ - **`vectros agents`** — list, inspect, create, and version stored agents (a model, a system prompt, and a tool whitelist).
23
24
  - **`vectros assume`** — switch identity namespace values on your own token, per a role's `assumable` grant.
24
25
  - **`vectros access`** — bind principals to contexts, and inspect what a binding grants.
25
26
  - **`vectros key`** — issue, list, revoke, and rotate scoped API keys (`ssk_*`).
@@ -78,7 +79,8 @@ On a machine with no local record of a prior mint (e.g. an ephemeral CI
78
79
  container re-running `--yes` for the first time) against a blueprint whose
79
80
  service principal already exists in the tenant, `--yes` alone isn't enough —
80
81
  add `--confirm-existing-principal` to make that expected case explicit and
81
- non-interactive; see AUTHORING.md's "idempotency contract" for why. For a CI re-apply that has no use for the
82
+ non-interactive; see AUTHORING.md's "idempotency contract" for why. The same flag covers a trigger's service principal
83
+ that already exists without this blueprint's mark (see the `apply` section below). For a CI re-apply that has no use for the
82
84
  key, `vectros blueprint apply` (below) is the better fit.
83
85
 
84
86
  **An issuer that needs verification.** A blueprint's `issuers` entry registered without `restrictedToDomain` starts
@@ -142,7 +144,7 @@ vectros blueprint apply ./my-thing.blueprint.yaml --tenant live --yes --confirm-
142
144
 
143
145
  `apply` runs the same pipeline as `vectros bootstrap` (the same credential, the same scope and capability gates,
144
146
  the same loader) with the key step switched off: the context, its service principal and access profile, schemas,
145
- roles, issuers, triggers and scripts are created or reconciled (and, only if you pass `--seed`, the blueprint's sample
147
+ roles, issuers, triggers, scripts and agents are created or reconciled (and, only if you pass `--seed`, the blueprint's sample
146
148
  seed records are written), but **no scoped key is minted,
147
149
  nothing is written to a keyring, and no MCP client config is touched**. (Short-lived bootstrap tokens are minted
148
150
  to call the platform, as with `bootstrap`; none is a scoped key.) That is what makes it fit for re-applying
@@ -166,11 +168,18 @@ run. Use `bootstrap` when you also want the credential.
166
168
  place, as `bootstrap` does.)
167
169
  - **An existing service principal needs `--confirm-existing-principal`** (with `--yes`, or with no terminal),
168
170
  which is every apply once the principal exists, on any machine: `apply` never reads a local key record, so a
169
- machine that ran `bootstrap` is not exempt. It lets `apply` rewrite that principal's access profile, and covers the
170
- blueprint's own service principal only (the principals a blueprint's triggers use are ensured without this check,
171
- as with `bootstrap`). In a pipeline this flag is standing consent: it also waves through a blueprint whose
172
- `servicePrincipal.externalId` collides with an unrelated identity, so keep the blueprint's source reviewed. Every
173
- run that proceeds prints which principal it reused (id, external id, created time) and why.
171
+ machine that ran `bootstrap` is not exempt. It lets `apply` rewrite that principal's access profile. The same flag
172
+ covers a trigger's service principal that already exists and that this blueprint did not mark. A principal created
173
+ for a trigger is marked with the blueprint's name (a `provisionedBy` key on the principal), so the confirmation
174
+ is asked only for one that has no mark (an earlier release made it, or someone made it by hand) or carries another
175
+ blueprint's: the first confirmation marks it as this blueprint's (an overwrite that needs the `users:u` scope in the
176
+ blueprint's context and is skipped when the principal's payload reads back masked; if the run does not write it, it says
177
+ why and the next run asks again), and with no
178
+ terminal and no flag the run stops before it writes a schema, role, profile, trigger, key or seed record. The mark is advisory, a guard against
179
+ an accidental name collision or a pre-created principal; it does not stop someone who can create principals and
180
+ copies the format. In a pipeline this flag is standing consent: it also waves through a blueprint whose
181
+ `servicePrincipal.externalId` or trigger name collides with an unrelated identity, so keep the blueprint's source
182
+ reviewed. Every run that proceeds prints which principal it reused (id, external id, created time) and why.
174
183
  - **Sample seed records are opt-in: `apply` writes none unless you pass `--seed`,** in either tenant, and never asks.
175
184
  This is the opposite of `bootstrap` (which seeds unless `--no-seed`) on purpose: a blueprint's seeds are
176
185
  illustrative, not real data, and a re-apply from a pipeline must not write them by omission. When the blueprint
@@ -186,13 +195,13 @@ run. Use `bootstrap` when you also want the credential.
186
195
  but `--require-verified-issuers` was given and an issuer is pending verification.
187
196
 
188
197
  Flags it shares with `bootstrap` (`--set`, `--values`, `--allow-tenant-wide-namespaces`,
189
- `--allow-script-adoption`, `--require-verified-issuers`, `--token`, `--base-url`) behave the same. `--tenant`,
198
+ `--allow-script-adoption`, `--allow-agent-adoption`, `--require-verified-issuers`, `--token`, `--base-url`) behave the same. `--tenant`,
190
199
  `--yes` and `--confirm-existing-principal` are shared but behave as described above (`--tenant` is required here,
191
200
  `--yes` is required without a terminal, and the principal flag applies to every re-apply). The flags that concern a
192
201
  key or your MCP client (`--rotate`, `--client`, `--no-merge`, `--activate`, `--no-activate`, `--use-scoped-token`,
193
202
  `--test`) belong to `bootstrap` and are refused with a pointer; the blueprint is an argument, not `--blueprint`, and
194
- there is no `--blank`. A script pushed onto an existing hand-authored name (`--allow-script-adoption`) is checked
195
- when the scripts are pushed, partway through, not up front. `vectros blueprint apply --help` lists everything.
203
+ there is no `--blank`. A script pushed onto an existing hand-authored name (`--allow-script-adoption`) and an agent
204
+ that exists with no blueprint mark (`--allow-agent-adoption`) are checked when they are written, partway through, not up front. `vectros blueprint apply --help` lists everything.
196
205
 
197
206
  ## `vectros blueprint-test` — verify it actually provisions (creds-required)
198
207
 
@@ -213,9 +222,16 @@ vectros blueprint-test task-management --keep
213
222
  ```
214
223
 
215
224
  Exit `0` = applied and every assertion passed; `1` = an assertion failed, apply
216
- errored, or the blueprint could not be read; `2` = no credential, or the scope gate or the capability gate refused the blueprint.
225
+ errored, the blueprint could not be read, or an agent the run created could not be retired or purged (the one teardown failure that changes the result); `130` = stopped by SIGINT (^C) and `143` = by SIGTERM, after the rest of the apply finishes (no further agents are written; a key mint and seed records still run) and the teardown it still runs (a second signal leaves at once and names the agents that may still be active); `2` = no credential, or the scope gate or the capability gate refused the blueprint,
226
+ or an agent name is too long to take the run's suffix.
217
227
  The app-context is intentionally **not** deleted (it's idempotent and reused).
218
228
 
229
+ A blueprint that declares `agents` (see [`vectros agents`](#vectros-agents--stored-versioned-agent-definitions)) runs too. Because a retired or purged agent keeps its name for good, the
230
+ test applies a copy of your blueprint whose agent names carry a suffix unique to the run (`triage` runs as `triage-t1a2b3c4d`; the report
231
+ lists each), then retires and purges exactly the agents it created, even when an assertion failed. Agents that exist under your declared names
232
+ are never touched. A name can be at most 54 characters long here, and the credential needs `agents:d` as well as the scopes an apply needs.
233
+ Each run leaves one purged row per declared agent behind, because a name stays reserved; `vectros agents list --include-retired` shows them.
234
+
219
235
  ## `vectros context` — app contexts
220
236
 
221
237
  A context is the namespace all data (records, documents, schemas, roles, access
@@ -323,9 +339,10 @@ be printable ASCII, at most 4096 characters. A tenant holds at most 25 provider
323
339
 
324
340
  The CLI does not sign the risk waiver: an account owner signs it in the developer portal, under **Model
325
341
  Providers**, for each environment (live or test). A config is usable only while that waiver is in force for
326
- your account. It is not in force when it is neither signed nor granted to your account, when it was signed
327
- against a text that has since changed, or when it has been revoked. A waiver that Vectros granted to your tenant,
328
- for which your tenant has no signed acceptance, is not affected by any of these. The portal shows which of these
342
+ your account. It is not in force when it is neither signed nor granted to your account, when it has been revoked,
343
+ or when Vectros has required a newer version than the one your owner signed (a waiver Vectros granted to your tenant
344
+ without a signature ends then too). A new published version of the waiver changes nothing by itself: the version your owner signed stays in force
345
+ until Vectros requires a newer one, and account owners are told in advance of the date. The portal shows which of these
329
346
  applies. An account that has accepted the Business Associate Agreement with Vectros in the developer portal needs one more thing before a call can
330
347
  use a config: an account owner attests that config in the developer portal (Model Providers). Until then the
331
348
  platform refuses the call with a `403` that says it needs a BAA-holder attestation. The CLI does not attest
@@ -508,6 +525,42 @@ A blueprint can ship a script instead of pushing one — see `scripts:` in
508
525
  convergent (an unchanged source pushes nothing) and never deletes: removing a `scripts:` entry
509
526
  leaves every version in place, which is why this command group exists to remove one deliberately.
510
527
 
528
+ ## `vectros agents` — stored, versioned agent definitions
529
+
530
+ A stored agent is a named definition of a model, a system prompt, a tool whitelist, per-run limits and a
531
+ spending cap, kept in an app context. Every change writes a new immutable version and the agent always
532
+ points at its newest one; nothing is edited in place. These verbs and a blueprint's `agents:` section
533
+ write through the same API, so use them for an agent no blueprint manages and to read what an apply stored.
534
+
535
+ ```bash
536
+ vectros agents create intake-triage --context my-app --file ./intake-triage.yaml
537
+ vectros agents list --context my-app # each agent at its newest version
538
+ vectros agents list --context my-app --include-retired
539
+ vectros agents get 3b1c9f2e7a5d… --context my-app # newest version, with its prompt
540
+ vectros agents get 3b1c9f2e7a5d… --context my-app --at-version 1 # an earlier version
541
+ vectros agents version 3b1c9f2e7a5d… --context my-app --file ./intake-triage.yaml --expected-version 1
542
+ ```
543
+
544
+ The definition file is JSON, or YAML for a `.yaml`/`.yml` file, with the fields of a blueprint's `agents` entry:
545
+ `model` (required), `description`, `authority`, `system`, `tools` (`{ name, allowWrites? }`), `limits` and `budget`.
546
+ A key outside that list is refused before anything is sent, because the platform would drop it and store the agent
547
+ without what you meant it to have.
548
+
549
+ | Subcommand | Flags | Notes |
550
+ |---|---|---|
551
+ | `create` | the agent name; `--context <c>`, `--file <path>` (both required); `--tenant <test\|live>` | Stores version 1. If the name already exists the stored agent is returned **untouched** and nothing is written; the output says so. A retired or purged name is refused (`409`) because the name stays reserved. |
552
+ | `version` | the agent id; `--context <c>`, `--file <path>` (both required); `--expected-version <n>`, `--restore`, `--tenant <test\|live>` | Writes the next version. A **full replacement**: a field the file leaves out takes its default, nothing is carried over from the version before. `--expected-version` refuses the write (`409`) if the agent has a newer version than the one you read. `--restore` brings a **retired** agent back, with the file as its next version; a purged agent cannot be restored. |
553
+ | `list` | `--context <c>` (required); `--include-retired`, `--tenant <test\|live>` | Each agent at its newest version, newest first. Retired agents are left out unless asked for. |
554
+ | `get` | the agent id; `--context <c>` (required); `--at-version <n>`, `--tenant <test\|live>` | One agent, with its prompt and write-enabled tools marked. Ids are opaque: copy them from `agents list`. |
555
+
556
+ `--context` is required on all four, because an agent belongs to one app context. `create` needs the
557
+ `agents:c` scope on the credential, `version` needs `agents:u`, and `get` needs `agents:r`; `list` needs `agents:r` too, or `runs:c`, which lists each agent's name, version and status without its definition. A `403` names the scope. (A credential that
558
+ can create but not read gets "the name is already in use" for a name that exists; the output says why.)
559
+ There is no `delete`: retiring an agent keeps its name reserved, so it stays a deliberate call to the API.
560
+
561
+ A blueprint can declare agents instead; see *Agents* in [`AUTHORING.md`](./AUTHORING.md). To bring agents you created by hand
562
+ under a blueprint, apply it once with `--allow-agent-adoption`.
563
+
511
564
  ## `vectros assume` — switch identity namespace values on your own token
512
565
 
513
566
  Re-mints your own verb token with one or more `identity.<namespace>` values
@@ -729,8 +782,8 @@ Blueprints are **untrusted input** (agent- or community-authored) and the
729
782
  CLI runs under an elevated ephemeral bridge token. So the trust boundary is
730
783
  **this binary, not the blueprint**: a hardcoded **scope gate** bounds every
731
784
  mint to a data-plane allowlist (`records` / `schemas` / `search` / `documents`
732
- / `folders` / `inference` / `entities`). Most control-plane scope (keys /
733
- app-contexts / users / billing / admin / namespaces / triggers) or a
785
+ / `folders` / `inference` / `entities` / `runs`). Most control-plane scope (keys /
786
+ app-contexts / users / billing / admin / namespaces / triggers / agents) or a
734
787
  `*` wildcard **hard-rejects** — the CLI mints nothing and exits non-zero. There is
735
788
  intentionally **no override flag**.
736
789
 
@@ -769,7 +822,7 @@ A blueprint's `accessProfile` and role clauses may also declare
769
822
  identity in your tenant) that reach across a partition boundary in a way no
770
823
  `resource:ops` verb can express. This rides a field entirely separate from
771
824
  `allowedActions`, and it has its own allowlist: **`member-lifecycle` and
772
- `delegate-principal-stamp` are admitted today.** Every other capability name —
825
+ `delegate-principal-stamp` are admitted.** Every other capability name —
773
826
  including ones the platform's own registry recognizes — is refused, the same
774
827
  fail-closed, deliberately-widen posture as the scope gate above. `vectros blueprint validate`/`plan` and
775
828
  `bootstrap` all report a rejected capability the same way they report a