@kindgi/cli 0.1.4 → 0.1.5-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 (319) hide show
  1. package/README.md +13 -7
  2. package/dist/build/defaults.d.ts +3 -1
  3. package/dist/build/defaults.d.ts.map +1 -1
  4. package/dist/build/defaults.js +44 -1
  5. package/dist/build/defaults.js.map +1 -1
  6. package/dist/build/java-image.d.ts +31 -0
  7. package/dist/build/java-image.d.ts.map +1 -0
  8. package/dist/build/java-image.js +146 -0
  9. package/dist/build/java-image.js.map +1 -0
  10. package/dist/build/pack-root.d.ts +1 -31
  11. package/dist/build/pack-root.d.ts.map +1 -1
  12. package/dist/build/pack-root.js +22 -2
  13. package/dist/build/pack-root.js.map +1 -1
  14. package/dist/build/runners.d.ts +44 -0
  15. package/dist/build/runners.d.ts.map +1 -1
  16. package/dist/build/scala-image.d.ts +21 -0
  17. package/dist/build/scala-image.d.ts.map +1 -0
  18. package/dist/build/scala-image.js +150 -0
  19. package/dist/build/scala-image.js.map +1 -0
  20. package/dist/cli-pin.d.ts +16 -0
  21. package/dist/cli-pin.d.ts.map +1 -0
  22. package/dist/cli-pin.js +66 -0
  23. package/dist/cli-pin.js.map +1 -0
  24. package/dist/commands/agents.d.ts.map +1 -1
  25. package/dist/commands/agents.js +9 -8
  26. package/dist/commands/agents.js.map +1 -1
  27. package/dist/commands/approvals.d.ts.map +1 -1
  28. package/dist/commands/approvals.js +30 -4
  29. package/dist/commands/approvals.js.map +1 -1
  30. package/dist/commands/artifacts.d.ts.map +1 -1
  31. package/dist/commands/artifacts.js +100 -37
  32. package/dist/commands/artifacts.js.map +1 -1
  33. package/dist/commands/auth.js +2 -2
  34. package/dist/commands/blocks.d.ts.map +1 -1
  35. package/dist/commands/blocks.js +5 -4
  36. package/dist/commands/blocks.js.map +1 -1
  37. package/dist/commands/build.d.ts +10 -2
  38. package/dist/commands/build.d.ts.map +1 -1
  39. package/dist/commands/build.js +109 -16
  40. package/dist/commands/build.js.map +1 -1
  41. package/dist/commands/capabilities.d.ts.map +1 -1
  42. package/dist/commands/capabilities.js +37 -10
  43. package/dist/commands/capabilities.js.map +1 -1
  44. package/dist/commands/console.d.ts +21 -0
  45. package/dist/commands/console.d.ts.map +1 -0
  46. package/dist/commands/console.js +87 -0
  47. package/dist/commands/console.js.map +1 -0
  48. package/dist/commands/conversations.d.ts.map +1 -1
  49. package/dist/commands/conversations.js +13 -2
  50. package/dist/commands/conversations.js.map +1 -1
  51. package/dist/commands/deploy.d.ts.map +1 -1
  52. package/dist/commands/deploy.js +2 -2
  53. package/dist/commands/deploy.js.map +1 -1
  54. package/dist/commands/dev.d.ts +11 -0
  55. package/dist/commands/dev.d.ts.map +1 -1
  56. package/dist/commands/dev.js +211 -39
  57. package/dist/commands/dev.js.map +1 -1
  58. package/dist/commands/doctor.d.ts +14 -2
  59. package/dist/commands/doctor.d.ts.map +1 -1
  60. package/dist/commands/doctor.js +355 -19
  61. package/dist/commands/doctor.js.map +1 -1
  62. package/dist/commands/env-scoped.d.ts +44 -0
  63. package/dist/commands/env-scoped.d.ts.map +1 -0
  64. package/dist/commands/env-scoped.js +222 -0
  65. package/dist/commands/env-scoped.js.map +1 -0
  66. package/dist/commands/env.d.ts.map +1 -1
  67. package/dist/commands/env.js +85 -123
  68. package/dist/commands/env.js.map +1 -1
  69. package/dist/commands/eval-runs.d.ts +9 -0
  70. package/dist/commands/eval-runs.d.ts.map +1 -1
  71. package/dist/commands/eval-runs.js +20 -19
  72. package/dist/commands/eval-runs.js.map +1 -1
  73. package/dist/commands/eval-suites.d.ts.map +1 -1
  74. package/dist/commands/eval-suites.js +16 -8
  75. package/dist/commands/eval-suites.js.map +1 -1
  76. package/dist/commands/exports.d.ts +3 -0
  77. package/dist/commands/exports.d.ts.map +1 -0
  78. package/dist/commands/exports.js +82 -0
  79. package/dist/commands/exports.js.map +1 -0
  80. package/dist/commands/feedback.d.ts.map +1 -1
  81. package/dist/commands/feedback.js +6 -5
  82. package/dist/commands/feedback.js.map +1 -1
  83. package/dist/commands/flows.d.ts.map +1 -1
  84. package/dist/commands/flows.js +2 -1
  85. package/dist/commands/flows.js.map +1 -1
  86. package/dist/commands/gate-policies.d.ts.map +1 -1
  87. package/dist/commands/gate-policies.js +2 -1
  88. package/dist/commands/gate-policies.js.map +1 -1
  89. package/dist/commands/guardrails.d.ts.map +1 -1
  90. package/dist/commands/guardrails.js +3 -2
  91. package/dist/commands/guardrails.js.map +1 -1
  92. package/dist/commands/helpers.js +5 -5
  93. package/dist/commands/helpers.js.map +1 -1
  94. package/dist/commands/index.d.ts.map +1 -1
  95. package/dist/commands/index.js +14 -0
  96. package/dist/commands/index.js.map +1 -1
  97. package/dist/commands/init.d.ts +1 -1
  98. package/dist/commands/init.d.ts.map +1 -1
  99. package/dist/commands/init.js +254 -18
  100. package/dist/commands/init.js.map +1 -1
  101. package/dist/commands/judge-classes.d.ts.map +1 -1
  102. package/dist/commands/judge-classes.js +11 -10
  103. package/dist/commands/judge-classes.js.map +1 -1
  104. package/dist/commands/judgments.d.ts.map +1 -1
  105. package/dist/commands/judgments.js +7 -6
  106. package/dist/commands/judgments.js.map +1 -1
  107. package/dist/commands/key.js +4 -4
  108. package/dist/commands/memory.d.ts.map +1 -1
  109. package/dist/commands/memory.js +277 -25
  110. package/dist/commands/memory.js.map +1 -1
  111. package/dist/commands/people.d.ts +3 -0
  112. package/dist/commands/people.d.ts.map +1 -0
  113. package/dist/commands/people.js +166 -0
  114. package/dist/commands/people.js.map +1 -0
  115. package/dist/commands/proposals.d.ts.map +1 -1
  116. package/dist/commands/proposals.js +390 -69
  117. package/dist/commands/proposals.js.map +1 -1
  118. package/dist/commands/provenance.d.ts.map +1 -1
  119. package/dist/commands/provenance.js +6 -7
  120. package/dist/commands/provenance.js.map +1 -1
  121. package/dist/commands/providers.d.ts.map +1 -1
  122. package/dist/commands/providers.js +6 -5
  123. package/dist/commands/providers.js.map +1 -1
  124. package/dist/commands/reviewers.d.ts.map +1 -1
  125. package/dist/commands/reviewers.js +3 -2
  126. package/dist/commands/reviewers.js.map +1 -1
  127. package/dist/commands/runs.d.ts.map +1 -1
  128. package/dist/commands/runs.js +24 -14
  129. package/dist/commands/runs.js.map +1 -1
  130. package/dist/commands/schedules.d.ts +3 -0
  131. package/dist/commands/schedules.d.ts.map +1 -0
  132. package/dist/commands/schedules.js +275 -0
  133. package/dist/commands/schedules.js.map +1 -0
  134. package/dist/commands/secrets.d.ts.map +1 -1
  135. package/dist/commands/secrets.js +10 -11
  136. package/dist/commands/secrets.js.map +1 -1
  137. package/dist/commands/service-accounts.d.ts +3 -0
  138. package/dist/commands/service-accounts.d.ts.map +1 -0
  139. package/dist/commands/service-accounts.js +175 -0
  140. package/dist/commands/service-accounts.js.map +1 -0
  141. package/dist/commands/skills.d.ts +1 -1
  142. package/dist/commands/skills.d.ts.map +1 -1
  143. package/dist/commands/skills.js +11 -4
  144. package/dist/commands/skills.js.map +1 -1
  145. package/dist/commands/sso.d.ts +6 -0
  146. package/dist/commands/sso.d.ts.map +1 -0
  147. package/dist/commands/sso.js +318 -0
  148. package/dist/commands/sso.js.map +1 -0
  149. package/dist/commands/tokens.d.ts +11 -0
  150. package/dist/commands/tokens.d.ts.map +1 -1
  151. package/dist/commands/tokens.js +144 -11
  152. package/dist/commands/tokens.js.map +1 -1
  153. package/dist/commands/tools.d.ts.map +1 -1
  154. package/dist/commands/tools.js +4 -3
  155. package/dist/commands/tools.js.map +1 -1
  156. package/dist/commands/unwired.d.ts.map +1 -1
  157. package/dist/commands/unwired.js +1 -30
  158. package/dist/commands/unwired.js.map +1 -1
  159. package/dist/commands/upgrade.d.ts +11 -0
  160. package/dist/commands/upgrade.d.ts.map +1 -0
  161. package/dist/commands/upgrade.js +160 -0
  162. package/dist/commands/upgrade.js.map +1 -0
  163. package/dist/context.d.ts +7 -0
  164. package/dist/context.d.ts.map +1 -1
  165. package/dist/context.js +1 -0
  166. package/dist/context.js.map +1 -1
  167. package/dist/dev/defaults.d.ts +28 -11
  168. package/dist/dev/defaults.d.ts.map +1 -1
  169. package/dist/dev/defaults.js +114 -35
  170. package/dist/dev/defaults.js.map +1 -1
  171. package/dist/dev/google-credentials.d.ts +50 -0
  172. package/dist/dev/google-credentials.d.ts.map +1 -0
  173. package/dist/dev/google-credentials.js +157 -0
  174. package/dist/dev/google-credentials.js.map +1 -0
  175. package/dist/dev/java-builder.d.ts +56 -0
  176. package/dist/dev/java-builder.d.ts.map +1 -0
  177. package/dist/dev/java-builder.js +204 -0
  178. package/dist/dev/java-builder.js.map +1 -0
  179. package/dist/dev/jvm-run-files.d.ts +29 -0
  180. package/dist/dev/jvm-run-files.d.ts.map +1 -0
  181. package/dist/dev/jvm-run-files.js +94 -0
  182. package/dist/dev/jvm-run-files.js.map +1 -0
  183. package/dist/dev/lines.d.ts +13 -0
  184. package/dist/dev/lines.d.ts.map +1 -0
  185. package/dist/dev/lines.js +24 -0
  186. package/dist/dev/lines.js.map +1 -0
  187. package/dist/dev/log-view.d.ts +116 -0
  188. package/dist/dev/log-view.d.ts.map +1 -0
  189. package/dist/dev/log-view.js +233 -0
  190. package/dist/dev/log-view.js.map +1 -0
  191. package/dist/dev/pack-code.d.ts +79 -4
  192. package/dist/dev/pack-code.d.ts.map +1 -1
  193. package/dist/dev/pack-code.js +262 -3
  194. package/dist/dev/pack-code.js.map +1 -1
  195. package/dist/dev/pack-env.d.ts.map +1 -1
  196. package/dist/dev/pack-env.js +4 -0
  197. package/dist/dev/pack-env.js.map +1 -1
  198. package/dist/dev/pack-service.d.ts +11 -1
  199. package/dist/dev/pack-service.d.ts.map +1 -1
  200. package/dist/dev/pack-service.js +56 -20
  201. package/dist/dev/pack-service.js.map +1 -1
  202. package/dist/dev/paths.d.ts +6 -0
  203. package/dist/dev/paths.d.ts.map +1 -1
  204. package/dist/dev/paths.js +8 -0
  205. package/dist/dev/paths.js.map +1 -1
  206. package/dist/dev/project-database.js +1 -1
  207. package/dist/dev/project-database.js.map +1 -1
  208. package/dist/dev/runners.d.ts +35 -9
  209. package/dist/dev/runners.d.ts.map +1 -1
  210. package/dist/dev/runtime-container.d.ts +10 -2
  211. package/dist/dev/runtime-container.d.ts.map +1 -1
  212. package/dist/dev/runtime-container.js +48 -20
  213. package/dist/dev/runtime-container.js.map +1 -1
  214. package/dist/dev/runtime-env.d.ts +10 -0
  215. package/dist/dev/runtime-env.d.ts.map +1 -1
  216. package/dist/dev/runtime-env.js +8 -4
  217. package/dist/dev/runtime-env.js.map +1 -1
  218. package/dist/dev/runtime-image.d.ts +1 -1
  219. package/dist/dev/runtime-image.d.ts.map +1 -1
  220. package/dist/dev/runtime-image.js +1 -1
  221. package/dist/dev/runtime-image.js.map +1 -1
  222. package/dist/dev/scala-builder.d.ts +72 -0
  223. package/dist/dev/scala-builder.d.ts.map +1 -0
  224. package/dist/dev/scala-builder.js +347 -0
  225. package/dist/dev/scala-builder.js.map +1 -0
  226. package/dist/env/project-env.d.ts.map +1 -1
  227. package/dist/env/project-env.js +3 -1
  228. package/dist/env/project-env.js.map +1 -1
  229. package/dist/errors.d.ts +9 -0
  230. package/dist/errors.d.ts.map +1 -1
  231. package/dist/errors.js +15 -0
  232. package/dist/errors.js.map +1 -1
  233. package/dist/init/dependency-specs.d.ts +26 -0
  234. package/dist/init/dependency-specs.d.ts.map +1 -1
  235. package/dist/init/dependency-specs.js +38 -0
  236. package/dist/init/dependency-specs.js.map +1 -1
  237. package/dist/init/java-augment.d.ts +24 -0
  238. package/dist/init/java-augment.d.ts.map +1 -0
  239. package/dist/init/java-augment.js +198 -0
  240. package/dist/init/java-augment.js.map +1 -0
  241. package/dist/init/mode-detect.d.ts +2 -2
  242. package/dist/init/mode-detect.d.ts.map +1 -1
  243. package/dist/init/mode-detect.js +12 -1
  244. package/dist/init/mode-detect.js.map +1 -1
  245. package/dist/init/scala-augment.d.ts +23 -0
  246. package/dist/init/scala-augment.d.ts.map +1 -0
  247. package/dist/init/scala-augment.js +213 -0
  248. package/dist/init/scala-augment.js.map +1 -0
  249. package/dist/init/template-files.d.ts +40 -2
  250. package/dist/init/template-files.d.ts.map +1 -1
  251. package/dist/init/template-files.js +56 -5
  252. package/dist/init/template-files.js.map +1 -1
  253. package/dist/main.d.ts +3 -0
  254. package/dist/main.d.ts.map +1 -1
  255. package/dist/main.js +20 -2
  256. package/dist/main.js.map +1 -1
  257. package/dist/open-url.d.ts +15 -0
  258. package/dist/open-url.d.ts.map +1 -0
  259. package/dist/open-url.js +41 -0
  260. package/dist/open-url.js.map +1 -0
  261. package/dist/package-manager.d.ts +10 -3
  262. package/dist/package-manager.d.ts.map +1 -1
  263. package/dist/package-manager.js +19 -1
  264. package/dist/package-manager.js.map +1 -1
  265. package/dist/providers/presets/anthropic.json +11 -3
  266. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +26 -2
  267. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +1 -1
  268. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +47 -3
  269. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +7 -5
  270. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +40 -15
  271. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +27 -1
  272. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +5 -4
  273. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +1 -1
  274. package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +220 -0
  275. package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +390 -0
  276. package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +209 -0
  277. package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +334 -0
  278. package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +270 -0
  279. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +21 -3
  280. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
  281. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +10 -3
  282. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +36 -5
  283. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +2 -2
  284. package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +217 -0
  285. package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +357 -0
  286. package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +199 -0
  287. package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +302 -0
  288. package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +302 -0
  289. package/dist/templates/java/.mvn/wrapper/maven-wrapper.properties +3 -0
  290. package/dist/templates/java/AGENTS.md +31 -0
  291. package/dist/templates/java/README.md.tmpl +69 -0
  292. package/dist/templates/java/gitignore +9 -0
  293. package/dist/templates/java/kindgi.config.json.tmpl +8 -0
  294. package/dist/templates/java/kindgiw +33 -0
  295. package/dist/templates/java/kindgiw.cmd +28 -0
  296. package/dist/templates/java/mvnw +295 -0
  297. package/dist/templates/java/pom.xml.tmpl +65 -0
  298. package/dist/templates/java/src/main/java/__PACKAGE__/agents/EchoAgent.java.tmpl +27 -0
  299. package/dist/templates/java/src/main/java/__PACKAGE__/flows/EchoFlow.java.tmpl +18 -0
  300. package/dist/templates/java/src/main/java/__PACKAGE__/guardrails/ResponseNotEmpty.java.tmpl +28 -0
  301. package/dist/templates/java/src/main/java/__PACKAGE__/tools/Echo.java.tmpl +22 -0
  302. package/dist/templates/java/src/main/java/__PACKAGE__/tools/Greet.java.tmpl +23 -0
  303. package/dist/templates/java/src/test/java/__PACKAGE__/ToolsTest.java.tmpl +30 -0
  304. package/dist/templates/minimal/README.md.tmpl +6 -12
  305. package/dist/templates/python/README.md.tmpl +4 -4
  306. package/dist/templates/sample/README.md.tmpl +5 -11
  307. package/dist/templates/scala/AGENTS.md +32 -0
  308. package/dist/templates/scala/README.md.tmpl +75 -0
  309. package/dist/templates/scala/build.sbt.tmpl +16 -0
  310. package/dist/templates/scala/gitignore +13 -0
  311. package/dist/templates/scala/kindgi.config.json.tmpl +8 -0
  312. package/dist/templates/scala/project/build.properties +1 -0
  313. package/dist/templates/scala/src/main/scala/__PACKAGE__/agents/EchoAgent.scala.tmpl +23 -0
  314. package/dist/templates/scala/src/main/scala/__PACKAGE__/flows/EchoFlow.scala.tmpl +16 -0
  315. package/dist/templates/scala/src/main/scala/__PACKAGE__/guardrails/ResponseNotEmpty.scala.tmpl +21 -0
  316. package/dist/templates/scala/src/main/scala/__PACKAGE__/tools/Echo.scala.tmpl +16 -0
  317. package/dist/templates/scala/src/main/scala/__PACKAGE__/tools/Greet.scala.tmpl +17 -0
  318. package/dist/templates/scala/src/test/scala/__PACKAGE__/ToolsSuite.scala.tmpl +23 -0
  319. package/package.json +13 -12
@@ -0,0 +1,270 @@
1
+ ---
2
+ name: kindgi-java-getting-started
3
+ description: >
4
+ Getting a Java Kindgi pack running: what a pack is, scaffolding one
5
+ (`kindgi init <name> --template=java`) or adding Kindgi to an existing
6
+ Maven app (`kindgi.config.json`, discovery under `kindgi` packages),
7
+ `./kindgiw dev`, the first agent run, connecting a real model, flows,
8
+ calling the Kindgi API from Java (`com.kindgi:kindgi-client`), and
9
+ building an image. Load this when a Maven project has no
10
+ `kindgi.config.json` yet and the user asks to "add Kindgi", "make an
11
+ agent", "set up a pack", or when you are orienting in a Java pack
12
+ (`kindgi.config.json` with `"language": "java"`) for the first time.
13
+ Authoring tools, guardrails, agents and flows is covered by
14
+ kindgi-java-authoring-tools, kindgi-java-authoring-guardrails,
15
+ kindgi-java-authoring-agents and kindgi-java-authoring-flows; models by
16
+ kindgi-authoring-providers.
17
+ type: core
18
+ library: "kindgi-pack (Java)"
19
+ version: "0.1.0"
20
+ sdk_version: "0.1.5-rc.0"
21
+ pack_languages: [java]
22
+ sources:
23
+ - sdks/java/kindgi-pack/README.md
24
+ - sdks/java/README.md
25
+ - site/src/content/docs/start/quickstart-java.md
26
+ ---
27
+
28
+ # Getting started with Kindgi in Java
29
+
30
+ > **Running `kindgi`:** the pack pins its CLI (`"cli"` in
31
+ > `kindgi.config.json`), as Maven's wrapper pins Maven. `./kindgiw` runs that
32
+ > version (`kindgiw.cmd` on Windows): through Node's `npx` when Node is
33
+ > installed, else `uvx`. So every `kindgi <command>` below runs as
34
+ > `./kindgiw <command>`, and `./kindgiw upgrade` moves the pin.
35
+ >
36
+ > **Preview:** Java and Scala support is tested and supported, but its API
37
+ > may still change in 0.1.6 without the usual deprecation period.
38
+
39
+ ## What a pack is
40
+
41
+ A **pack** is a project Kindgi indexes and runs. Its config is
42
+ `kindgi.config.json` (`"language": "java"`). Its primitives are
43
+ `public static final` fields of classes in four kinds of packages:
44
+
45
+ - **Tools** (`…/tools/…`, `Tool.define`): your Java code an agent or flow
46
+ calls.
47
+ - **Guardrails** (`…/guardrails/…`, `Guardrail.define`): checks over an
48
+ agent's turn.
49
+ - **Agents** (`…/agents/…`, `Agent.define`): data. Instructions, tools,
50
+ capabilities. The model runs in Kindgi.
51
+ - **Flows** (`…/flows/…`, `Flow.define`): data. Steps (tool or agent nodes)
52
+ and the edges between them.
53
+
54
+ Kindgi runs the tools and checks in the pack's own JVM (the pack service,
55
+ `com.kindgi:kindgi-pack`) and calls them over HTTP. Everything else runs in
56
+ the Kindgi runtime. In those packages, a helper is a package-private class,
57
+ a record, an enum or an interface. A public class that defines nothing is
58
+ an error, so a forgotten `static` can't drop a tool silently. Tests
59
+ (`*Test.java`, `*IT.java`, `src/test/`) are never primitives.
60
+
61
+ ## Scaffold a new pack
62
+
63
+ You need a JDK 17 or later (`JAVA_HOME`). Maven comes with the pack
64
+ (`./mvnw`).
65
+
66
+ ```sh
67
+ npx --yes @kindgi/cli@0.1 init my-pack --template=java # or: uvx --from "kindgi-cli>=0.1,<0.2" kindgi init …
68
+ cd my-pack
69
+ ./mvnw test # the template's tests: the tools, called directly
70
+ ./kindgiw dev # boots Kindgi locally and runs this pack, recompiling on save
71
+ ```
72
+
73
+ `kindgi dev` needs Docker and Postgres. It starts Postgres in Docker unless
74
+ `KINDGI_DATABASE_URL` points at yours. It checks the JDK (`JAVA_HOME`'s, or
75
+ `dev.javaHome` in `kindgi.config.json`) and Maven (the pack's `mvnw`, or
76
+ `dev.maven`, such as `["mvn", "-s", "settings.xml"]`). Maven compiles the
77
+ pack, the Java indexer reads it, and a save recompiles. A compile error is
78
+ reported as `file:line:col`, and the last good code keeps serving.
79
+ `MAVEN_ARGS` and `MAVEN_OPTS` reach Maven, never the pack.
80
+
81
+ ## Add Kindgi to an existing Maven app
82
+
83
+ In the app's directory (where its `pom.xml` is):
84
+
85
+ ```sh
86
+ npx --yes @kindgi/cli@0.1 init # --pack-id=<id> if the app's artifactId doesn't make one
87
+ ./kindgiw dev
88
+ ```
89
+
90
+ `init` writes `kindgi.config.json`:
91
+ - the pack id, from the app's `artifactId`, and its version;
92
+ - the CLI version it pins (`"cli"`, which `./kindgiw` runs, also written);
93
+ - discovery under `kindgi` packages (`src/main/java/**/kindgi/tools/**/*.java`
94
+ and so on), so the app's own `tools` packages are never taken for
95
+ Kindgi's.
96
+
97
+ It leaves `pom.xml` alone, and prints the `com.kindgi:kindgi-pack`
98
+ dependency to add (from Maven Central, at the CLI's version). It also adds
99
+ these skills and `.gitignore` entries. An app with both a `package.json` and
100
+ a `pom.xml` gets a TypeScript pack unless you pass `--template=java`.
101
+
102
+ A tool there is a class in a `kindgi.tools` package under the app's own
103
+ (`com.acme.app.kindgi.tools`), and calls the app's code directly. A class a
104
+ tool uses must be on the runtime classpath (`compile` or `runtime` scope,
105
+ not `test` or `provided`): the image copies the runtime dependencies only.
106
+ `kindgi dev` reads the app's `.env` and `.env.local`: keys already there
107
+ reach the tools as environment variables.
108
+
109
+ ## Layout of the template
110
+
111
+ ```
112
+ my-pack/
113
+ ├── kindgi.config.json # "language": "java", the pack's id and version, the CLI it pins
114
+ ├── pom.xml # com.kindgi:kindgi-pack, Java 17
115
+ ├── mvnw, .mvn/ # the Maven wrapper
116
+ ├── kindgiw, kindgiw.cmd # the Kindgi CLI wrapper
117
+ ├── src/main/java/mypack/
118
+ │ ├── tools/Echo.java, tools/Greet.java # Tool.define(...)
119
+ │ ├── guardrails/ResponseNotEmpty.java # Guardrail.define(...)
120
+ │ ├── agents/EchoAgent.java # Agent.define(...)
121
+ │ └── flows/EchoFlow.java # Flow.define(...)
122
+ ├── src/test/java/mypack/ToolsTest.java # the tools, called directly
123
+ └── .claude/skills/ # these skills (`./kindgiw skills sync` refreshes them)
124
+ ```
125
+
126
+ The package comes from the pack's id (`my-pack` becomes `mypack`).
127
+ `kindgi.config.json` also takes `discovery`, `dev`, `env`, `environments`,
128
+ `image` and `providers`.
129
+
130
+ ## First run
131
+
132
+ With `kindgi dev` running, from another terminal in the pack directory:
133
+
134
+ ```sh
135
+ ./kindgiw runs start --agent=my-pack.echo-agent --input='{"userMessage":"Ada"}'
136
+ ./kindgiw runs start --flow=my-pack.echo-flow --input='{"message":"Ada"}'
137
+ ```
138
+
139
+ The agent's answer comes from `dev-echo`, a **fallback** provider a new pack
140
+ gets: no model, no key. It calls the agent's first tool with
141
+ `{"message": <userMessage>}` and replies "⚠ dev-echo isn't a real model: …",
142
+ then "Tool responded: …". The turn carries the `fallback-provider` and
143
+ `dev-echo-not-a-model` warnings. It can't fill in any other tool's input,
144
+ and it can't give a typed answer. For a real model, store an LLM provider's
145
+ key and register its preset (Anthropic below; `./kindgiw providers presets`
146
+ lists OpenAI, Gemini, Groq and OpenRouter too):
147
+
148
+ ```sh
149
+ ./kindgiw secrets set ANTHROPIC_API_KEY --env=local --scope=tenant # no-echo prompt; writes .env.local
150
+ ./kindgiw providers register --preset=anthropic
151
+ ```
152
+
153
+ It takes over at the next turn. That registration is in this project's dev
154
+ database only. To have `kindgi dev` register it on every boot, in every
155
+ worktree and after `--reset`, declare it in `kindgi.config.json`:
156
+ `"providers": [{"preset": "anthropic"}]` (its key, `ANTHROPIC_API_KEY`, comes
157
+ from the env files). Details and other providers: `kindgi-authoring-providers`.
158
+
159
+ To see what Kindgi sees (the index), with no runtime:
160
+
161
+ ```sh
162
+ ./mvnw -q compile dependency:build-classpath -Dmdep.outputFile=target/classpath.txt
163
+ java -cp "target/classes:$(cat target/classpath.txt)" com.kindgi.pack.Main index --pack-dir .
164
+ ```
165
+
166
+ ## Flows
167
+
168
+ A flow is data: nodes and edges (`flow.schema.json`). A node's ref may be
169
+ the `Tool` itself:
170
+
171
+ ```java
172
+ public static final Flow FLOW = Flow.define("acme.ledger.record-flow")
173
+ .version("0.1.0")
174
+ .toolNode("record", RecordExpense.TOOL)
175
+ .edge("e-start", "$start", "record")
176
+ .edge("e-end", "record", "$end")
177
+ .build();
178
+ ```
179
+
180
+ A node gets the output of its single upstream node (the run input after
181
+ `$start`), or what its `inputMapping` says. Run one with
182
+ `./kindgiw runs start --flow=<id> --input='{…}'`. For branches, loops and
183
+ agent steps, see `kindgi-java-authoring-flows`.
184
+
185
+ ## Calling Kindgi from Java
186
+
187
+ `com.kindgi:kindgi-client` (on Maven Central, at the same version as the
188
+ CLI) covers the whole API, with typed models and errors:
189
+
190
+ ```java
191
+ Kindgi client = Kindgi.create(); // KINDGI_API_URL + KINDGI_API_TOKEN; in dev, the running kindgi dev
192
+ Run run = client.runs().start(StartRunBody.WithAgent.builder()
193
+ .agent("my-pack.echo-agent")
194
+ .input(Map.of("userMessage", "Ada"))
195
+ .build());
196
+ try (EventStream<RunEvent> events = client.runs().follow(run.id())) {
197
+ for (RunEvent event : events) System.out.println(event.kind());
198
+ }
199
+ ```
200
+
201
+ The methods follow the API's operations: `approvals.reviewers.list` is
202
+ `client.approvals().reviewers().list()`. `client.async()` has the same ones,
203
+ answering `CompletableFuture`s. A refused call throws a typed
204
+ `KindgiApiException` (`NotFoundException`, …). The client shades its own
205
+ Jackson, so the app's Jackson is left alone. In production it never reads
206
+ `.kindgirc.json`: set `KINDGI_API_URL` and `KINDGI_API_TOKEN`.
207
+
208
+ ## Your app and Kindgi's data
209
+
210
+ When the app keeps something a run did (a ticket a flow triaged, an answer
211
+ an agent gave), its own row stores the run's id, in a column such as
212
+ `kindgi_run_id`. The app reads the rest through the API, server side:
213
+
214
+ - **Status, output, timing:** `client.runs().get(runId)`.
215
+ - **The audit, step by step:** `client.runs().journal(runId)`.
216
+ - **What it cost:** `client.cost().records().list(…)`, filtered by the run.
217
+ - **When a run finished:** the `run.finished` webhook, not polling.
218
+
219
+ Show it in the app's own UI. **Never:**
220
+
221
+ - **query Kindgi's database**, even on the app's own Postgres server, or map
222
+ its tables in JPA. Its schema is private and changes with every release,
223
+ row-level security guards every tenant query, and a runtime Kindgi hosts
224
+ gives no database access.
225
+ - **link users to Kindgi's console**, or any Kindgi UI, for this data.
226
+
227
+ Docs: https://docs.kindgi.com/v0.1/guides/runs/show-runs-in-your-app/
228
+
229
+ ## Build an image
230
+
231
+ `./kindgiw build --env=<name>` builds the pack's image for an
232
+ `environments.<name>` block of `kindgi.config.json`; `--local` builds it with
233
+ this machine's Docker. Maven compiles the pack in a pinned Maven + JDK 17
234
+ image, fetching kindgi-pack from Maven Central. The index is built in the
235
+ image, and the pack service runs on a JRE 17 as its entrypoint, as user
236
+ 65532.
237
+
238
+ Debian packages the code needs are declared in `kindgi.config.json`, and the
239
+ image installs them: `"image": {"systemPackages": ["tesseract-ocr"]}`
240
+ (names, or `name=version`). So are the variables the code reads, names only:
241
+ `"env": {"required": ["DATABASE_URL"], "optional": ["SENTRY_DSN"]}`. A
242
+ deployed pack service missing a required one isn't ready, and its `/readyz`
243
+ names it.
244
+
245
+ ## Two things need the human
246
+
247
+ - **The pack id and version** in `kindgi.config.json`. The id prefixes every
248
+ primitive (`<pack-id>.<name>`): pick it once.
249
+ - **Model credentials.** Ask for the key; never invent or hard-code one.
250
+
251
+ ## Next
252
+
253
+ - A tool: `kindgi-java-authoring-tools`.
254
+ - A guardrail: `kindgi-java-authoring-guardrails`.
255
+ - An agent: `kindgi-java-authoring-agents`.
256
+ - A flow: `kindgi-java-authoring-flows`.
257
+ - A real model: `kindgi-authoring-providers`.
258
+ - An external resource (a database) for the coding agent:
259
+ `kindgi-authoring-mcp-servers`.
260
+
261
+ ## Keeping skills up to date
262
+
263
+ `./kindgiw skills sync` refreshes `.claude/skills/` from the CLI's copy
264
+ (local edits are kept unless `--force`). `kindgi dev` says when they are out
265
+ of date.
266
+
267
+ ## When the framework itself is the problem
268
+
269
+ If the bug is in Kindgi or kindgi-pack and not in the pack's code, load
270
+ `kindgi-framework-feedback` and file it with `./kindgiw feedback write`.
@@ -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.4"
19
- sdk_version: "0.1.4"
18
+ version: "0.1.5"
19
+ sdk_version: "0.1.5-rc.0"
20
20
  pack_languages: [python]
21
21
  sources:
22
22
  - sdks/python/src/kindgi/pack/define.py
@@ -158,7 +158,25 @@ brief_writer = Agent(
158
158
  the call. Default kinds are `invalid-arguments` and `unknown-tool`
159
159
  (nothing ran); add `tool-error` only when retrying the tool is safe.
160
160
  Each retry costs a step.
161
- - **`retrieval`** — memory retrieval declarations; usually `[]`.
161
+ - **`retrieval`** — what the agent reads from memory before each turn;
162
+ empty = no memory. Each intent is a dict with the API's keys:
163
+ `{"types": ["acme.preference"], "scope": "same-user", "mode": "both",
164
+ "limit": 5}`. `scope` is `same-user`, `same-conversation`,
165
+ `same-project` or `tenant`; `mode` absent (newest first), `keyword`,
166
+ `semantic` or `both`. Facts reach the model as data in a `<memory>`
167
+ block, never as instructions. `semantic`/`both` need embeddings on the
168
+ runtime (`KINDGI_MEMORY_EMBEDDINGS`); without them a `semantic` intent
169
+ fails the turn (`semantic-unavailable`). `{"source": "conversations",
170
+ "scope": "same-user"}` recalls this agent's earlier conversations: the
171
+ people's own words only, unless `"roles": ["user", "agent"]`.
172
+ - **`memory`** — `{"remember": {"types": ["acme.preference"], "scope":
173
+ "same-user", "keepDays": 30}}` gives the turn the built-in tool
174
+ `kindgi_remember` (name it exactly so in the instructions). The model
175
+ picks type, text, `key` and expiry, never the scope; a fact wider than
176
+ one person, or instruction-like text, waits for a person's approval.
177
+ Use a model with reliable tool calling. `{"instructionTypes":
178
+ ["acme.policy"]}` makes a retrieved, verified fact of those types an
179
+ instruction. See https://docs.kindgi.com/v0.1/guides/agents/give-an-agent-memory/.
162
180
 
163
181
  ## Which model answers
164
182
 
@@ -17,7 +17,7 @@ description: >
17
17
  type: core
18
18
  library: "kindgi (Python)"
19
19
  version: "0.1.2"
20
- sdk_version: "0.1.4"
20
+ sdk_version: "0.1.5-rc.0"
21
21
  pack_languages: [python]
22
22
  sources:
23
23
  - sdks/python/src/kindgi/pack/define.py
@@ -14,8 +14,8 @@ description: >
14
14
  kindgi-python-authoring-tools.
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
- version: "0.1.3"
18
- sdk_version: "0.1.4"
17
+ version: "0.1.4"
18
+ sdk_version: "0.1.5-rc.0"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/src/kindgi/pack/define.py
@@ -121,7 +121,14 @@ def no_fabricated_quotes(config: Config, trace: RunTrace) -> CheckResult:
121
121
  - **`config`** — the values the check runs with (above); **`config_type`**
122
122
  — the config's type when the check's first parameter isn't annotated
123
123
  with it.
124
- - **`name`** — a display name. **`check_id`** — defaults to the id.
124
+ - **`name`** — a display name. **`check_id`** — defaults to the id. It
125
+ can't be a built-in check's id (`must-cite`, `never-call-tool`,
126
+ `max-tool-calls`, `output-matches`, `tool-order`, `required-substring`,
127
+ `forbidden-substring`): a pack can't replace a built-in, and the
128
+ decorator raises `DefinitionError`. Name yours
129
+ `<pack>.checks.<name>`. A Python pack can't use a built-in check yet,
130
+ since `@guardrail` always decorates a check function: write the rule
131
+ as your own check.
125
132
  - `sandbox=`, `limits=`, `network=` are recorded in the index.
126
133
 
127
134
  ## Testing
@@ -15,7 +15,7 @@ description: >
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
17
  version: "0.1.2"
18
- sdk_version: "0.1.4"
18
+ sdk_version: "0.1.5-rc.0"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/src/kindgi/pack/define.py
@@ -116,7 +116,11 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
116
116
  or wait with `ctx.cancellation.wait(timeout)` between slow steps.
117
117
  - `ctx.secrets` — the secrets the tool declares in `needs_spec`,
118
118
  resolved for the call's tenant (below).
119
- - `ctx.env`, `ctx.config` — **reserved, empty today**.
119
+ - `ctx.env` — the env values the tool declares in `needs_spec`, resolved
120
+ for the call: its project's value, else its org's, else the tenant's
121
+ (`kindgi env set NAME <value> --scope=project:<id> --env=<env>`).
122
+ Strings, and not secret. Empty from an older runtime.
123
+ - `ctx.config` — **reserved, empty today**.
120
124
 
121
125
  ## Configuration and secrets
122
126
 
@@ -140,6 +144,33 @@ fails the call, naming the secret, when it is missing or doesn't match.
140
144
  Every declared secret is required. In a test, pass them:
141
145
  `ToolContext.for_test(secrets={"CITATOR_KEY": "…"})`.
142
146
 
147
+ A value that differs per tenant, org or project but isn't secret (a base URL, a region, an account id) is an **env value**: declared in `needs_spec`, read from `ctx.env`:
148
+
149
+ ```python
150
+ @tool(
151
+ id="acme.find-order",
152
+ mutating=False,
153
+ needs_spec={
154
+ "env": {
155
+ "ORDERS_BASE_URL": {"type": "string", "pattern": "^https://"},
156
+ "ORDERS_REGION": {"type": "string", "enum": ["eu", "us"], "default": "eu"},
157
+ }
158
+ },
159
+ )
160
+ def find_order(lookup: Lookup, ctx: ToolContext) -> Found:
161
+ """…"""
162
+ return Found(url=f"{ctx.env['ORDERS_BASE_URL']}/{ctx.env['ORDERS_REGION']}/orders/{lookup.order_id}")
163
+ ```
164
+
165
+ - **Which value a call gets:** its project's, else its org's, else the tenant's, in the runtime's env; a schema `default` makes a name optional. The values a call used are recorded with it, so a retry or a resume sees the same ones.
166
+ - **Setting them:** `kindgi env set ORDERS_REGION us --scope=project:<project-id> --env=local` (or `--scope=tenant`, for every project). Changing a value that's already set takes `--force`.
167
+ - **A declared value nobody set** stops the call before the tool runs. For a tool `acme-orders.needs-account` that declares `ACME_ACCOUNT_ID`, the message reads:
168
+ ```text
169
+ precondition-failed: Tool "acme-orders.needs-account" was not run: env-value-missing: tool "acme-orders.needs-account" needs env value "ACME_ACCOUNT_ID" in env "local", and none is set for project e889c1f5-eae7-45dc-8669-5bd029a5d85c, its org, or the tenant. Set it: kindgi env set ACME_ACCOUNT_ID <value> --scope=project:e889c1f5-eae7-45dc-8669-5bd029a5d85c --env=local (or --scope=tenant, for every project)
170
+ ```
171
+ - **Not secret:** env values are recorded with each run that uses them and shown in its journal. A credential is a secret, never an env value.
172
+ - **In a test:** `ToolContext.for_test(env={"ORDERS_BASE_URL": "…"})`.
173
+
143
174
  Everything else comes from the process environment: `os.environ["CITATOR_URL"]`.
144
175
  The pack service runs with the pack's environment — in `kindgi dev`
145
176
  that is the pack's `.env` and `.env.local` (or `[tool.kindgi.dev]
@@ -274,9 +305,9 @@ removed field, a narrower type — not on every save.
274
305
  ## Common mistakes
275
306
 
276
307
  1. **Copying the sample tool's shape without asking what the tool should do.**
277
- 2. **Reading `ctx.env` / `ctx.config`, or an undeclared `ctx.secrets` name.**
278
- The first two are empty, and `ctx.secrets` holds only what `needs_spec`
279
- declares; use `os.environ` for the rest.
308
+ 2. **Reading `ctx.config`, or an undeclared `ctx.env` or `ctx.secrets` name.**
309
+ `ctx.config` is empty, and `ctx.env` and `ctx.secrets` hold only what
310
+ `needs_spec` declares; use `os.environ` for the rest.
280
311
  3. **A non-object input** (`def f(n: int)`): the input must be a model,
281
312
  TypedDict, dataclass or object schema.
282
313
  4. **No docstring and no `description=`**, or an unannotated input or
@@ -15,7 +15,7 @@ description: >
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
17
  version: "0.1.7"
18
- sdk_version: "0.1.4"
18
+ sdk_version: "0.1.5-rc.0"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/README.md
@@ -189,7 +189,7 @@ from kindgi.client import Kindgi
189
189
  client = Kindgi() # KINDGI_API_URL + KINDGI_API_TOKEN, or Kindgi(url, token=…)
190
190
  run = client.runs.start(agent="my-pack.echo-agent", input={"userMessage": "Ada"})
191
191
  print(run.status, run.output["response"]["content"])
192
- for event in client.runs.stream(str(run.id)):
192
+ for event in client.runs.follow(run.id): # to the run's end, reconnecting
193
193
  print(event.kind)
194
194
  ```
195
195
 
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: kindgi-scala-authoring-agents
3
+ description: >
4
+ Covers writing agents for a Kindgi pack in Scala (`kindgi-pack-scala`,
5
+ `com.kindgi.pack.scaladsl`): `Agent(id)` as a `val` of an object named like
6
+ its file, wiring tools (`Tool` vals or an id with a version range) and
7
+ guardrails, capabilities and model choice (preferredProvider /
8
+ preferredModel), conversation policy, turn budgets, prompt parameters, a
9
+ typed answer from a case class (`output[T]`), and tool-error retries, all
10
+ as data with Scala maps. Load this whenever you are authoring or editing
11
+ code in a Scala pack's agents packages (a pack whose `kindgi.config.json`
12
+ says `"language": "scala"`), defining an agent, or when the user asks to
13
+ add, change or refactor one. Scala tools are covered by
14
+ kindgi-scala-authoring-tools, Scala guardrails by
15
+ kindgi-scala-authoring-guardrails, connecting a real model by
16
+ kindgi-authoring-providers.
17
+ type: core
18
+ library: "kindgi-pack-scala"
19
+ version: "0.1.0"
20
+ sdk_version: "0.1.5-rc.0"
21
+ pack_languages: [scala]
22
+ sources:
23
+ - sdks/scala/README.md
24
+ - sdks/scala/kindgi-pack-scala/src/main/scala/com/kindgi/pack/scaladsl/Agent.scala
25
+ - packages/specs/schemas/agent.schema.json
26
+ - packages/specs/schemas/pack-index.schema.json
27
+ ---
28
+
29
+ # Authoring Kindgi agents in Scala
30
+
31
+ > **Running `kindgi`:** the pack pins its CLI (`"cli"` in
32
+ > `kindgi.config.json`), and `./kindgiw` runs that version, so every
33
+ > `kindgi <command>` below runs as `./kindgiw <command>`.
34
+ >
35
+ > Scala support is in preview: tested and supported, but the API may still
36
+ > change in 0.1.6 without the usual deprecation period.
37
+
38
+ An **agent** is a versioned, model-driven orchestrator. It's made of:
39
+ - instructions (a prompt template);
40
+ - the tools it may call;
41
+ - the capabilities its model needs;
42
+ - guardrails that gate its answer;
43
+ - optionally, a conversation policy.
44
+
45
+ In a Scala pack it is **data**: a `val` of type `Agent` in an object named
46
+ like its file, in an `agents` package. The model runs in the Kindgi runtime,
47
+ not in your JVM. Your Scala code runs only inside the agent's tools and
48
+ guardrail checks.
49
+
50
+ ## Ask before building
51
+
52
+ "Add an agent" is a conversation opener, not a ticket. Before writing a
53
+ file, ask:
54
+
55
+ - **What should the agent do?** The purpose drives everything else.
56
+ - **Which tools does it need?** New ones, or existing ones?
57
+ - **Multi-turn or one-shot?** History changes the shape.
58
+ - **Any rules it must respect?** Those become guardrails.
59
+
60
+ The pack's sample agent proves the runtime works end to end. It is not the
61
+ shape to imitate unless the user asks for that.
62
+
63
+ ## An agent
64
+
65
+ ```scala
66
+ // src/main/scala/acme/agents/BriefWriter.scala
67
+ package acme.agents
68
+
69
+ import acme.guardrails.ResponseNotEmpty
70
+ import acme.tools.Echo
71
+ import com.kindgi.pack.scaladsl._
72
+
73
+ /** acme.brief-writer: drafts a brief's argument from the case facts. */
74
+ object BriefWriter {
75
+ /** The typed answer: the final message must be JSON of this shape. */
76
+ final case class Brief(argument: String, citations: List[String])
77
+
78
+ val agent: Agent = Agent("acme.brief-writer")
79
+ .version("0.1.0")
80
+ .name("Brief Writer")
81
+ .description("Drafts appellate briefs from a case file; cites precedents.")
82
+ .instructions(
83
+ "You are drafting a brief in {{ jurisdiction }}. The user gives the case facts; you write " +
84
+ "a Section IV argument citing at least two precedents. Check every cite with the echo tool " +
85
+ "before using it. Never invent one.")
86
+ .capability(Map("needs" -> List(Map("feature" -> "tool-use"))))
87
+ .tool(Echo.tool)
88
+ .guardrail(ResponseNotEmpty.guardrail)
89
+ .set("parameters", List(Map("name" -> "jurisdiction", "type" -> "string", "required" -> true)))
90
+ .set("conversationPolicy", Map("historyLimit" -> 20))
91
+ .set("budget", Map("maxSteps" -> 8, "maxCostUsd" -> 0.5, "maxWallMs" -> 60000))
92
+ .set("toolErrors", Map("maxRetries" -> 1, "retryOn" -> List("invalid-arguments", "unknown-tool")))
93
+ .output[Brief]
94
+ .build()
95
+ }
96
+ ```
97
+
98
+ - Tools and guardrails are the pack's own vals, imported like any member:
99
+ `.tool(Echo.tool)`, `.guardrail(ResponseNotEmpty.guardrail)`.
100
+ - **`build()` needs a version, a name and instructions.** Anything missing
101
+ is an error where the agent is defined, and the indexer reports it with
102
+ the file.
103
+ - **Every other field is `set(field, value)`, keyed as on the wire,** with
104
+ Scala maps and lists: the field and its maps are camelCase
105
+ (`conversationPolicy`, `maxSteps`, `historyLimit`), as `agent.schema.json`
106
+ names them. The indexer checks each agent against the pack index's
107
+ schema, and `kindgi dev` reports a mistake with its file.
108
+ - An object may hold several agents, each in its own `val`.
109
+
110
+ ## Field by field
111
+
112
+ - **`id`:** `<pack-id>.<agent-name>`, kebab-case, dot-namespaced.
113
+ - **`version`:** an exact semver. Conversations pin the version they started
114
+ on.
115
+ - **`name`, `description`**, and `set("tags", List(…))`: for people and
116
+ listings. The model never sees the description.
117
+ - **`instructions`:** a LiquidJS template. `{{ variable }}` comes from
118
+ `parameters` or the runtime's own variables (`today`, `now`, `agent.*`,
119
+ `conversation.*`). It's rendered strictly: an unknown variable fails the
120
+ turn. Write it as a brief for a capable colleague: what to do, which tools
121
+ to prefer, what to refuse, the quality bar. Name a tool by what it does
122
+ ("the verify-citation tool"), never by its dotted id. The model sees ids in
123
+ its provider's form (`acme__verify-citation` for Anthropic and
124
+ OpenAI-compatible models), and a dotted id in the instructions can make it
125
+ call a name it wasn't given. `instructions(Map("prompt" -> …, "version" -> …))`
126
+ references a registered prompt block instead.
127
+ - **`capability(Map(…))`:** what the model must support, such as
128
+ `Map("needs" -> List(Map("feature" -> "tool-use")))`. Call it once per
129
+ capability. The turn routes its first capability to pick a provider and
130
+ model; with none declared, the turn fails.
131
+ - **`tool(tool)`:** pins that tool's version (its own, or the pack's).
132
+ **`tool(id, range)`** is a tool of another pack, with a semver **range**
133
+ (`"^1.0.0"`); the highest active matching version is picked at turn
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
137
+ guardrail fails the turn.
138
+ - **`set("parameters", List(Map("name" -> …, "type" -> …, "required" -> …)))`:**
139
+ inputs the caller supplies per run. They fill `{{ … }}` in the
140
+ instructions.
141
+ - **`set("preferredProvider", "anthropic")`, `set("preferredModel", "claude-haiku-4-5")`:**
142
+ soft hints. The router prefers them when they satisfy the capabilities.
143
+ To *require* a model, put it in the capability:
144
+ `Map("needs" -> List(Map("feature" -> "tool-use"), Map("models" -> Map("allow" -> List("claude-haiku-4-5")))))`.
145
+ - **`set("conversationPolicy", …)`:** `historyLimit` caps the prior messages
146
+ loaded, and `hitl` configures approval gates. Absent, the turn loads the
147
+ full history with no gates. A tenant's `hitl` policy can tighten the gates
148
+ (a shorter timeout, a higher reviewer role, stricter per tool), never
149
+ loosen them.
150
+ - **`set("budget", …)`:** per turn. `maxSteps` counts model calls (default
151
+ 8); `maxCostUsd`; `maxWallMs` (default 120 000). Exceeding the steps or the
152
+ cost fails the turn (`budget-exceeded`); running out of wall time aborts
153
+ it. Leave room for real models: a turn with tool calls can take tens of
154
+ seconds.
155
+ - **`output[T]`:** a typed answer, with its schema derived from the case
156
+ class. The final answer must be JSON matching it. A wrong one goes back to
157
+ the model with the problems (`maxRepairs`, default 1), and then the turn
158
+ fails (`output-schema-violation`). For `maxRepairs` or a schema of your
159
+ own, use `set("output", Map("schema" -> …, "maxRepairs" -> 2))`. The parsed
160
+ answer is the turn result's `output`. In a flow it is
161
+ `nodeOutputs.<step>.output.<field>`.
162
+ - **`set("toolErrors", …)`:** `maxRetries` and `retryOn`. A failed tool call
163
+ goes back to the model as the call's result, so it can fix the call. The
164
+ default kinds are `invalid-arguments` and `unknown-tool` (nothing ran). Add
165
+ `tool-error` only when retrying the tool is safe. Each retry costs a step.
166
+
167
+ ## Which model answers
168
+
169
+ Agents run on a registered model provider: the router picks one whose
170
+ models satisfy the capabilities. `kindgi dev` gives a new pack `dev-echo`, a
171
+ **fallback** that answers only while no other provider fits. It calls the
172
+ first tool and replies "⚠ dev-echo isn't a real model: …", then "Tool
173
+ responded: …". The turn carries the `fallback-provider` and
174
+ `dev-echo-not-a-model` warnings. dev-echo can't fill in any other tool
175
+ input, and can't give a typed answer: an agent with an output type fails
176
+ with `output-schema-violation` until a real model is registered. To register
177
+ one, see `kindgi-authoring-providers` (`./kindgiw providers register --preset=anthropic`,
178
+ or `"providers": [{"preset": "anthropic"}]` in `kindgi.config.json`).
179
+
180
+ ## Iterating
181
+
182
+ Save the file: `kindgi dev` recompiles through sbt's server, re-indexes, and
183
+ the next run uses it, with no restart. Bump `version` when you break what
184
+ callers rely on (a removed parameter, an incompatible output), not on every
185
+ save.
186
+
187
+ Run an agent from another terminal in the pack directory:
188
+
189
+ ```sh
190
+ ./kindgiw runs start --agent=acme.brief-writer --input='{"userMessage":"…","parameters":{"jurisdiction":"US"}}'
191
+ ```
192
+
193
+ ## Common mistakes
194
+
195
+ 1. **Building an agent without asking what it should do.** Copying the
196
+ sample's shape answers the wrong question.
197
+ 2. **No `capability(…)`.** The turn can't pick a model.
198
+ 3. **Scala names inside the maps.** `set("budget", Map("max_steps" -> 4))`
199
+ isn't a budget: the keys are the wire's camelCase (`maxSteps`,
200
+ `historyLimit`, `maxRetries`).
201
+ 4. **An unregistered guardrail id.** Pass the `Guardrail` val, or make sure
202
+ the id is one the tenant has.
203
+ 5. **`{{ variable }}` not in `parameters`.** The turn fails when the
204
+ instructions render.
205
+ 6. **An agent as a `def` or a `lazy val`.** It's a file error: make it a
206
+ `val`.
207
+ 7. **A tight `maxWallMs` with a real model.** 15 s aborts real turns under
208
+ load; 60 s is a safer start.
209
+ 8. **Expecting dev-echo to give a typed answer.** It can't: register a real
210
+ model first.
211
+
212
+ ## When the framework itself is the problem
213
+
214
+ If the bug is in Kindgi, kindgi-pack or the Scala layer (the index dropping
215
+ a field, a misleading error, the router picking the wrong model) and not in
216
+ the pack's code, load `kindgi-framework-feedback` and file it with
217
+ `./kindgiw feedback write`.