@kindgi/cli 0.1.4-rc.5 → 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.
- package/README.md +16 -10
- package/dist/build/defaults.d.ts +3 -1
- package/dist/build/defaults.d.ts.map +1 -1
- package/dist/build/defaults.js +44 -1
- package/dist/build/defaults.js.map +1 -1
- package/dist/build/java-image.d.ts +31 -0
- package/dist/build/java-image.d.ts.map +1 -0
- package/dist/build/java-image.js +146 -0
- package/dist/build/java-image.js.map +1 -0
- package/dist/build/pack-root.d.ts +1 -31
- package/dist/build/pack-root.d.ts.map +1 -1
- package/dist/build/pack-root.js +22 -2
- package/dist/build/pack-root.js.map +1 -1
- package/dist/build/runners.d.ts +44 -0
- package/dist/build/runners.d.ts.map +1 -1
- package/dist/build/scala-image.d.ts +21 -0
- package/dist/build/scala-image.d.ts.map +1 -0
- package/dist/build/scala-image.js +150 -0
- package/dist/build/scala-image.js.map +1 -0
- package/dist/cli-pin.d.ts +16 -0
- package/dist/cli-pin.d.ts.map +1 -0
- package/dist/cli-pin.js +66 -0
- package/dist/cli-pin.js.map +1 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +9 -8
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/approvals.d.ts.map +1 -1
- package/dist/commands/approvals.js +30 -4
- package/dist/commands/approvals.js.map +1 -1
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +100 -37
- package/dist/commands/artifacts.js.map +1 -1
- package/dist/commands/auth.js +2 -2
- package/dist/commands/blocks.d.ts.map +1 -1
- package/dist/commands/blocks.js +5 -4
- package/dist/commands/blocks.js.map +1 -1
- package/dist/commands/build.d.ts +10 -2
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +109 -16
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/capabilities.d.ts.map +1 -1
- package/dist/commands/capabilities.js +37 -10
- package/dist/commands/capabilities.js.map +1 -1
- package/dist/commands/console.d.ts +21 -0
- package/dist/commands/console.d.ts.map +1 -0
- package/dist/commands/console.js +87 -0
- package/dist/commands/console.js.map +1 -0
- package/dist/commands/conversations.d.ts.map +1 -1
- package/dist/commands/conversations.js +13 -2
- package/dist/commands/conversations.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +2 -2
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +11 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +211 -39
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts +18 -5
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +421 -21
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env-scoped.d.ts +44 -0
- package/dist/commands/env-scoped.d.ts.map +1 -0
- package/dist/commands/env-scoped.js +222 -0
- package/dist/commands/env-scoped.js.map +1 -0
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +85 -123
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/eval-runs.d.ts +9 -0
- package/dist/commands/eval-runs.d.ts.map +1 -1
- package/dist/commands/eval-runs.js +20 -19
- package/dist/commands/eval-runs.js.map +1 -1
- package/dist/commands/eval-suites.d.ts.map +1 -1
- package/dist/commands/eval-suites.js +16 -8
- package/dist/commands/eval-suites.js.map +1 -1
- package/dist/commands/exports.d.ts +3 -0
- package/dist/commands/exports.d.ts.map +1 -0
- package/dist/commands/exports.js +82 -0
- package/dist/commands/exports.js.map +1 -0
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +6 -5
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/flows.d.ts.map +1 -1
- package/dist/commands/flows.js +2 -1
- package/dist/commands/flows.js.map +1 -1
- package/dist/commands/gate-policies.d.ts.map +1 -1
- package/dist/commands/gate-policies.js +2 -1
- package/dist/commands/gate-policies.js.map +1 -1
- package/dist/commands/guardrails.d.ts.map +1 -1
- package/dist/commands/guardrails.js +3 -2
- package/dist/commands/guardrails.js.map +1 -1
- package/dist/commands/helpers.js +5 -5
- package/dist/commands/helpers.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +14 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +254 -18
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/judge-classes.d.ts.map +1 -1
- package/dist/commands/judge-classes.js +11 -10
- package/dist/commands/judge-classes.js.map +1 -1
- package/dist/commands/judgments.d.ts.map +1 -1
- package/dist/commands/judgments.js +7 -6
- package/dist/commands/judgments.js.map +1 -1
- package/dist/commands/key.js +4 -4
- package/dist/commands/memory.d.ts.map +1 -1
- package/dist/commands/memory.js +277 -25
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/people.d.ts +3 -0
- package/dist/commands/people.d.ts.map +1 -0
- package/dist/commands/people.js +166 -0
- package/dist/commands/people.js.map +1 -0
- package/dist/commands/proposals.d.ts.map +1 -1
- package/dist/commands/proposals.js +390 -69
- package/dist/commands/proposals.js.map +1 -1
- package/dist/commands/provenance.d.ts.map +1 -1
- package/dist/commands/provenance.js +6 -7
- package/dist/commands/provenance.js.map +1 -1
- package/dist/commands/providers.d.ts.map +1 -1
- package/dist/commands/providers.js +46 -7
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/reviewers.d.ts.map +1 -1
- package/dist/commands/reviewers.js +3 -2
- package/dist/commands/reviewers.js.map +1 -1
- package/dist/commands/runs.d.ts.map +1 -1
- package/dist/commands/runs.js +24 -14
- package/dist/commands/runs.js.map +1 -1
- package/dist/commands/schedules.d.ts +3 -0
- package/dist/commands/schedules.d.ts.map +1 -0
- package/dist/commands/schedules.js +275 -0
- package/dist/commands/schedules.js.map +1 -0
- package/dist/commands/secrets.d.ts.map +1 -1
- package/dist/commands/secrets.js +10 -11
- package/dist/commands/secrets.js.map +1 -1
- package/dist/commands/service-accounts.d.ts +3 -0
- package/dist/commands/service-accounts.d.ts.map +1 -0
- package/dist/commands/service-accounts.js +175 -0
- package/dist/commands/service-accounts.js.map +1 -0
- package/dist/commands/skills.d.ts +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +11 -4
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/sso.d.ts +6 -0
- package/dist/commands/sso.d.ts.map +1 -0
- package/dist/commands/sso.js +318 -0
- package/dist/commands/sso.js.map +1 -0
- package/dist/commands/tokens.d.ts +11 -0
- package/dist/commands/tokens.d.ts.map +1 -1
- package/dist/commands/tokens.js +144 -11
- package/dist/commands/tokens.js.map +1 -1
- package/dist/commands/tools.d.ts.map +1 -1
- package/dist/commands/tools.js +4 -3
- package/dist/commands/tools.js.map +1 -1
- package/dist/commands/unwired.d.ts.map +1 -1
- package/dist/commands/unwired.js +1 -30
- package/dist/commands/unwired.js.map +1 -1
- package/dist/commands/upgrade.d.ts +11 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +160 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -0
- package/dist/context.js.map +1 -1
- package/dist/dev/defaults.d.ts +28 -11
- package/dist/dev/defaults.d.ts.map +1 -1
- package/dist/dev/defaults.js +114 -35
- package/dist/dev/defaults.js.map +1 -1
- package/dist/dev/google-credentials.d.ts +50 -0
- package/dist/dev/google-credentials.d.ts.map +1 -0
- package/dist/dev/google-credentials.js +157 -0
- package/dist/dev/google-credentials.js.map +1 -0
- package/dist/dev/java-builder.d.ts +56 -0
- package/dist/dev/java-builder.d.ts.map +1 -0
- package/dist/dev/java-builder.js +204 -0
- package/dist/dev/java-builder.js.map +1 -0
- package/dist/dev/jvm-run-files.d.ts +29 -0
- package/dist/dev/jvm-run-files.d.ts.map +1 -0
- package/dist/dev/jvm-run-files.js +94 -0
- package/dist/dev/jvm-run-files.js.map +1 -0
- package/dist/dev/lines.d.ts +13 -0
- package/dist/dev/lines.d.ts.map +1 -0
- package/dist/dev/lines.js +24 -0
- package/dist/dev/lines.js.map +1 -0
- package/dist/dev/log-view.d.ts +116 -0
- package/dist/dev/log-view.d.ts.map +1 -0
- package/dist/dev/log-view.js +233 -0
- package/dist/dev/log-view.js.map +1 -0
- package/dist/dev/pack-code.d.ts +79 -4
- package/dist/dev/pack-code.d.ts.map +1 -1
- package/dist/dev/pack-code.js +262 -3
- package/dist/dev/pack-code.js.map +1 -1
- package/dist/dev/pack-env.d.ts.map +1 -1
- package/dist/dev/pack-env.js +4 -0
- package/dist/dev/pack-env.js.map +1 -1
- package/dist/dev/pack-service.d.ts +11 -1
- package/dist/dev/pack-service.d.ts.map +1 -1
- package/dist/dev/pack-service.js +56 -20
- package/dist/dev/pack-service.js.map +1 -1
- package/dist/dev/paths.d.ts +6 -0
- package/dist/dev/paths.d.ts.map +1 -1
- package/dist/dev/paths.js +8 -0
- package/dist/dev/paths.js.map +1 -1
- package/dist/dev/project-database.js +1 -1
- package/dist/dev/project-database.js.map +1 -1
- package/dist/dev/runners.d.ts +35 -9
- package/dist/dev/runners.d.ts.map +1 -1
- package/dist/dev/runtime-container.d.ts +10 -2
- package/dist/dev/runtime-container.d.ts.map +1 -1
- package/dist/dev/runtime-container.js +48 -20
- package/dist/dev/runtime-container.js.map +1 -1
- package/dist/dev/runtime-env.d.ts +10 -0
- package/dist/dev/runtime-env.d.ts.map +1 -1
- package/dist/dev/runtime-env.js +8 -4
- package/dist/dev/runtime-env.js.map +1 -1
- package/dist/dev/runtime-image.d.ts +1 -1
- package/dist/dev/runtime-image.js +1 -1
- package/dist/dev/scala-builder.d.ts +72 -0
- package/dist/dev/scala-builder.d.ts.map +1 -0
- package/dist/dev/scala-builder.js +347 -0
- package/dist/dev/scala-builder.js.map +1 -0
- package/dist/env/project-env.d.ts.map +1 -1
- package/dist/env/project-env.js +3 -1
- package/dist/env/project-env.js.map +1 -1
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -1
- package/dist/help.d.ts +14 -0
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +55 -0
- package/dist/help.js.map +1 -1
- package/dist/init/dependency-specs.d.ts +26 -0
- package/dist/init/dependency-specs.d.ts.map +1 -1
- package/dist/init/dependency-specs.js +38 -0
- package/dist/init/dependency-specs.js.map +1 -1
- package/dist/init/java-augment.d.ts +24 -0
- package/dist/init/java-augment.d.ts.map +1 -0
- package/dist/init/java-augment.js +198 -0
- package/dist/init/java-augment.js.map +1 -0
- package/dist/init/mode-detect.d.ts +2 -2
- package/dist/init/mode-detect.d.ts.map +1 -1
- package/dist/init/mode-detect.js +12 -1
- package/dist/init/mode-detect.js.map +1 -1
- package/dist/init/scala-augment.d.ts +23 -0
- package/dist/init/scala-augment.d.ts.map +1 -0
- package/dist/init/scala-augment.js +213 -0
- package/dist/init/scala-augment.js.map +1 -0
- package/dist/init/template-files.d.ts +40 -2
- package/dist/init/template-files.d.ts.map +1 -1
- package/dist/init/template-files.js +56 -5
- package/dist/init/template-files.js.map +1 -1
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +30 -4
- package/dist/main.js.map +1 -1
- package/dist/open-url.d.ts +15 -0
- package/dist/open-url.d.ts.map +1 -0
- package/dist/open-url.js +41 -0
- package/dist/open-url.js.map +1 -0
- package/dist/package-manager.d.ts +10 -3
- package/dist/package-manager.d.ts.map +1 -1
- package/dist/package-manager.js +19 -1
- package/dist/package-manager.js.map +1 -1
- package/dist/providers/preset-loader.d.ts.map +1 -1
- package/dist/providers/preset-loader.js +9 -1
- package/dist/providers/preset-loader.js.map +1 -1
- package/dist/providers/presets/anthropic.json +35 -4
- package/dist/providers/presets/gemini-api.json +3 -0
- package/dist/providers/presets/gemini.json +3 -0
- package/dist/providers/presets/groq.json +1 -0
- package/dist/providers/presets/openai.json +36 -4
- package/dist/providers/presets/openrouter.json +6 -2
- package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +28 -4
- package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +47 -3
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +7 -5
- package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +81 -52
- package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +27 -1
- package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +5 -4
- package/dist/sdk-skills/kindgi-getting-started/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +220 -0
- package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +390 -0
- package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +209 -0
- package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +334 -0
- package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +270 -0
- package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +23 -5
- package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +10 -3
- package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +36 -5
- package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +2 -2
- package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +217 -0
- package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +357 -0
- package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +199 -0
- package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +302 -0
- package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +302 -0
- package/dist/templates/java/.mvn/wrapper/maven-wrapper.properties +3 -0
- package/dist/templates/java/AGENTS.md +31 -0
- package/dist/templates/java/README.md.tmpl +69 -0
- package/dist/templates/java/gitignore +9 -0
- package/dist/templates/java/kindgi.config.json.tmpl +8 -0
- package/dist/templates/java/kindgiw +33 -0
- package/dist/templates/java/kindgiw.cmd +28 -0
- package/dist/templates/java/mvnw +295 -0
- package/dist/templates/java/pom.xml.tmpl +65 -0
- package/dist/templates/java/src/main/java/__PACKAGE__/agents/EchoAgent.java.tmpl +27 -0
- package/dist/templates/java/src/main/java/__PACKAGE__/flows/EchoFlow.java.tmpl +18 -0
- package/dist/templates/java/src/main/java/__PACKAGE__/guardrails/ResponseNotEmpty.java.tmpl +28 -0
- package/dist/templates/java/src/main/java/__PACKAGE__/tools/Echo.java.tmpl +22 -0
- package/dist/templates/java/src/main/java/__PACKAGE__/tools/Greet.java.tmpl +23 -0
- package/dist/templates/java/src/test/java/__PACKAGE__/ToolsTest.java.tmpl +30 -0
- package/dist/templates/minimal/README.md.tmpl +8 -14
- package/dist/templates/python/README.md.tmpl +6 -6
- package/dist/templates/sample/README.md.tmpl +7 -13
- package/dist/templates/scala/AGENTS.md +32 -0
- package/dist/templates/scala/README.md.tmpl +75 -0
- package/dist/templates/scala/build.sbt.tmpl +16 -0
- package/dist/templates/scala/gitignore +13 -0
- package/dist/templates/scala/kindgi.config.json.tmpl +8 -0
- package/dist/templates/scala/project/build.properties +1 -0
- package/dist/templates/scala/src/main/scala/__PACKAGE__/agents/EchoAgent.scala.tmpl +23 -0
- package/dist/templates/scala/src/main/scala/__PACKAGE__/flows/EchoFlow.scala.tmpl +16 -0
- package/dist/templates/scala/src/main/scala/__PACKAGE__/guardrails/ResponseNotEmpty.scala.tmpl +21 -0
- package/dist/templates/scala/src/main/scala/__PACKAGE__/tools/Echo.scala.tmpl +16 -0
- package/dist/templates/scala/src/main/scala/__PACKAGE__/tools/Greet.scala.tmpl +17 -0
- package/dist/templates/scala/src/test/scala/__PACKAGE__/ToolsSuite.scala.tmpl +23 -0
- package/package.json +13 -12
|
@@ -5,8 +5,9 @@ description: >
|
|
|
5
5
|
can actually call a real model. Covers four paths — hosted via
|
|
6
6
|
Anthropic native adapter, Gemini on Vertex AI (Google Application
|
|
7
7
|
Default Credentials, no API key), hosted via the OpenAI-compat adapter
|
|
8
|
-
(works with OpenAI
|
|
9
|
-
|
|
8
|
+
(works with OpenAI, Groq, self-hosted vLLM and Ollama, and any other
|
|
9
|
+
OpenAI-compatible endpoint, a hosted gateway such as OpenRouter
|
|
10
|
+
included), and local
|
|
10
11
|
via the in-process ONNX adapter — plus the credential flow (in
|
|
11
12
|
`kindgi dev` the key lives in the project's env files — `.env`, then
|
|
12
13
|
`.env.local` — added by hand or with `kindgi secrets set`'s no-echo
|
|
@@ -22,9 +23,9 @@ description: >
|
|
|
22
23
|
kindgi-getting-started.
|
|
23
24
|
type: core
|
|
24
25
|
library: "@kindgi/sdk"
|
|
25
|
-
version: "0.9.
|
|
26
|
-
sdk_version: "0.1.
|
|
27
|
-
pack_languages: [node, python]
|
|
26
|
+
version: "0.9.11"
|
|
27
|
+
sdk_version: "0.1.5-rc.0"
|
|
28
|
+
pack_languages: [node, python, java, scala]
|
|
28
29
|
sources:
|
|
29
30
|
- packages/adapters/model-anthropic/src/provider.ts
|
|
30
31
|
- packages/adapters/model-gemini/src/provider.ts
|
|
@@ -40,7 +41,8 @@ sources:
|
|
|
40
41
|
> (`@kindgi/cli`), not a global command. Run it through the project's
|
|
41
42
|
> package manager — `pnpm exec kindgi …`, `npx --no kindgi …` (npm),
|
|
42
43
|
> `yarn kindgi …` or `bun run kindgi …`. A Python pack (`[tool.kindgi]` in
|
|
43
|
-
> `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`.
|
|
44
|
+
> `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`. A Java
|
|
45
|
+
> or Scala pack (`kindgi.config.json`) runs the CLI it pins: `./kindgiw …`.
|
|
44
46
|
> Commands below are written `kindgi …` for brevity.
|
|
45
47
|
|
|
46
48
|
An **agent** is a versioned declaration; it needs a **provider** to run.
|
|
@@ -75,8 +77,9 @@ Three moving parts:
|
|
|
75
77
|
1. **API key on disk** — in `kindgi dev` (environment `local`) the dotenv
|
|
76
78
|
secret binding reads the project's own env files: `.env`, then
|
|
77
79
|
`.env.local` on top (change the list with `dev.envFiles` in
|
|
78
|
-
`kindgi.config.ts`,
|
|
79
|
-
pack's `pyproject.toml`
|
|
80
|
+
`kindgi.config.ts`, `envFiles` under `[tool.kindgi.dev]` in a Python
|
|
81
|
+
pack's `pyproject.toml`, or `dev.envFiles` in a Java or Scala pack's
|
|
82
|
+
`kindgi.config.json`). A key already in the app's `.env` just works.
|
|
80
83
|
`kindgi secrets set` (interactive, no-echo) writes `.env.local`. For
|
|
81
84
|
non-sensitive values (log levels, region names, feature flags),
|
|
82
85
|
`kindgi env set NAME VALUE --env=local` writes the same file with a
|
|
@@ -106,7 +109,11 @@ yours.
|
|
|
106
109
|
## Path A — Hosted, native Anthropic
|
|
107
110
|
|
|
108
111
|
Best fidelity to Anthropic's API (prompt caching, latest models, tool
|
|
109
|
-
use
|
|
112
|
+
use). Requires an `ANTHROPIC_API_KEY`.
|
|
113
|
+
|
|
114
|
+
A model's `structured-output` feature is a routing label: the model can
|
|
115
|
+
follow a JSON schema natively, but Kindgi's typed outputs use instructions,
|
|
116
|
+
then parse, check against the schema and repair, on every provider.
|
|
110
117
|
|
|
111
118
|
**Step 1 — set the key:**
|
|
112
119
|
```sh
|
|
@@ -123,9 +130,19 @@ credential on argv.
|
|
|
123
130
|
|
|
124
131
|
**Step 2 — register it, from the preset:**
|
|
125
132
|
```sh
|
|
126
|
-
kindgi providers register --preset=anthropic # Opus 5.5, Sonnet 5.5, Haiku 4.5
|
|
127
|
-
kindgi providers register --preset=anthropic --models=claude-
|
|
133
|
+
kindgi providers register --preset=anthropic # Opus 5.5, Sonnet 5.5 (default), Haiku 5.5, Haiku 4.5
|
|
134
|
+
kindgi providers register --preset=anthropic --models=claude-sonnet-5-5 # just one
|
|
128
135
|
```
|
|
136
|
+
Before pinning a Claude model, check its status on Anthropic's model
|
|
137
|
+
deprecations page (https://platform.claude.com/docs/en/about-claude/model-deprecations): a turn routed to a retired model fails. Prefer the
|
|
138
|
+
preset's default. Each
|
|
139
|
+
preset names a default model (`metadata.defaultModel`, marked `(default)`
|
|
140
|
+
when it registers), which an agent with no preference gets. A preset
|
|
141
|
+
registered before 0.1.4 has none: unregister it and register it again.
|
|
142
|
+
The Claude 5.5 and GPT-6 models take no `temperature` (`"sampling": false`:
|
|
143
|
+
the call goes without it, with a `sampling-unsupported` warning), and a
|
|
144
|
+
model's `thinking` says how it thinks; thinking counts against
|
|
145
|
+
`maxOutputTokens` and bills as output.
|
|
129
146
|
The preset carries the models, context windows, output limits and current
|
|
130
147
|
prices (`kindgi providers presets` lists the presets and when their prices
|
|
131
148
|
were checked); `--max-output-tokens=<n>` sets another output limit. In a pack it refuses until the key is in the pack's env files —
|
|
@@ -139,8 +156,8 @@ needs under `kindgi dev`:
|
|
|
139
156
|
```ts
|
|
140
157
|
// in kindgi.config.ts
|
|
141
158
|
providers: [
|
|
142
|
-
{ preset: 'anthropic', models: ['claude-
|
|
143
|
-
{ preset: 'gemini', project: 'acme-gcp', models: ['gemini-
|
|
159
|
+
{ preset: 'anthropic', models: ['claude-sonnet-5-5'] }, // key ANTHROPIC_API_KEY, from the env files
|
|
160
|
+
{ preset: 'gemini', project: 'acme-gcp', models: ['gemini-3.8-flash'] },
|
|
144
161
|
{ spec: { /* the provider.json body below */ } },
|
|
145
162
|
],
|
|
146
163
|
```
|
|
@@ -148,14 +165,17 @@ providers: [
|
|
|
148
165
|
# in pyproject.toml: one table per provider, same keys
|
|
149
166
|
[[tool.kindgi.providers]]
|
|
150
167
|
preset = "anthropic"
|
|
151
|
-
models = ["claude-
|
|
168
|
+
models = ["claude-sonnet-5-5"]
|
|
152
169
|
```
|
|
170
|
+
In a Java or Scala pack's `kindgi.config.json`, the same keys:
|
|
171
|
+
`"providers": [{"preset": "anthropic", "models": ["claude-sonnet-5-5"]}]`.
|
|
153
172
|
- A preset entry takes `models`, `project`, `secret` (the key's name, in place
|
|
154
|
-
of the preset's) and `maxOutputTokens`, spelled the same in `pyproject.toml
|
|
173
|
+
of the preset's) and `maxOutputTokens`, spelled the same in `pyproject.toml`
|
|
174
|
+
and `kindgi.config.json`;
|
|
155
175
|
a `spec` entry is a `--spec` body. A
|
|
156
176
|
key is always a secret's name (`secret_ref`); a credential in
|
|
157
177
|
`adapter_config` is refused.
|
|
158
|
-
- Each boot prints `Providers from kindgi.config.ts:` with one line each:
|
|
178
|
+
- Each boot prints `Providers from kindgi.config.ts:` (the pack's config file) with one line each:
|
|
159
179
|
`registered`, `unchanged`, `registered again (changed in kindgi.config.ts)`,
|
|
160
180
|
`unregistered (no longer in kindgi.config.ts)`, or ⚠ `not registered: <KEY>
|
|
161
181
|
is not in .env, .env.local` (set the key, then restart: the config isn't
|
|
@@ -167,7 +187,7 @@ models = ["claude-haiku-4-5"]
|
|
|
167
187
|
providers with `kindgi providers register`.
|
|
168
188
|
|
|
169
189
|
**Step 2 (by hand) — write `provider.json`** at the pack root. One connection,
|
|
170
|
-
|
|
190
|
+
two models — matches how the Anthropic SDK actually works (the API
|
|
171
191
|
key is per-vendor; the model is per-call):
|
|
172
192
|
```json
|
|
173
193
|
{
|
|
@@ -194,16 +214,6 @@ key is per-vendor; the model is per-call):
|
|
|
194
214
|
"completionUsdPer1kTokens": 0.01
|
|
195
215
|
},
|
|
196
216
|
"description": "Balanced performance/cost."
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
"name": "claude-haiku-4-5",
|
|
200
|
-
"contextWindow": 200000,
|
|
201
|
-
"features": ["tool-use"],
|
|
202
|
-
"cost": {
|
|
203
|
-
"promptUsdPer1kTokens": 0.001,
|
|
204
|
-
"completionUsdPer1kTokens": 0.005
|
|
205
|
-
},
|
|
206
|
-
"description": "Fastest and cheapest — routing, classification, simple calls."
|
|
207
217
|
}
|
|
208
218
|
],
|
|
209
219
|
"description": "Anthropic Claude via native adapter."
|
|
@@ -261,9 +271,9 @@ Works with **any** OpenAI-compatible endpoint. Same adapter, different
|
|
|
261
271
|
| Groq | `https://api.groq.com/openai/v1` |
|
|
262
272
|
| Together | `https://api.together.xyz/v1` |
|
|
263
273
|
| Fireworks | `https://api.fireworks.ai/inference/v1` |
|
|
264
|
-
| OpenRouter | `https://openrouter.ai/api/v1` |
|
|
265
274
|
| DeepSeek | `https://api.deepseek.com/v1` |
|
|
266
275
|
| LiteLLM proxy | `http://localhost:4000/v1` |
|
|
276
|
+
| OpenRouter (a hosted gateway) | `https://openrouter.ai/api/v1` |
|
|
267
277
|
|
|
268
278
|
The connection carries the `baseURL` (in `adapter_config`);
|
|
269
279
|
each endpoint is a separate provider row because each has its own API
|
|
@@ -485,24 +495,16 @@ outside Google Cloud: put a service-account key (its JSON) in a secret
|
|
|
485
495
|
"region": "global",
|
|
486
496
|
"models": [
|
|
487
497
|
{
|
|
488
|
-
"name": "gemini-
|
|
498
|
+
"name": "gemini-3.8-flash",
|
|
489
499
|
"contextWindow": 1048576,
|
|
490
|
-
"features": ["tool-use"],
|
|
500
|
+
"features": ["tool-use", "structured-output", "long-context"],
|
|
491
501
|
"maxOutputTokens": 65536,
|
|
492
|
-
"cost": {
|
|
493
|
-
"promptUsdPer1kTokens": 0.00125,
|
|
494
|
-
"completionUsdPer1kTokens": 0.01,
|
|
495
|
-
"longContext": {
|
|
496
|
-
"thresholdTokens": 200000,
|
|
497
|
-
"promptUsdPer1kTokens": 0.0025,
|
|
498
|
-
"completionUsdPer1kTokens": 0.015
|
|
499
|
-
}
|
|
500
|
-
}
|
|
502
|
+
"cost": { "promptUsdPer1kTokens": 0.00075, "completionUsdPer1kTokens": 0.00375 }
|
|
501
503
|
},
|
|
502
504
|
{
|
|
503
|
-
"name": "gemini-
|
|
505
|
+
"name": "gemini-3.5-flash-lite",
|
|
504
506
|
"contextWindow": 1048576,
|
|
505
|
-
"features": ["tool-use"],
|
|
507
|
+
"features": ["tool-use", "structured-output", "long-context"],
|
|
506
508
|
"maxOutputTokens": 65536,
|
|
507
509
|
"cost": { "promptUsdPer1kTokens": 0.0003, "completionUsdPer1kTokens": 0.0025 }
|
|
508
510
|
}
|
|
@@ -517,11 +519,17 @@ outside Google Cloud: put a service-account key (its JSON) in a secret
|
|
|
517
519
|
- `metadata.region` is the Vertex location: `global`, or a region such as
|
|
518
520
|
`us-central1` or `northamerica-northeast1` when data must stay in one
|
|
519
521
|
place. `unspecified` means `global`. Different locations are different
|
|
520
|
-
provider rows.
|
|
522
|
+
provider rows. Check that the location serves the model: Gemini 3.8 Flash
|
|
523
|
+
isn't served from `us-central1`.
|
|
524
|
+
- Don't register `gemini-2.5-pro` or `gemini-2.5-flash`: Vertex AI retires
|
|
525
|
+
both on 2026-10-20.
|
|
521
526
|
- Rates are per 1K tokens, from Google's published pricing; check them
|
|
522
|
-
before relying on budgets. Thinking tokens bill as output.
|
|
523
|
-
|
|
524
|
-
|
|
527
|
+
before relying on budgets. Thinking tokens bill as output, and Gemini 3.8
|
|
528
|
+
Flash thinks by default. `gemini-3.8-flash`'s rates above are Google's
|
|
529
|
+
launch price, through 2026-12-31 ($0.0015 / $0.0075 from 2027-01-01).
|
|
530
|
+
`longContext` (`{ thresholdTokens, promptUsdPer1kTokens,
|
|
531
|
+
completionUsdPer1kTokens }` in a model's `cost`) switches the whole call
|
|
532
|
+
to the higher rates past the threshold; `cachedPromptMultiplier` (default 0.25) prices cached
|
|
525
533
|
prompt tokens.
|
|
526
534
|
|
|
527
535
|
**Step 3 — register and check:**
|
|
@@ -533,7 +541,8 @@ Or skip step 2: `kindgi providers register --preset=gemini --project=<your-gcp-p
|
|
|
533
541
|
registers both models above.
|
|
534
542
|
Then pin it from an agent with `preferredProvider: 'gemini'` (and a model
|
|
535
543
|
with `preferredModel`; in Python, `preferred_provider="gemini"` and
|
|
536
|
-
`preferred_model
|
|
544
|
+
`preferred_model=…`; in Java, `.set("preferredProvider", "gemini")`), or let
|
|
545
|
+
the router pick by capability.
|
|
537
546
|
|
|
538
547
|
## How the router picks between multiple providers + models
|
|
539
548
|
|
|
@@ -548,13 +557,16 @@ tenant policy), then sorts survivors in this order:
|
|
|
548
557
|
- Only `preferredModel` set → promote any provider exposing that model.
|
|
549
558
|
- Only `preferredProvider` set → promote every model of that provider.
|
|
550
559
|
`defineAgent` takes both (`preferredProvider`, `preferredModel`), and
|
|
551
|
-
so does a Python `Agent` (`preferred_provider=`, `preferred_model=`)
|
|
560
|
+
so does a Python `Agent` (`preferred_provider=`, `preferred_model=`) and
|
|
561
|
+
a Java `Agent.define(…)` (`set("preferredProvider", …)`).
|
|
552
562
|
2. **`capability.prefer[]` weights.** If the agent's capability
|
|
553
563
|
declares `prefer: [{feature: 'thinking', weight: 3}, ...]`, tuples
|
|
554
564
|
with matching model features (or provider attributes) get higher
|
|
555
565
|
scores. Sorted by summed score, descending.
|
|
556
|
-
3. **Deterministic
|
|
557
|
-
|
|
566
|
+
3. **Deterministic tiebreak.** When scores tie, tuples sort by provider
|
|
567
|
+
id, then the provider's `defaultModel` before its other models, then
|
|
568
|
+
model name — replay-safe and stable. A provider without a
|
|
569
|
+
`defaultModel` falls back to its first model by name.
|
|
558
570
|
|
|
559
571
|
**Practical rule:** preferences are soft — they rank, they don't
|
|
560
572
|
exclude. To guarantee which model runs, make it a hard requirement in
|
|
@@ -645,7 +657,8 @@ defineAgent({
|
|
|
645
657
|
be the FULL npm package name of the adapter — `"@kindgi/adapter-model-anthropic"`,
|
|
646
658
|
NOT `"anthropic"`. Adapters are registered with the runtime under
|
|
647
659
|
their full package names, and a short name matches none of them, so
|
|
648
|
-
the
|
|
660
|
+
registering is refused: the runtime has no adapter by that name
|
|
661
|
+
(`✗ /adapter_id: …`). The model adapters are
|
|
649
662
|
`@kindgi/adapter-model-anthropic`, `@kindgi/adapter-model-gemini`,
|
|
650
663
|
`@kindgi/adapter-model-openai-compat` and
|
|
651
664
|
`@kindgi/adapter-model-in-process`; `kindgi providers presets` shows
|
|
@@ -682,8 +695,9 @@ defineAgent({
|
|
|
682
695
|
Then re-register.
|
|
683
696
|
|
|
684
697
|
6. **Key not found by the runtime.** `kindgi dev` reads the env files
|
|
685
|
-
at the PACK ROOT (the directory with `kindgi.config.ts`,
|
|
686
|
-
pack's `pyproject.toml` with `[tool.kindgi]
|
|
698
|
+
at the PACK ROOT (the directory with `kindgi.config.ts`, a Python
|
|
699
|
+
pack's `pyproject.toml` with `[tool.kindgi]`, or a Java or Scala pack's
|
|
700
|
+
`kindgi.config.json`) — `.env` and
|
|
687
701
|
`.env.local`, or whatever `dev.envFiles` lists; the boot log prints
|
|
688
702
|
which files it found. A `KINDGI_`-prefixed name is Kindgi runtime
|
|
689
703
|
config and never resolves as a secret. Outside `kindgi dev`, the
|
|
@@ -712,6 +726,21 @@ defineAgent({
|
|
|
712
726
|
that names nothing registered, and the tenant's policy. `kindgi
|
|
713
727
|
providers list` shows what is registered.
|
|
714
728
|
|
|
729
|
+
10. **A setting the adapter can't use.** Registering checks the spec
|
|
730
|
+
against its adapter (no network call, no key read) and refuses what
|
|
731
|
+
it can't use: `422 provider-config-invalid`, nothing stored, one line
|
|
732
|
+
per problem with its JSON-pointer path:
|
|
733
|
+
```text
|
|
734
|
+
Error [invalid-request]: Provider "ollama" doesn't fit adapter @kindgi/adapter-model-openai-compat: adapter_config.api must be one of responses, chat-completions.
|
|
735
|
+
✗ /adapter_config/api: adapter_config.api must be one of responses, chat-completions.
|
|
736
|
+
```
|
|
737
|
+
Fix each `✗` line's setting and register again. A key the adapter
|
|
738
|
+
needs is checked too (`✗ /secret_ref: …`); whether the key works, or
|
|
739
|
+
the endpoint answers, isn't (the first turn finds out). A
|
|
740
|
+
registration stored before 0.1.5 wasn't checked: `kindgi doctor`
|
|
741
|
+
names its problems (`GET /v1/providers/<id>/check`); unregister it
|
|
742
|
+
and register it again.
|
|
743
|
+
|
|
715
744
|
## Verifying end-to-end
|
|
716
745
|
|
|
717
746
|
```sh
|
|
@@ -13,7 +13,7 @@ description: >
|
|
|
13
13
|
type: core
|
|
14
14
|
library: "@kindgi/sdk"
|
|
15
15
|
version: "0.4.4"
|
|
16
|
-
sdk_version: "0.1.
|
|
16
|
+
sdk_version: "0.1.5-rc.0"
|
|
17
17
|
pack_languages: [node]
|
|
18
18
|
sources:
|
|
19
19
|
- packages/tools/src/types.ts
|
|
@@ -132,6 +132,32 @@ const defined = defineTool({
|
|
|
132
132
|
|
|
133
133
|
The runtime resolves every declared secret on every call, for the call's tenant, in its env (`KINDGI_ENV`; in `kindgi dev`, `local`: the pack's `.env` and `.env.local`). It checks each value against its schema, and fails the call, naming the secret, when one is missing or doesn't match. Every declared secret is required, so in a runtime call `ctx.secrets` holds them all; it's optional in the type because a unit test builds its own context and passes `secrets: { CITATOR_KEY: '…' }`.
|
|
134
134
|
|
|
135
|
+
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 `needsSpec.env`, read from `ctx.env`:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const defined = defineTool({
|
|
139
|
+
// …id, description, version, input, output, effects…
|
|
140
|
+
needsSpec: {
|
|
141
|
+
env: {
|
|
142
|
+
ORDERS_BASE_URL: { type: 'string', pattern: '^https://' },
|
|
143
|
+
ORDERS_REGION: { type: 'string', enum: ['eu', 'us'], default: 'eu' },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
handler: async ({ orderId }, ctx) => ({
|
|
147
|
+
url: `${ctx.env?.ORDERS_BASE_URL}/${ctx.env?.ORDERS_REGION}/orders/${orderId}`,
|
|
148
|
+
}),
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- **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.
|
|
153
|
+
- **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`.
|
|
154
|
+
- **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:
|
|
155
|
+
```text
|
|
156
|
+
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)
|
|
157
|
+
```
|
|
158
|
+
- **Not secret:** env values are recorded with each run that uses them and shown in its journal. A credential is a secret (`needsSpec.secrets`), never an env value.
|
|
159
|
+
- **In a unit test:** pass `env: { … }` in the context `invokeTool` gets.
|
|
160
|
+
|
|
135
161
|
Everything else comes from the process environment: `process.env.CITATOR_URL`. The pack service runs with the pack's env files in `kindgi dev`, and with the container's environment in an image. Declare the names your code reads in `kindgi.config.ts`, `env: { required: ['CITATOR_URL'], optional: [...] }`: a deployment injects exactly those, a pack service missing a required one isn't ready and says which, and `kindgi dev` warns about it. Values per environment go in `environments.<name>.env`, secrets only as references.
|
|
136
162
|
|
|
137
163
|
## Declarative HTTP spec
|
|
@@ -14,9 +14,9 @@ description: >
|
|
|
14
14
|
diagnostic output into durable input for framework improvement.
|
|
15
15
|
type: core
|
|
16
16
|
library: "@kindgi/sdk"
|
|
17
|
-
version: "0.4.
|
|
18
|
-
sdk_version: "0.1.
|
|
19
|
-
pack_languages: [node, python]
|
|
17
|
+
version: "0.4.2"
|
|
18
|
+
sdk_version: "0.1.5-rc.0"
|
|
19
|
+
pack_languages: [node, python, java, scala]
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
# Capturing framework feedback
|
|
@@ -25,7 +25,8 @@ pack_languages: [node, python]
|
|
|
25
25
|
> (`@kindgi/cli`), not a global command. Run it through the project's
|
|
26
26
|
> package manager — `pnpm exec kindgi …`, `npx --no kindgi …` (npm),
|
|
27
27
|
> `yarn kindgi …` or `bun run kindgi …`. A Python pack (`[tool.kindgi]` in
|
|
28
|
-
> `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`.
|
|
28
|
+
> `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`. A Java
|
|
29
|
+
> or Scala pack (`kindgi.config.json`) runs the CLI it pins: `./kindgiw …`.
|
|
29
30
|
> Commands below are written `kindgi …` for brevity.
|
|
30
31
|
|
|
31
32
|
You just spent time diagnosing a Kindgi-framework issue. That diagnostic
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kindgi-java-authoring-agents
|
|
3
|
+
description: >
|
|
4
|
+
Covers writing agents for a Kindgi pack in Java (`com.kindgi:kindgi-pack`):
|
|
5
|
+
`Agent.define(id)` as a `public static final` field, wiring tools (`Tool`
|
|
6
|
+
objects or an id with a version range) and guardrails, capabilities and
|
|
7
|
+
model choice (preferredProvider / preferredModel), conversation policy,
|
|
8
|
+
turn budgets, prompt parameters, a typed answer from a record, and
|
|
9
|
+
tool-error retries, all as data. Load this whenever you are authoring or
|
|
10
|
+
editing code in a Java pack's agents packages (a pack whose
|
|
11
|
+
`kindgi.config.json` says `"language": "java"`), defining an agent, or
|
|
12
|
+
when the user asks to add, change or refactor one. Java tools are covered
|
|
13
|
+
by kindgi-java-authoring-tools, Java guardrails by
|
|
14
|
+
kindgi-java-authoring-guardrails, connecting a real model by
|
|
15
|
+
kindgi-authoring-providers.
|
|
16
|
+
type: core
|
|
17
|
+
library: "kindgi-pack (Java)"
|
|
18
|
+
version: "0.1.0"
|
|
19
|
+
sdk_version: "0.1.5-rc.0"
|
|
20
|
+
pack_languages: [java]
|
|
21
|
+
sources:
|
|
22
|
+
- sdks/java/kindgi-pack/README.md
|
|
23
|
+
- sdks/java/kindgi-pack/src/main/java/com/kindgi/pack/Agent.java
|
|
24
|
+
- packages/specs/schemas/agent.schema.json
|
|
25
|
+
- packages/specs/schemas/pack-index.schema.json
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# Authoring Kindgi agents in Java
|
|
29
|
+
|
|
30
|
+
> **Running `kindgi`:** the pack pins its CLI (`"cli"` in
|
|
31
|
+
> `kindgi.config.json`), and `./kindgiw` runs that version, so every
|
|
32
|
+
> `kindgi <command>` below runs as `./kindgiw <command>`. Maven runs as
|
|
33
|
+
> `./mvnw`.
|
|
34
|
+
>
|
|
35
|
+
> Java 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 Java pack it is **data**: a `public static final Agent` field of a class
|
|
46
|
+
in an `agents` package. The model runs in the Kindgi runtime, not in your
|
|
47
|
+
JVM. Your Java code runs only inside the agent's tools and guardrail checks.
|
|
48
|
+
|
|
49
|
+
## Ask before building
|
|
50
|
+
|
|
51
|
+
"Add an agent" is a conversation opener, not a ticket. Before writing a
|
|
52
|
+
file, ask:
|
|
53
|
+
|
|
54
|
+
- **What should the agent do?** The purpose drives everything else.
|
|
55
|
+
- **Which tools does it need?** New ones, or existing ones?
|
|
56
|
+
- **Multi-turn or one-shot?** History changes the shape.
|
|
57
|
+
- **Any rules it must respect?** Those become guardrails.
|
|
58
|
+
|
|
59
|
+
The pack's sample agent proves the runtime works end to end. It is not the
|
|
60
|
+
shape to imitate unless the user asks for that.
|
|
61
|
+
|
|
62
|
+
## An agent
|
|
63
|
+
|
|
64
|
+
```java
|
|
65
|
+
// src/main/java/acme/agents/BriefWriter.java
|
|
66
|
+
package acme.agents;
|
|
67
|
+
|
|
68
|
+
import acme.guardrails.ResponseNotEmpty;
|
|
69
|
+
import acme.tools.Echo;
|
|
70
|
+
import com.kindgi.pack.Agent;
|
|
71
|
+
import java.util.List;
|
|
72
|
+
import java.util.Map;
|
|
73
|
+
|
|
74
|
+
/** acme.brief-writer: drafts a brief's argument from the case facts. */
|
|
75
|
+
public final class BriefWriter {
|
|
76
|
+
/** The typed answer: the final message must be JSON of this shape. */
|
|
77
|
+
public record Brief(String argument, List<String> citations) {}
|
|
78
|
+
|
|
79
|
+
public static final Agent AGENT = Agent.define("acme.brief-writer")
|
|
80
|
+
.version("0.1.0")
|
|
81
|
+
.name("Brief Writer")
|
|
82
|
+
.description("Drafts appellate briefs from a case file; cites precedents.")
|
|
83
|
+
.instructions("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.of("needs", List.of(Map.of("feature", "tool-use"))))
|
|
87
|
+
.tool(Echo.TOOL)
|
|
88
|
+
.guardrail(ResponseNotEmpty.GUARDRAIL)
|
|
89
|
+
.set("parameters", List.of(Map.of("name", "jurisdiction", "type", "string", "required", true)))
|
|
90
|
+
.set("conversationPolicy", Map.of("historyLimit", 20))
|
|
91
|
+
.set("budget", Map.of("maxSteps", 8, "maxCostUsd", 0.5, "maxWallMs", 60_000))
|
|
92
|
+
.set("toolErrors", Map.of("maxRetries", 1, "retryOn", List.of("invalid-arguments", "unknown-tool")))
|
|
93
|
+
.output(Brief.class)
|
|
94
|
+
.build();
|
|
95
|
+
|
|
96
|
+
private BriefWriter() {}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- Tools and guardrails are the pack's own fields, imported like any class:
|
|
101
|
+
`.tool(Echo.TOOL)`, `.guardrail(ResponseNotEmpty.GUARDRAIL)`.
|
|
102
|
+
- **`build()` needs a version, a name and instructions.** Anything missing
|
|
103
|
+
is an error where the agent is defined, and the indexer reports it with
|
|
104
|
+
the file.
|
|
105
|
+
- **Every other field is `set(field, value)`, keyed as on the wire:** the
|
|
106
|
+
field and its maps are camelCase (`conversationPolicy`, `maxSteps`,
|
|
107
|
+
`historyLimit`), as `agent.schema.json` names them. The indexer checks
|
|
108
|
+
each agent against the pack index's schema, and `kindgi dev` reports a
|
|
109
|
+
mistake with its file.
|
|
110
|
+
- A class may hold several agents, each in its own `static final` field.
|
|
111
|
+
|
|
112
|
+
## Field by field
|
|
113
|
+
|
|
114
|
+
- **`id`:** `<pack-id>.<agent-name>`, kebab-case, dot-namespaced.
|
|
115
|
+
- **`version`:** an exact semver. Conversations pin the version they started
|
|
116
|
+
on.
|
|
117
|
+
- **`name`, `description`**, and `set("tags", List.of(…))`: for people and
|
|
118
|
+
listings. The model never sees the description.
|
|
119
|
+
- **`instructions`:** a LiquidJS template. `{{ variable }}` comes from
|
|
120
|
+
`parameters` or the runtime's own variables (`today`, `now`, `agent.*`,
|
|
121
|
+
`conversation.*`). It's rendered strictly: an unknown variable fails the
|
|
122
|
+
turn. Write it as a brief for a capable colleague: what to do, which tools
|
|
123
|
+
to prefer, what to refuse, the quality bar. Name a tool by what it does
|
|
124
|
+
("the verify-citation tool"), never by its dotted id. The model sees ids in
|
|
125
|
+
its provider's form (`acme__verify-citation` for Anthropic and
|
|
126
|
+
OpenAI-compatible models), and a dotted id in the instructions can make it
|
|
127
|
+
call a name it wasn't given. `instructions(Map.of("prompt", …, "version", …))`
|
|
128
|
+
references a registered prompt block instead.
|
|
129
|
+
- **`capability(Map)`:** what the model must support, such as
|
|
130
|
+
`Map.of("needs", List.of(Map.of("feature", "tool-use")))`. Call it once per
|
|
131
|
+
capability. The turn routes its first capability to pick a provider and
|
|
132
|
+
model; with none declared, the turn fails.
|
|
133
|
+
- **`tool(Tool)`:** pins that tool's version (its own, or the pack's).
|
|
134
|
+
**`tool(id, range)`** is a tool of another pack, with a semver **range**
|
|
135
|
+
(`"^1.0.0"`); the highest active matching version is picked at turn
|
|
136
|
+
start. An agent with no tools is chat-only.
|
|
137
|
+
- **`guardrail(Guardrail)`** or **`guardrail(id)`:** evaluated once per turn
|
|
138
|
+
on the final answer, before it is stored. An id with no registered
|
|
139
|
+
guardrail fails the turn.
|
|
140
|
+
- **`set("parameters", List.of(Map.of("name", …, "type", …, "required", …)))`:**
|
|
141
|
+
inputs the caller supplies per run. They fill `{{ … }}` in the
|
|
142
|
+
instructions.
|
|
143
|
+
- **`set("preferredProvider", "anthropic")`, `set("preferredModel", "claude-haiku-4-5")`:**
|
|
144
|
+
soft hints. The router prefers them when they satisfy the capabilities.
|
|
145
|
+
To *require* a model, put it in the capability:
|
|
146
|
+
`Map.of("needs", List.of(Map.of("feature", "tool-use"), Map.of("models", Map.of("allow", List.of("claude-haiku-4-5")))))`.
|
|
147
|
+
- **`set("conversationPolicy", …)`:** `historyLimit` caps the prior messages
|
|
148
|
+
loaded, and `hitl` configures approval gates. Absent, the turn loads the
|
|
149
|
+
full history with no gates. A tenant's `hitl` policy can tighten the gates
|
|
150
|
+
(a shorter timeout, a higher reviewer role, stricter per tool), never
|
|
151
|
+
loosen them.
|
|
152
|
+
- **`set("budget", …)`:** per turn. `maxSteps` counts model calls (default
|
|
153
|
+
8); `maxCostUsd`; `maxWallMs` (default 120 000). Exceeding the steps or the
|
|
154
|
+
cost fails the turn (`budget-exceeded`); running out of wall time aborts
|
|
155
|
+
it. Leave room for real models: a turn with tool calls can take tens of
|
|
156
|
+
seconds.
|
|
157
|
+
- **`output(Type.class)`:** a typed answer, with its schema derived from the
|
|
158
|
+
record. The final answer must be JSON matching it. A wrong one goes back
|
|
159
|
+
to the model with the problems (`maxRepairs`, default 1), and then the
|
|
160
|
+
turn fails (`output-schema-violation`). For `maxRepairs` or a schema of
|
|
161
|
+
your own, use `set("output", Map.of("schema", …, "maxRepairs", 2))`. The
|
|
162
|
+
parsed answer is the turn result's `output`. In a flow it is
|
|
163
|
+
`nodeOutputs.<step>.output.<field>`.
|
|
164
|
+
- **`set("toolErrors", …)`:** `maxRetries` and `retryOn`. A failed tool call
|
|
165
|
+
goes back to the model as the call's result, so it can fix the call. The
|
|
166
|
+
default kinds are `invalid-arguments` and `unknown-tool` (nothing ran). Add
|
|
167
|
+
`tool-error` only when retrying the tool is safe. Each retry costs a step.
|
|
168
|
+
|
|
169
|
+
## Which model answers
|
|
170
|
+
|
|
171
|
+
Agents run on a registered model provider: the router picks one whose
|
|
172
|
+
models satisfy the capabilities. `kindgi dev` gives a new pack `dev-echo`, a
|
|
173
|
+
**fallback** that answers only while no other provider fits. It calls the
|
|
174
|
+
first tool and replies "⚠ dev-echo isn't a real model: …", then "Tool
|
|
175
|
+
responded: …". The turn carries the `fallback-provider` and
|
|
176
|
+
`dev-echo-not-a-model` warnings. dev-echo can't fill in any other tool
|
|
177
|
+
input, and can't give a typed answer: an agent with `output` fails with
|
|
178
|
+
`output-schema-violation` until a real model is registered. To register one,
|
|
179
|
+
see `kindgi-authoring-providers` (`./kindgiw providers register --preset=anthropic`,
|
|
180
|
+
or `"providers": [{"preset": "anthropic"}]` in `kindgi.config.json`).
|
|
181
|
+
|
|
182
|
+
## Iterating
|
|
183
|
+
|
|
184
|
+
Save the file: `kindgi dev` recompiles, re-indexes, and the next run uses
|
|
185
|
+
it, with no restart. Bump `version` when you break what callers rely on (a
|
|
186
|
+
removed parameter, an incompatible output), not on every save.
|
|
187
|
+
|
|
188
|
+
Run an agent from another terminal in the pack directory:
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
./kindgiw runs start --agent=acme.brief-writer --input='{"userMessage":"…","parameters":{"jurisdiction":"US"}}'
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
or from a Java app with the client (`kindgi-java-getting-started`).
|
|
195
|
+
|
|
196
|
+
## Common mistakes
|
|
197
|
+
|
|
198
|
+
1. **Building an agent without asking what it should do.** Copying the
|
|
199
|
+
sample's shape answers the wrong question.
|
|
200
|
+
2. **No `capability(…)`.** The turn can't pick a model.
|
|
201
|
+
3. **Java names inside the maps.** `set("budget", Map.of("max_steps", 4))`
|
|
202
|
+
isn't a budget: the keys are the wire's camelCase (`maxSteps`,
|
|
203
|
+
`historyLimit`, `maxRetries`).
|
|
204
|
+
4. **An unregistered guardrail id.** Pass the `Guardrail` field, or make sure
|
|
205
|
+
the id is one the tenant has.
|
|
206
|
+
5. **`{{ variable }}` not in `parameters`.** The turn fails when the
|
|
207
|
+
instructions render.
|
|
208
|
+
6. **An agent that isn't a `static final` field.** Only static fields are
|
|
209
|
+
indexed.
|
|
210
|
+
7. **A tight `maxWallMs` with a real model.** 15 s aborts real turns under
|
|
211
|
+
load; 60 s is a safer start.
|
|
212
|
+
8. **Expecting dev-echo to give a typed answer.** It can't: register a real
|
|
213
|
+
model first.
|
|
214
|
+
|
|
215
|
+
## When the framework itself is the problem
|
|
216
|
+
|
|
217
|
+
If the bug is in Kindgi or kindgi-pack (the index dropping a field, a
|
|
218
|
+
misleading error, the router picking the wrong model) and not in the pack's
|
|
219
|
+
code, load `kindgi-framework-feedback` and file it with
|
|
220
|
+
`./kindgiw feedback write`.
|