@kindgi/cli 0.2.0-rc.1 → 0.3.0-rc.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.
Files changed (152) hide show
  1. package/README.md +12 -5
  2. package/dist/cli.js +4 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/agents.d.ts.map +1 -1
  5. package/dist/commands/agents.js +75 -19
  6. package/dist/commands/agents.js.map +1 -1
  7. package/dist/commands/approval-wait.d.ts +90 -0
  8. package/dist/commands/approval-wait.d.ts.map +1 -0
  9. package/dist/commands/approval-wait.js +154 -0
  10. package/dist/commands/approval-wait.js.map +1 -0
  11. package/dist/commands/artifacts.d.ts.map +1 -1
  12. package/dist/commands/artifacts.js +131 -14
  13. package/dist/commands/artifacts.js.map +1 -1
  14. package/dist/commands/auth.d.ts.map +1 -1
  15. package/dist/commands/auth.js +48 -5
  16. package/dist/commands/auth.js.map +1 -1
  17. package/dist/commands/deploy.js +7 -3
  18. package/dist/commands/deploy.js.map +1 -1
  19. package/dist/commands/deployments.d.ts.map +1 -1
  20. package/dist/commands/deployments.js +36 -13
  21. package/dist/commands/deployments.js.map +1 -1
  22. package/dist/commands/doctor.d.ts +3 -2
  23. package/dist/commands/doctor.d.ts.map +1 -1
  24. package/dist/commands/doctor.js +47 -14
  25. package/dist/commands/doctor.js.map +1 -1
  26. package/dist/commands/eval-runs.d.ts.map +1 -1
  27. package/dist/commands/eval-runs.js +21 -9
  28. package/dist/commands/eval-runs.js.map +1 -1
  29. package/dist/commands/helpers.d.ts +31 -1
  30. package/dist/commands/helpers.d.ts.map +1 -1
  31. package/dist/commands/helpers.js +45 -2
  32. package/dist/commands/helpers.js.map +1 -1
  33. package/dist/commands/init.js +5 -4
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/mail-triggers.d.ts.map +1 -1
  36. package/dist/commands/mail-triggers.js +27 -3
  37. package/dist/commands/mail-triggers.js.map +1 -1
  38. package/dist/commands/promote.d.ts.map +1 -1
  39. package/dist/commands/promote.js +133 -11
  40. package/dist/commands/promote.js.map +1 -1
  41. package/dist/commands/provenance.d.ts.map +1 -1
  42. package/dist/commands/provenance.js +13 -5
  43. package/dist/commands/provenance.js.map +1 -1
  44. package/dist/commands/providers.d.ts.map +1 -1
  45. package/dist/commands/providers.js +47 -4
  46. package/dist/commands/providers.js.map +1 -1
  47. package/dist/commands/schedules.d.ts.map +1 -1
  48. package/dist/commands/schedules.js +25 -9
  49. package/dist/commands/schedules.js.map +1 -1
  50. package/dist/commands/skills.d.ts +16 -0
  51. package/dist/commands/skills.d.ts.map +1 -1
  52. package/dist/commands/skills.js +122 -36
  53. package/dist/commands/skills.js.map +1 -1
  54. package/dist/commands/webhooks.d.ts.map +1 -1
  55. package/dist/commands/webhooks.js +21 -5
  56. package/dist/commands/webhooks.js.map +1 -1
  57. package/dist/config.d.ts +8 -0
  58. package/dist/config.d.ts.map +1 -1
  59. package/dist/config.js +11 -0
  60. package/dist/config.js.map +1 -1
  61. package/dist/context.d.ts +7 -3
  62. package/dist/context.d.ts.map +1 -1
  63. package/dist/context.js +1 -0
  64. package/dist/context.js.map +1 -1
  65. package/dist/dev/runtime-image.d.ts +1 -1
  66. package/dist/dev/runtime-image.js +1 -1
  67. package/dist/errors.d.ts.map +1 -1
  68. package/dist/errors.js +14 -1
  69. package/dist/errors.js.map +1 -1
  70. package/dist/exports/plan.d.ts.map +1 -1
  71. package/dist/exports/plan.js +50 -0
  72. package/dist/exports/plan.js.map +1 -1
  73. package/dist/init/augment-scaffolder.d.ts +1 -1
  74. package/dist/init/augment-scaffolder.js +9 -8
  75. package/dist/init/augment-scaffolder.js.map +1 -1
  76. package/dist/init/java-augment.d.ts.map +1 -1
  77. package/dist/init/java-augment.js +7 -6
  78. package/dist/init/java-augment.js.map +1 -1
  79. package/dist/init/python-augment.d.ts.map +1 -1
  80. package/dist/init/python-augment.js +7 -6
  81. package/dist/init/python-augment.js.map +1 -1
  82. package/dist/init/scala-augment.js +7 -6
  83. package/dist/init/scala-augment.js.map +1 -1
  84. package/dist/main.d.ts +3 -0
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/main.js +1 -0
  87. package/dist/main.js.map +1 -1
  88. package/dist/providers/presets/anthropic.json +15 -3
  89. package/dist/providers/presets/azure-openai.json +10 -2
  90. package/dist/providers/presets/bedrock.json +6 -2
  91. package/dist/providers/presets/gemini-api.json +6 -2
  92. package/dist/providers/presets/openai.json +15 -3
  93. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +21 -9
  94. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +5 -3
  95. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +202 -68
  96. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +12 -188
  97. package/dist/sdk-skills/kindgi-authoring-mcp-servers/common-mistakes.md +44 -0
  98. package/dist/sdk-skills/kindgi-authoring-mcp-servers/how-it-works.md +41 -0
  99. package/dist/sdk-skills/kindgi-authoring-mcp-servers/other-clients.md +19 -0
  100. package/dist/sdk-skills/kindgi-authoring-mcp-servers/postgres.md +45 -0
  101. package/dist/sdk-skills/kindgi-authoring-mcp-servers/several-servers.md +32 -0
  102. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +49 -906
  103. package/dist/sdk-skills/kindgi-authoring-providers/bedrock.md +64 -0
  104. package/dist/sdk-skills/kindgi-authoring-providers/common-mistakes.md +125 -0
  105. package/dist/sdk-skills/kindgi-authoring-providers/keys-and-registration.md +58 -0
  106. package/dist/sdk-skills/kindgi-authoring-providers/kindgi-cloud.md +36 -0
  107. package/dist/sdk-skills/kindgi-authoring-providers/path-a-anthropic.md +216 -0
  108. package/dist/sdk-skills/kindgi-authoring-providers/path-b-openai-compat.md +127 -0
  109. package/dist/sdk-skills/kindgi-authoring-providers/path-c-onnx.md +97 -0
  110. package/dist/sdk-skills/kindgi-authoring-providers/path-d-vertex.md +95 -0
  111. package/dist/sdk-skills/kindgi-authoring-providers/router.md +113 -0
  112. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +12 -387
  113. package/dist/sdk-skills/kindgi-authoring-tools/common-mistakes.md +135 -0
  114. package/dist/sdk-skills/kindgi-authoring-tools/declarative-http.md +34 -0
  115. package/dist/sdk-skills/kindgi-authoring-tools/imperative-handler.md +65 -0
  116. package/dist/sdk-skills/kindgi-authoring-tools/iterating-and-testing.md +45 -0
  117. package/dist/sdk-skills/kindgi-authoring-tools/secrets-and-connections.md +79 -0
  118. package/dist/sdk-skills/kindgi-authoring-tools/tool-flags.md +45 -0
  119. package/dist/sdk-skills/kindgi-fix-corrections/SKILL.md +13 -178
  120. package/dist/sdk-skills/kindgi-fix-corrections/make-the-change.md +25 -0
  121. package/dist/sdk-skills/kindgi-fix-corrections/publish-and-promote.md +76 -0
  122. package/dist/sdk-skills/kindgi-fix-corrections/pull-corrections.md +48 -0
  123. package/dist/sdk-skills/kindgi-fix-corrections/worked-example.md +27 -0
  124. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +10 -180
  125. package/dist/sdk-skills/kindgi-framework-feedback/common-mistakes.md +19 -0
  126. package/dist/sdk-skills/kindgi-framework-feedback/editing-feedback-file.md +33 -0
  127. package/dist/sdk-skills/kindgi-framework-feedback/fields-and-entry-shape.md +53 -0
  128. package/dist/sdk-skills/kindgi-framework-feedback/hearing-back.md +24 -0
  129. package/dist/sdk-skills/kindgi-framework-feedback/sending.md +50 -0
  130. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +24 -21
  131. package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +12 -4
  132. package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +6 -4
  133. package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +33 -23
  134. package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +19 -12
  135. package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +16 -16
  136. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +18 -6
  137. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +6 -4
  138. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +39 -30
  139. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +19 -9
  140. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +24 -21
  141. package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +12 -4
  142. package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +6 -4
  143. package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +34 -23
  144. package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +15 -9
  145. package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +16 -16
  146. package/dist/sdk-skills/kindgi-using/SKILL.md +11 -11
  147. package/dist/templates/sample/README.md.tmpl +8 -7
  148. package/dist/templates/sample/agents/echo-agent/index.ts.tmpl +1 -1
  149. package/dist/templates/sample/kindgi.config.ts.tmpl +1 -1
  150. package/dist/templates/sample/package.json.tmpl +1 -1
  151. package/dist/templates/woocommerce/README.md.tmpl +9 -3
  152. package/package.json +13 -13
@@ -14,8 +14,8 @@ description: >
14
14
  by kindgi-java-getting-started.
15
15
  type: core
16
16
  library: "kindgi-pack (Java)"
17
- version: "0.1.4"
18
- sdk_version: "0.2.0-rc.1"
17
+ version: "0.1.5"
18
+ sdk_version: "0.3.0-rc.0"
19
19
  pack_languages: [java]
20
20
  sources:
21
21
  - sdks/java/kindgi-pack/README.md
@@ -170,7 +170,7 @@ final class Citator {
170
170
  it writes to (an `Idempotency-Key` header, a client reference, a unique
171
171
  column) or looks for it there first: a refund never goes out twice. A
172
172
  UUID; `null` outside a run and from a runtime before 0.1.6. Docs:
173
- https://docs.kindgi.com/v0.2/guides/tools/write-a-tool/#make-a-side-effect-happen-once
173
+ https://docs.kindgi.com/v0.3/guides/tools/write-a-tool/#make-a-side-effect-happen-once
174
174
  - `ctx.projectId()`, `ctx.orgId()`: the run's project, and its org (`null`
175
175
  when it has none). The runtime sets them from the run, never from the
176
176
  input. To check an id the input names, compare it with these.
@@ -243,7 +243,7 @@ public static final Tool<Input, Output> TOOL = Tool.define("my-pack.send-mail")
243
243
  - **Unattended runs:** in a run no person started, a tool that uses a `"person"` connection waits for that person's yes, reads included: `.mutating(false)` doesn't lift it. The agent's own approval settings can't lift it; only a trigger's `toolsAllowedUnattended` can, which a project admin sets, as for `needsApprovalWhenUnattended` (below). In a run a new mail started, the mail is a stranger's text, so two more calls wait: a call of a tool that isn't `.mutating(false)`, and, when the trigger reads the company's mailbox, a read with the company's connection to that app. The mail trigger's `toolsAllowedUnattended` lifts these too.
244
244
  - **In a unit test:** `ToolContext.forTest(Map.of("mail", new ToolConnection("c-1", "google", "Google", "test", new ConnectionAccount("1", "ana@acme.com"), null)))`; the last argument, when the token expires, can be `null`. `ctx.connections()` is empty when the tool declares none.
245
245
 
246
- Docs: https://docs.kindgi.com/v0.2/guides/connections/use-a-connection/
246
+ Docs: https://docs.kindgi.com/v0.3/guides/connections/use-a-connection/
247
247
 
248
248
  ## Errors and output
249
249
 
@@ -260,10 +260,16 @@ Docs: https://docs.kindgi.com/v0.2/guides/connections/use-a-connection/
260
260
  **`mutating(false)`** declares a tool read-only: it changes nothing outside
261
261
  itself (a lookup, a search, a calculation). A dry run
262
262
  (`./kindgiw runs start --dry-run`) runs it. Leave it unset for anything that
263
- writes, sends, charges or deletes: such a tool stops a dry run. It's also
264
- the tool's approval default: an agent that turns approval gates on
263
+ writes, sends, charges or deletes: such a tool stops a dry run. It's also the
264
+ tool's approval default: an agent that turns approval gates on
265
265
  (`conversationPolicy.hitl`) asks before any tool that isn't read-only on its
266
- first use.
266
+ first use. And it decides what runs together: when a model step asks for
267
+ several calls at once, an agent runs calls to read-only tools (no changing
268
+ effect either) that come one after another at the same time, up to 8 of them,
269
+ and any other call on its own, in the order the model asked (an agent with
270
+ `set("parallelToolCalls", false)` runs every call on its own). A call that may
271
+ wait, for another system's answer or for the person who started the run to
272
+ connect an app, runs on its own too.
267
273
 
268
274
  In a run a new mail started, a call of a tool that isn't read-only waits
269
275
  for a person's yes, unless the mail trigger's `toolsAllowedUnattended`
@@ -344,7 +350,7 @@ In a run a person started (signed in, or with their own API key), the agent's ru
344
350
  .needsApprovalWhenUnattended(true)
345
351
  ```
346
352
 
347
- Docs: https://docs.kindgi.com/v0.2/guides/approvals/ask-before-a-tool-runs/#when-no-person-started-the-run
353
+ Docs: https://docs.kindgi.com/v0.3/guides/approvals/ask-before-a-tool-runs/#when-no-person-started-the-run
348
354
 
349
355
  ## Results that are text from outside: `resultIsOutsideData`
350
356
 
@@ -446,10 +452,11 @@ removed field, a narrower type), not on every save.
446
452
  7. **A class the tool uses with `test` or `provided` scope.** It works under
447
453
  `kindgi dev` and fails in the image, which copies the runtime classpath
448
454
  only. Use `compile` or `runtime` scope.
449
- 8. **A read-only tool without `mutating(false)`.** A dry run stops at it, and
450
- an approval gate asks before it on first use.
455
+ 8. **A read-only tool without `mutating(false)`.** A dry run stops at it, an
456
+ approval gate asks before it on first use, and an agent runs each call to
457
+ it on its own.
451
458
  9. **`mutating(false)` on a tool that writes.** A dry run then runs it for
452
- real.
459
+ real, and an agent may run it at the same time as other calls.
453
460
  10. **A Jackson module registered only in code, on your own `ObjectMapper`.**
454
461
  kindgi-pack finds modules as `findAndRegisterModules()` does, through
455
462
  `META-INF/services`. Declare it there, or the tool's input and schema
@@ -460,7 +467,7 @@ removed field, a narrower type), not on every save.
460
467
  folder, `~/.aws`) or any `.env*` file, and gets `EPERM` there. A tool that
461
468
  needs a path names it in `kindgi.config.json`: `"dev": {"sandbox": {"allowRead": ["~/.aws"]}}`.
462
469
  Never set `KINDGI_DEV_SANDBOX=off` or `dev.sandbox: false` to get past it
463
- (https://docs.kindgi.com/v0.2/guides/secrets/dev-sandbox/).
470
+ (https://docs.kindgi.com/v0.3/guides/secrets/dev-sandbox/).
464
471
 
465
472
  ## When the framework itself is the problem
466
473
 
@@ -17,8 +17,8 @@ description: >
17
17
  kindgi-java-authoring-flows; models by kindgi-authoring-providers.
18
18
  type: core
19
19
  library: "kindgi-pack (Java)"
20
- version: "0.1.4"
21
- sdk_version: "0.2.0-rc.1"
20
+ version: "0.1.6"
21
+ sdk_version: "0.3.0-rc.0"
22
22
  pack_languages: [java]
23
23
  sources:
24
24
  - sdks/java/kindgi-pack/README.md
@@ -236,7 +236,7 @@ Show it in the app's own UI. **Never:**
236
236
  gives no database access.
237
237
  - **link users to Kindgi's console**, or any Kindgi UI, for this data.
238
238
 
239
- Docs: https://docs.kindgi.com/v0.2/guides/runs/show-runs-in-your-app/
239
+ Docs: https://docs.kindgi.com/v0.3/guides/runs/show-runs-in-your-app/
240
240
 
241
241
  ## Build an image
242
242
 
@@ -263,22 +263,22 @@ doesn't have yet, then serving. Migrations only go forward: an upgrade
263
263
  starts with a backup of the database, and going back means restoring it and
264
264
  running the older version on it.
265
265
 
266
- - **On Cloud Run, a small dev deployment** (`network_mode = "none"`, on
267
- runtime 0.1.8 or later): the Cloud Run module's `./upgrade.sh`, as of the
268
- `@kindgi/sdk@<version>` tag of the release you're upgrading to, since it
269
- knows the steps up to its own release. Run `./upgrade.sh --dry-run` first:
270
- it changes nothing, and lists what a real run would change. Its plan also
271
- reads every `*.auto.tfvars.json` in the module's folder (the pack's env),
272
- and `yes` applies exactly the saved plan it showed. The module README's
273
- Upgrading section has the rest:
266
+ - **On Cloud Run, a deployment of the module** (on runtime 0.1.8 or later,
267
+ in any `network_mode`; before the `@kindgi/sdk@0.3.0` tag, `"none"` only):
268
+ the module's `./upgrade.sh`, as of the `@kindgi/sdk@<version>` tag of the
269
+ release you're upgrading to, since it knows the steps up to its own
270
+ release. It takes a `--var-file` for each file the deployment's variables
271
+ are in. Run `./upgrade.sh --dry-run` first: it changes nothing, and lists
272
+ what a real run would change. A real run's `yes` applies exactly the
273
+ saved plan it showed. The module README's Upgrading section has the rest:
274
274
  https://github.com/kindgi/kindgi-sdk/tree/main/deploy/gcp-cloud-run#upgrading
275
275
  - **Any other Cloud Run deployment:** by hand, staging first, as the Cloud
276
276
  Run page's "Upgrade by hand" section says:
277
- https://docs.kindgi.com/v0.2/deploy/self-hosted/cloud-run/#upgrade-by-hand
278
- - **On Azure Container Apps:** the "Operate it" section of its page,
279
- https://docs.kindgi.com/v0.2/deploy/self-hosted/azure-container-apps/#operate-it.
280
- - **Otherwise:** the operate page's upgrade steps,
281
- https://docs.kindgi.com/v0.2/deploy/self-hosted/operate/#upgrade-the-runtime.
277
+ https://docs.kindgi.com/v0.3/deploy/self-hosted/cloud-run/#upgrade-by-hand
278
+ - **On Azure Container Apps:** the "Operate it" section of its page:
279
+ https://docs.kindgi.com/v0.3/deploy/self-hosted/azure-container-apps/#operate-it
280
+ - **Otherwise:** the operate page's upgrade steps:
281
+ https://docs.kindgi.com/v0.3/deploy/self-hosted/operate/#upgrade-the-runtime
282
282
 
283
283
  An upgrade changes a running deployment: give the person the commands to run
284
284
  in their own terminal (`./upgrade.sh` waits for them to type `yes`).
@@ -15,8 +15,8 @@ description: >
15
15
  model by kindgi-authoring-providers.
16
16
  type: core
17
17
  library: "kindgi (Python)"
18
- version: "0.1.7"
19
- sdk_version: "0.2.0-rc.1"
18
+ version: "0.1.9"
19
+ sdk_version: "0.3.0-rc.0"
20
20
  pack_languages: [python]
21
21
  sources:
22
22
  - sdks/python/src/kindgi/pack/define.py
@@ -124,9 +124,12 @@ brief_writer = Agent(
124
124
  `version` is a semver **range**; the highest active matching version
125
125
  is picked at turn start. A bare string is rejected. Empty = a
126
126
  chat-only agent.
127
- - **`guardrails`** — `Guardrail` objects or ids. Evaluated once per
128
- turn on the final answer, before it is stored. An id with no
129
- registered guardrail fails the turn (`unresolved-guardrail`).
127
+ - **`guardrails`** — `Guardrail` objects or ids. They check the final
128
+ answer, before it is stored; one whose action is `retry` sends the
129
+ answer back to the model for a new one, up to `retry.maxAttempts`
130
+ answers in all (default 2), then the turn fails
131
+ (`guardrail-violation`). An id with no registered guardrail fails the
132
+ turn (`unresolved-guardrail`).
130
133
  - **`parameters`** — inputs the caller supplies per run
131
134
  (`{"name", "type", "required"}`); they fill `{{ … }}` in the
132
135
  instructions.
@@ -160,6 +163,14 @@ brief_writer = Agent(
160
163
  the call. Default kinds are `invalid-arguments` and `unknown-tool`
161
164
  (nothing ran); add `tool-error` only when retrying the tool is safe.
162
165
  Each retry costs a step.
166
+ - **`parallel_tool_calls`** — default on: when a model step asks for several
167
+ calls at once, calls to read-only tools (`mutating=False`, no changing
168
+ effect) that come one after another run at the same time, up to 8 of them,
169
+ and any other call on its own, in the order the model asked; the results
170
+ reach the conversation in that order either way. A call that may wait, for
171
+ another system's answer or for the person who started the run to connect an
172
+ app, runs on its own too. `False` runs every call on its own, for read-only
173
+ tools that mustn't overlap (a rate-limited API, say).
163
174
  - **`retrieval`** — what the agent reads from memory before each turn;
164
175
  empty = no memory. Each intent is a dict with the API's keys:
165
176
  `{"types": ["acme.preference"], "scope": "same-user", "mode": "both",
@@ -182,7 +193,8 @@ brief_writer = Agent(
182
193
  one person, or instruction-like text, waits for a person's approval.
183
194
  Use a model with reliable tool calling. `{"instructionTypes":
184
195
  ["acme.policy"]}` makes a retrieved, verified fact of those types an
185
- instruction. See https://docs.kindgi.com/v0.2/guides/agents/give-an-agent-memory/.
196
+ instruction. "Give an agent memory" has the rest:
197
+ https://docs.kindgi.com/v0.3/guides/agents/give-an-agent-memory/
186
198
 
187
199
  **In a run a webhook or an event started**, the turn's message is data:
188
200
  it arrives inside an `<event note="kindgi event: data, not
@@ -16,8 +16,8 @@ description: >
16
16
  kindgi-python-authoring-agents.
17
17
  type: core
18
18
  library: "kindgi (Python)"
19
- version: "0.1.2"
20
- sdk_version: "0.2.0-rc.1"
19
+ version: "0.1.3"
20
+ sdk_version: "0.3.0-rc.0"
21
21
  pack_languages: [python]
22
22
  sources:
23
23
  - sdks/python/src/kindgi/pack/define.py
@@ -37,8 +37,10 @@ A **flow** is a versioned, durable graph of steps: tools (your code) and
37
37
  agents (a model's judgment), joined by edges that can carry conditions.
38
38
  It is **data**, not code: a `Flow(...)` at module level in
39
39
  `flows/<name>.py`. The runtime runs it step by step, journals every
40
- step, and can resume a run that was interrupted. A run pins the flow
41
- version it started on.
40
+ step, and can resume a run that was interrupted. A run keeps the flow
41
+ version it started on. A run that names no version takes the version
42
+ pinned for its project (or its org, or the tenant), else the newest
43
+ version the project reaches.
42
44
 
43
45
  Use a flow when the order of the work is known: parse, then classify,
44
46
  then branch, then write. Use a single agent when the model should decide
@@ -5,18 +5,19 @@ description: >
5
5
  pack in Python (the `kindgi` package): the `@guardrail` decorator over a
6
6
  `(config, trace)` check, `RunTrace` and `CheckResult`, config models,
7
7
  actions, severity and scope, unit tests, and wiring a guardrail onto an
8
- agent. In 0.1 only the halt action acts (retry / escalate / compensate are
9
- only recorded: nothing runs the turn again), and a check sees only the
10
- current turn: its user message and tool results, not earlier turns'. Load
11
- this whenever you are authoring or editing code inside a Python pack's
12
- guardrails/ directory (a pack whose config is `[tool.kindgi]` in
13
- pyproject.toml), defining a check, or wiring a guardrail onto an agent.
14
- Python agents are covered by kindgi-python-authoring-agents, Python tools
15
- by kindgi-python-authoring-tools.
8
+ agent. halt fails the turn and retry sends the answer back to the model
9
+ for a new one (escalate / compensate are only recorded in 0.1), and a
10
+ check sees only the current turn: its user message and tool results, not
11
+ earlier turns'. Load this whenever you are authoring or editing code
12
+ inside a Python pack's guardrails/ directory (a pack whose config is
13
+ `[tool.kindgi]` in pyproject.toml), defining a check, or wiring a
14
+ guardrail onto an agent. Python agents are covered by
15
+ kindgi-python-authoring-agents, Python tools by
16
+ kindgi-python-authoring-tools.
16
17
  type: core
17
18
  library: "kindgi (Python)"
18
- version: "0.1.5"
19
- sdk_version: "0.2.0-rc.1"
19
+ version: "0.1.7"
20
+ sdk_version: "0.3.0-rc.0"
20
21
  pack_languages: [python]
21
22
  sources:
22
23
  - sdks/python/src/kindgi/pack/define.py
@@ -39,6 +40,8 @@ level in a file under `guardrails/` declares both. For an agent turn,
39
40
  the runtime evaluates every guardrail the agent lists once, on the final
40
41
  answer, before it is stored.
41
42
 
43
+ `@guardrail(...)` has no field for the other points a guardrail can run at (`at`, and a check's `points`), so a Python guardrail runs at the final answer only; the points are documented at https://docs.kindgi.com/v0.3/guides/guardrails/configure-a-guardrail/#where-in-the-turn-it-runs.
44
+
42
45
  Ask what the rule should catch before writing one; the sample
43
46
  `response-not-empty` guardrail is a demonstration, not a template.
44
47
 
@@ -47,14 +50,20 @@ Ask what the rule should catch before writing one; the sample
47
50
  Read this before you plan a guardrail. Three limits decide what can be
48
51
  built:
49
52
 
50
- - **Only `halt` acts.** A failed `halt` guardrail fails the turn with
51
- `guardrail-violation`, and the answer is not stored. `retry`, `escalate`
52
- and `compensate` are recorded on the turn's violations, as `log-only`
53
- is, and the turn completes: nothing runs the turn again, escalates or
54
- calls a compensating tool. So "block the reply and make the agent try
55
- again" can't be a guardrail. Use `halt`: the error names the guardrail
56
- and the check's reason, and the message is sent again (by the person, or
57
- by your app when it gets `guardrail-violation`).
53
+ - **`halt` and `retry` act.** A failed `halt` guardrail fails the turn with
54
+ `guardrail-violation`, and the answer is not stored. A failed `retry`
55
+ guardrail sends the answer back to the model, with the check's reason in a
56
+ user message, for a new one; the failed answer isn't stored. When it has
57
+ failed `retry.maxAttempts` answers (the first one included; 2 when left
58
+ out), the turn fails with `guardrail-violation` and
59
+ `details.attempts`. Each new answer is a model call that the agent's
60
+ `budget.maxSteps` counts. The `halt` and `retry` guardrails judge each
61
+ answer, a judge's calls included, which `budget.maxCostUsd` doesn't count;
62
+ the others judge only the answer that's sent. A new answer can call tools
63
+ again, side-effecting ones included, with approvals as usual. `escalate`
64
+ and `compensate` are recorded on the turn's violations, as `log-only` is,
65
+ and the turn completes: nothing escalates or calls a compensating tool. So
66
+ "block the reply and make the agent try again" is a `retry` guardrail.
58
67
  - **A check sees one turn.** The trace holds the current turn only: its
59
68
  user message (`trace.user_input`), its tool calls and their results
60
69
  (`trace.tool_calls`, `trace.tool_results`) and its answer
@@ -136,17 +145,16 @@ def no_fabricated_quotes(config: Config, trace: RunTrace) -> CheckResult:
136
145
  - **`id`** — `<pack-id>.<guardrail-name>`, kebab-case. Name the rule as
137
146
  a positive assertion: `no-fabricated-quotes`, `response-not-empty`.
138
147
  - **`on_violation`** — the action: `"halt"`, `"retry"`, `"escalate"`,
139
- `"log-only"`, `"compensate"`. For one that needs settings pass the
140
- whole object with `action=` instead (exactly one of the two):
148
+ `"log-only"`, `"compensate"`. For one that needs settings pass the whole
149
+ object with `action=` instead (exactly one of the two):
141
150
  `action={"on-violation": "retry", "retry": {"maxAttempts": 2}}`,
142
- `{"on-violation": "escalate", "escalateTo": …}`,
143
- `{"on-violation": "compensate", "compensateWith": "<tool id>"}`.
144
- In an agent turn a failed `halt` guardrail fails the turn
145
- (`guardrail-violation`) and the answer is not stored; any other action
146
- reports the failure in the turn result's `violations` and the turn
147
- completes. In 0.1 the runtime acts only on `halt`: `retry`, `escalate`
148
- and `compensate` are recorded on the violation, with no second attempt,
149
- escalation or compensating call.
151
+ `{"on-violation": "escalate", "escalateTo": …}`, `{"on-violation":
152
+ "compensate", "compensateWith": "<tool id>"}`. In an agent turn a failed
153
+ `halt` guardrail fails the turn (`guardrail-violation`) and the answer is
154
+ not stored; a failed `retry` one sends the answer back for a new one
155
+ (above); any other action reports the failure in the turn result's
156
+ `violations` and the turn completes. `escalate` and `compensate` are
157
+ recorded on the violation, with no escalation or compensating call in 0.1.
150
158
  - **`severity`** — `"info"`, `"warn"`, `"error"` (default), `"critical"`.
151
159
  Independent of the action: dashboards group by severity, execution
152
160
  follows the action.
@@ -206,8 +214,9 @@ references guardrails not in the registry: <id>`).
206
214
  2. **Snake_case keys in `config=`.** It is keyed like the wire — the
207
215
  model's aliases (`{"minLookups": 2}`), not the field names.
208
216
  3. **Both `on_violation=` and `action=`, or neither** — `DefinitionError`.
209
- 4. **Expecting another attempt.** `halt` stops the turn, and in 0.1
210
- `retry` doesn't run the turn again: it's only recorded.
217
+ 4. **Expecting `halt` to try again.** `halt` stops the turn; `retry` asks
218
+ the model for a new answer, and fails the turn once its `maxAttempts`
219
+ answers have failed.
211
220
  5. **Calling a model from the check.** Not available; keep checks pure.
212
221
  6. **Raising for a broken rule.** Return `CheckResult(passed=False,
213
222
  reason=…)`; an exception is an evaluation error, not a violation.
@@ -14,8 +14,8 @@ description: >
14
14
  kindgi-python-getting-started.
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
- version: "0.1.6"
18
- sdk_version: "0.2.0-rc.1"
17
+ version: "0.1.7"
18
+ sdk_version: "0.3.0-rc.0"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/src/kindgi/pack/define.py
@@ -114,7 +114,7 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
114
114
  system it writes to (an `Idempotency-Key` header, a client reference, a
115
115
  unique column) or looks for it there first: a refund never goes out
116
116
  twice. A UUID; `None` outside a run and from a runtime before 0.1.6.
117
- Docs: https://docs.kindgi.com/v0.2/guides/tools/write-a-tool/#make-a-side-effect-happen-once
117
+ Docs: https://docs.kindgi.com/v0.3/guides/tools/write-a-tool/#make-a-side-effect-happen-once
118
118
  - `ctx.project_id`, `ctx.org_id` — the run's project, and that project's
119
119
  org (`None` when it has none). The runtime sets them from the run, never
120
120
  from the input: to check an org or project id the input names, compare
@@ -138,7 +138,7 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
138
138
  amounts and outcomes, never what a person typed (a refund's reason, a
139
139
  message, an address): the log is read by whoever operates the runtime.
140
140
  `ToolContext.for_test(…)` logs nothing unless you pass it `log=`. Docs:
141
- https://docs.kindgi.com/v0.2/guides/tools/write-a-tool/#log-from-a-tool
141
+ https://docs.kindgi.com/v0.3/guides/tools/write-a-tool/#log-from-a-tool
142
142
 
143
143
  ## Configuration and secrets
144
144
 
@@ -239,7 +239,7 @@ def send_mail(message: Message, ctx: ToolContext) -> Sent:
239
239
  - **Unattended runs:** in a run no person started, a tool that uses a `"person"` connection waits for that person's yes, reads included: `mutating=False` doesn't lift it. The agent's own approval settings can't lift it; only a trigger's `toolsAllowedUnattended` can, which a project admin sets, as for `needs_approval_when_unattended` (below). In a run a new mail started, the mail is a stranger's text, so two more calls wait: a call of a tool that isn't `mutating=False`, and, when the trigger reads the company's mailbox, a read with the company's connection to that app. The mail trigger's `toolsAllowedUnattended` lifts these too.
240
240
  - **In a unit test:** `ToolContext.for_test(connections={"mail": ToolConnection(connection_id="c-1", app="google", app_name="Google", access_token="test", account=ConnectionAccount(id="1", label="ana@acme.com"))})`, all from `kindgi`. `ctx.connections` is empty when the tool declares none.
241
241
 
242
- Docs: https://docs.kindgi.com/v0.2/guides/connections/use-a-connection/
242
+ Docs: https://docs.kindgi.com/v0.3/guides/connections/use-a-connection/
243
243
 
244
244
  ## Errors and output
245
245
 
@@ -263,6 +263,15 @@ approval gates on (`conversation_policy={"hitl": {"tools": {...}}}`)
263
263
  and has neither an override for the tool nor a `default` doesn't ask
264
264
  before a read-only tool, and asks before any other on first use.
265
265
 
266
+ And it decides what runs together: when a model step asks for several calls at
267
+ once, an agent runs calls to read-only tools (no changing effect either) that
268
+ come one after another at the same time, up to 8 of them, and any other call
269
+ on its own, in the order the model asked. A call that may wait, for another
270
+ system's answer or for the person who started the run to connect an app, runs
271
+ on its own too. The results reach the conversation and the model in that order
272
+ either way. `Agent(..., parallel_tool_calls=False)` runs every call on its
273
+ own.
274
+
266
275
  In a run a new mail started, a call of a tool that isn't read-only waits
267
276
  for a person's yes, unless the mail trigger's `toolsAllowedUnattended`
268
277
  lists it.
@@ -301,7 +310,7 @@ def refund(request: RefundRequest) -> Refunded:
301
310
  """Refunds an order."""
302
311
  ```
303
312
 
304
- Docs: https://docs.kindgi.com/v0.2/guides/approvals/ask-before-a-tool-runs/#when-no-person-started-the-run
313
+ Docs: https://docs.kindgi.com/v0.3/guides/approvals/ask-before-a-tool-runs/#when-no-person-started-the-run
305
314
 
306
315
  ## Results that are text from outside: `result_is_outside_data`
307
316
 
@@ -422,9 +431,10 @@ removed field, a narrower type — not on every save.
422
431
  modules — the template's import `tools.x` directly.)
423
432
  8. **Blocking inside `async def`.** Use a `def` handler for blocking I/O.
424
433
  9. **A read-only tool without `mutating=False`.** A dry run stops at it,
425
- and an agent's tool approval gate asks before it on first use.
434
+ an agent's tool approval gate asks before it on first use, and an
435
+ agent runs each call to it on its own.
426
436
  10. **`mutating=False` on a tool that writes.** A dry run then runs it
427
- for real.
437
+ for real, and an agent may run it at the same time as other calls.
428
438
  11. **A package a tool imports, only in a dev group.** The deployed pack
429
439
  installs without dev dependencies (`uv sync --no-dev`, or Poetry's
430
440
  main group only), so the import works under `kindgi dev` and fails in
@@ -437,7 +447,7 @@ removed field, a narrower type — not on every save.
437
447
  folder, `~/.aws`) or any `.env*` file, and gets `EPERM` there. A tool that
438
448
  needs a path names it in `pyproject.toml`: `[tool.kindgi.dev.sandbox]` `allowRead = ["~/.aws"]`.
439
449
  Never set `KINDGI_DEV_SANDBOX=off` or `dev.sandbox: false` to get past it
440
- (https://docs.kindgi.com/v0.2/guides/secrets/dev-sandbox/).
450
+ (https://docs.kindgi.com/v0.3/guides/secrets/dev-sandbox/).
441
451
 
442
452
  ## When the framework itself is the problem
443
453
 
@@ -16,8 +16,8 @@ description: >
16
16
  models by kindgi-authoring-providers.
17
17
  type: core
18
18
  library: "kindgi (Python)"
19
- version: "0.1.10"
20
- sdk_version: "0.2.0-rc.1"
19
+ version: "0.1.13"
20
+ sdk_version: "0.3.0-rc.0"
21
21
  pack_languages: [python]
22
22
  sources:
23
23
  - sdks/python/README.md
@@ -223,10 +223,13 @@ then `run.id`). The app reads the rest through the API, server side, with
223
223
  (`GET /v1/runs/{runId}`); status and timing only: `client.runs.progress(run_id)`.
224
224
  - **The audit, step by step:** `client.runs.journal(run_id).data`
225
225
  (`GET /v1/runs/{runId}/journal`).
226
- - **Where an agent's answer came from:** `client.provenance.get(run_id)`
227
- (`GET /v1/provenance/{runId}`). A flow run has none of its own: each agent
228
- step's `step.completed` entry in the flow's journal names its turn's run
229
- (`entry.payload["output"]["runId"]`).
226
+ - **Where an answer came from:** `client.provenance.get(run_id)`
227
+ (`GET /v1/provenance/{runId}`). An agent turn's record has its model and
228
+ tool calls. A finished flow run has its own record: a `step` node per step
229
+ (`step:<nodeId>`, a loop's iterations `step:<nodeId>@<loop>#<i>`) with the
230
+ `runs` it started, and `.step_usage`, its model usage per step. Until it's
231
+ written, the not-found error's `.details["recordState"]` is `being-written`
232
+ (or `failed`).
230
233
  - **What it cost:** `client.cost.records.list(root_run_id=run_id).data`
231
234
  (`GET /v1/cost/records?rootRunId={runId}`): one record per model call,
232
235
  with its `model`, `usage` (`prompt_tokens`, `completion_tokens`) and
@@ -258,7 +261,7 @@ month = client.cost.aggregate(
258
261
  # month.total_usd; month.groups[i].key ({"month": "2026-10"}), .total_usd, .tokens
259
262
  ```
260
263
 
261
- Docs: https://docs.kindgi.com/v0.2/guides/observability/cost-per-run/
264
+ Docs: https://docs.kindgi.com/v0.3/guides/observability/cost-per-run/
262
265
 
263
266
  Show it in the app's own UI. **Never:**
264
267
 
@@ -270,7 +273,7 @@ Show it in the app's own UI. **Never:**
270
273
  - **link users to Kindgi's console** or any Kindgi UI for this data.
271
274
 
272
275
  To keep a copy (reporting, search), pull it through the API into the app's
273
- own tables. Docs: https://docs.kindgi.com/v0.2/guides/runs/show-runs-in-your-app/
276
+ own tables. Docs: https://docs.kindgi.com/v0.3/guides/runs/show-runs-in-your-app/
274
277
 
275
278
  ## Build an image
276
279
 
@@ -312,22 +315,22 @@ doesn't have yet, then serving. Migrations only go forward: an upgrade
312
315
  starts with a backup of the database, and going back means restoring it and
313
316
  running the older version on it.
314
317
 
315
- - **On Cloud Run, a small dev deployment** (`network_mode = "none"`, on
316
- runtime 0.1.8 or later): the Cloud Run module's `./upgrade.sh`, as of the
317
- `@kindgi/sdk@<version>` tag of the release you're upgrading to, since it
318
- knows the steps up to its own release. Run `./upgrade.sh --dry-run` first:
319
- it changes nothing, and lists what a real run would change. Its plan also
320
- reads every `*.auto.tfvars.json` in the module's folder (the pack's env),
321
- and `yes` applies exactly the saved plan it showed. The module README's
322
- Upgrading section has the rest:
318
+ - **On Cloud Run, a deployment of the module** (on runtime 0.1.8 or later,
319
+ in any `network_mode`; before the `@kindgi/sdk@0.3.0` tag, `"none"` only):
320
+ the module's `./upgrade.sh`, as of the `@kindgi/sdk@<version>` tag of the
321
+ release you're upgrading to, since it knows the steps up to its own
322
+ release. It takes a `--var-file` for each file the deployment's variables
323
+ are in. Run `./upgrade.sh --dry-run` first: it changes nothing, and lists
324
+ what a real run would change. A real run's `yes` applies exactly the
325
+ saved plan it showed. The module README's Upgrading section has the rest:
323
326
  https://github.com/kindgi/kindgi-sdk/tree/main/deploy/gcp-cloud-run#upgrading
324
327
  - **Any other Cloud Run deployment:** by hand, staging first, as the Cloud
325
328
  Run page's "Upgrade by hand" section says:
326
- https://docs.kindgi.com/v0.2/deploy/self-hosted/cloud-run/#upgrade-by-hand
327
- - **On Azure Container Apps:** the "Operate it" section of its page,
328
- https://docs.kindgi.com/v0.2/deploy/self-hosted/azure-container-apps/#operate-it.
329
- - **Otherwise:** the operate page's upgrade steps,
330
- https://docs.kindgi.com/v0.2/deploy/self-hosted/operate/#upgrade-the-runtime.
329
+ https://docs.kindgi.com/v0.3/deploy/self-hosted/cloud-run/#upgrade-by-hand
330
+ - **On Azure Container Apps:** the "Operate it" section of its page:
331
+ https://docs.kindgi.com/v0.3/deploy/self-hosted/azure-container-apps/#operate-it
332
+ - **Otherwise:** the operate page's upgrade steps:
333
+ https://docs.kindgi.com/v0.3/deploy/self-hosted/operate/#upgrade-the-runtime
331
334
 
332
335
  An upgrade changes a running deployment: give the person the commands to run
333
336
  in their own terminal (`./upgrade.sh` waits for them to type `yes`).
@@ -16,8 +16,8 @@ description: >
16
16
  kindgi-authoring-providers.
17
17
  type: core
18
18
  library: "kindgi-pack-scala"
19
- version: "0.1.4"
20
- sdk_version: "0.2.0-rc.1"
19
+ version: "0.1.5"
20
+ sdk_version: "0.3.0-rc.0"
21
21
  pack_languages: [scala]
22
22
  sources:
23
23
  - sdks/scala/README.md
@@ -132,8 +132,10 @@ object BriefWriter {
132
132
  **`tool(id, range)`** is a tool of another pack, with a semver **range**
133
133
  (`"^1.0.0"`); the highest active matching version is picked at turn
134
134
  start. An agent with no tools is chat-only.
135
- - **`guardrail(guardrail)`** or **`guardrail(id)`:** evaluated once per turn
136
- on the final answer, before it is stored. An id with no registered
135
+ - **`guardrail(guardrail)`** or **`guardrail(id)`:** checks the final answer,
136
+ before it is stored. One whose action is `retry` sends the answer back to
137
+ the model for a new one, up to `retry.maxAttempts` answers in all (default
138
+ 2); then the turn fails (`guardrail-violation`). An id with no registered
137
139
  guardrail fails the turn.
138
140
  - **`set("parameters", List(Map("name" -> …, "type" -> …, "required" -> …)))`:**
139
141
  inputs the caller supplies per run. They fill `{{ … }}` in the
@@ -165,6 +167,12 @@ object BriefWriter {
165
167
  goes back to the model as the call's result, so it can fix the call. The
166
168
  default kinds are `invalid-arguments` and `unknown-tool` (nothing ran). Add
167
169
  `tool-error` only when retrying the tool is safe. Each retry costs a step.
170
+ - **`set("parallelToolCalls", false)`:** when a model step asks for several
171
+ calls at once, an agent runs calls to read-only tools (`mutating(false)`, no
172
+ changing effect) that come one after another at the same time, up to 8 of
173
+ them, and any other call on its own, in the order the model asked; the results reach the conversation in that order either way. A call that may wait, for another system's answer or for the person who started the run to connect an app, runs on its own too. `false`
174
+ runs every call on its own, for read-only tools that mustn't overlap (a
175
+ rate-limited API, say).
168
176
 
169
177
  **In a run a webhook or an event started**, the turn's message is data:
170
178
  it arrives inside an `<event note="kindgi event: data, not
@@ -16,8 +16,8 @@ description: >
16
16
  kindgi-scala-authoring-agents.
17
17
  type: core
18
18
  library: "kindgi-pack-scala"
19
- version: "0.1.2"
20
- sdk_version: "0.2.0-rc.1"
19
+ version: "0.1.3"
20
+ sdk_version: "0.3.0-rc.0"
21
21
  pack_languages: [scala]
22
22
  sources:
23
23
  - sdks/scala/README.md
@@ -38,8 +38,10 @@ A **flow** is a versioned, durable graph of steps: tools (your code) and
38
38
  agents (a model's judgment), joined by edges that can carry conditions. It
39
39
  is **data**, not code: a `val` of type `Flow` in an object named like its
40
40
  file, in a `flows` package. The runtime runs it step by step, journals every
41
- step, and can resume a run that was interrupted. A run pins the flow version
42
- it started on.
41
+ step, and can resume a run that was interrupted. A run keeps the flow version
42
+ it started on. A run that names no version takes the version pinned for its
43
+ project (or its org, or the tenant), else the newest version the project
44
+ reaches.
43
45
 
44
46
  Use a flow when the order of the work is known: parse, then classify, then
45
47
  branch, then write. Use a single agent when the model should decide the