@kindgi/cli 0.2.0-rc.1 → 0.3.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +12 -5
  2. package/dist/cli.js +4 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/agents.d.ts.map +1 -1
  5. package/dist/commands/agents.js +75 -19
  6. package/dist/commands/agents.js.map +1 -1
  7. package/dist/commands/approval-wait.d.ts +90 -0
  8. package/dist/commands/approval-wait.d.ts.map +1 -0
  9. package/dist/commands/approval-wait.js +154 -0
  10. package/dist/commands/approval-wait.js.map +1 -0
  11. package/dist/commands/artifacts.d.ts.map +1 -1
  12. package/dist/commands/artifacts.js +131 -14
  13. package/dist/commands/artifacts.js.map +1 -1
  14. package/dist/commands/auth.d.ts.map +1 -1
  15. package/dist/commands/auth.js +48 -5
  16. package/dist/commands/auth.js.map +1 -1
  17. package/dist/commands/deploy.js +7 -3
  18. package/dist/commands/deploy.js.map +1 -1
  19. package/dist/commands/deployments.d.ts.map +1 -1
  20. package/dist/commands/deployments.js +36 -13
  21. package/dist/commands/deployments.js.map +1 -1
  22. package/dist/commands/doctor.d.ts +3 -2
  23. package/dist/commands/doctor.d.ts.map +1 -1
  24. package/dist/commands/doctor.js +47 -14
  25. package/dist/commands/doctor.js.map +1 -1
  26. package/dist/commands/eval-runs.d.ts.map +1 -1
  27. package/dist/commands/eval-runs.js +21 -9
  28. package/dist/commands/eval-runs.js.map +1 -1
  29. package/dist/commands/helpers.d.ts +31 -1
  30. package/dist/commands/helpers.d.ts.map +1 -1
  31. package/dist/commands/helpers.js +45 -2
  32. package/dist/commands/helpers.js.map +1 -1
  33. package/dist/commands/init.js +5 -4
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/mail-triggers.d.ts.map +1 -1
  36. package/dist/commands/mail-triggers.js +27 -3
  37. package/dist/commands/mail-triggers.js.map +1 -1
  38. package/dist/commands/promote.d.ts.map +1 -1
  39. package/dist/commands/promote.js +133 -11
  40. package/dist/commands/promote.js.map +1 -1
  41. package/dist/commands/provenance.d.ts.map +1 -1
  42. package/dist/commands/provenance.js +13 -5
  43. package/dist/commands/provenance.js.map +1 -1
  44. package/dist/commands/providers.d.ts.map +1 -1
  45. package/dist/commands/providers.js +47 -4
  46. package/dist/commands/providers.js.map +1 -1
  47. package/dist/commands/schedules.d.ts.map +1 -1
  48. package/dist/commands/schedules.js +25 -9
  49. package/dist/commands/schedules.js.map +1 -1
  50. package/dist/commands/skills.d.ts +16 -0
  51. package/dist/commands/skills.d.ts.map +1 -1
  52. package/dist/commands/skills.js +122 -36
  53. package/dist/commands/skills.js.map +1 -1
  54. package/dist/commands/webhooks.d.ts.map +1 -1
  55. package/dist/commands/webhooks.js +21 -5
  56. package/dist/commands/webhooks.js.map +1 -1
  57. package/dist/config.d.ts +8 -0
  58. package/dist/config.d.ts.map +1 -1
  59. package/dist/config.js +11 -0
  60. package/dist/config.js.map +1 -1
  61. package/dist/context.d.ts +7 -3
  62. package/dist/context.d.ts.map +1 -1
  63. package/dist/context.js +1 -0
  64. package/dist/context.js.map +1 -1
  65. package/dist/dev/runtime-image.d.ts +1 -1
  66. package/dist/dev/runtime-image.js +1 -1
  67. package/dist/errors.d.ts.map +1 -1
  68. package/dist/errors.js +14 -1
  69. package/dist/errors.js.map +1 -1
  70. package/dist/exports/plan.d.ts.map +1 -1
  71. package/dist/exports/plan.js +50 -0
  72. package/dist/exports/plan.js.map +1 -1
  73. package/dist/init/augment-scaffolder.d.ts +1 -1
  74. package/dist/init/augment-scaffolder.js +9 -8
  75. package/dist/init/augment-scaffolder.js.map +1 -1
  76. package/dist/init/java-augment.d.ts.map +1 -1
  77. package/dist/init/java-augment.js +7 -6
  78. package/dist/init/java-augment.js.map +1 -1
  79. package/dist/init/python-augment.d.ts.map +1 -1
  80. package/dist/init/python-augment.js +7 -6
  81. package/dist/init/python-augment.js.map +1 -1
  82. package/dist/init/scala-augment.js +7 -6
  83. package/dist/init/scala-augment.js.map +1 -1
  84. package/dist/main.d.ts +3 -0
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/main.js +1 -0
  87. package/dist/main.js.map +1 -1
  88. package/dist/providers/presets/anthropic.json +15 -3
  89. package/dist/providers/presets/azure-openai.json +10 -2
  90. package/dist/providers/presets/bedrock.json +6 -2
  91. package/dist/providers/presets/gemini-api.json +6 -2
  92. package/dist/providers/presets/openai.json +15 -3
  93. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +21 -9
  94. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +5 -3
  95. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +202 -68
  96. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +12 -188
  97. package/dist/sdk-skills/kindgi-authoring-mcp-servers/common-mistakes.md +44 -0
  98. package/dist/sdk-skills/kindgi-authoring-mcp-servers/how-it-works.md +41 -0
  99. package/dist/sdk-skills/kindgi-authoring-mcp-servers/other-clients.md +19 -0
  100. package/dist/sdk-skills/kindgi-authoring-mcp-servers/postgres.md +45 -0
  101. package/dist/sdk-skills/kindgi-authoring-mcp-servers/several-servers.md +32 -0
  102. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +49 -906
  103. package/dist/sdk-skills/kindgi-authoring-providers/bedrock.md +64 -0
  104. package/dist/sdk-skills/kindgi-authoring-providers/common-mistakes.md +125 -0
  105. package/dist/sdk-skills/kindgi-authoring-providers/keys-and-registration.md +58 -0
  106. package/dist/sdk-skills/kindgi-authoring-providers/kindgi-cloud.md +36 -0
  107. package/dist/sdk-skills/kindgi-authoring-providers/path-a-anthropic.md +216 -0
  108. package/dist/sdk-skills/kindgi-authoring-providers/path-b-openai-compat.md +127 -0
  109. package/dist/sdk-skills/kindgi-authoring-providers/path-c-onnx.md +97 -0
  110. package/dist/sdk-skills/kindgi-authoring-providers/path-d-vertex.md +95 -0
  111. package/dist/sdk-skills/kindgi-authoring-providers/router.md +113 -0
  112. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +12 -387
  113. package/dist/sdk-skills/kindgi-authoring-tools/common-mistakes.md +135 -0
  114. package/dist/sdk-skills/kindgi-authoring-tools/declarative-http.md +34 -0
  115. package/dist/sdk-skills/kindgi-authoring-tools/imperative-handler.md +65 -0
  116. package/dist/sdk-skills/kindgi-authoring-tools/iterating-and-testing.md +45 -0
  117. package/dist/sdk-skills/kindgi-authoring-tools/secrets-and-connections.md +79 -0
  118. package/dist/sdk-skills/kindgi-authoring-tools/tool-flags.md +45 -0
  119. package/dist/sdk-skills/kindgi-fix-corrections/SKILL.md +13 -178
  120. package/dist/sdk-skills/kindgi-fix-corrections/make-the-change.md +25 -0
  121. package/dist/sdk-skills/kindgi-fix-corrections/publish-and-promote.md +76 -0
  122. package/dist/sdk-skills/kindgi-fix-corrections/pull-corrections.md +48 -0
  123. package/dist/sdk-skills/kindgi-fix-corrections/worked-example.md +27 -0
  124. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +10 -180
  125. package/dist/sdk-skills/kindgi-framework-feedback/common-mistakes.md +19 -0
  126. package/dist/sdk-skills/kindgi-framework-feedback/editing-feedback-file.md +33 -0
  127. package/dist/sdk-skills/kindgi-framework-feedback/fields-and-entry-shape.md +53 -0
  128. package/dist/sdk-skills/kindgi-framework-feedback/hearing-back.md +24 -0
  129. package/dist/sdk-skills/kindgi-framework-feedback/sending.md +50 -0
  130. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +24 -21
  131. package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +12 -4
  132. package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +6 -4
  133. package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +33 -23
  134. package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +19 -12
  135. package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +16 -16
  136. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +18 -6
  137. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +6 -4
  138. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +39 -30
  139. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +19 -9
  140. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +24 -21
  141. package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +12 -4
  142. package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +6 -4
  143. package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +34 -23
  144. package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +15 -9
  145. package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +16 -16
  146. package/dist/sdk-skills/kindgi-using/SKILL.md +11 -11
  147. package/dist/templates/sample/README.md.tmpl +8 -7
  148. package/dist/templates/sample/agents/echo-agent/index.ts.tmpl +1 -1
  149. package/dist/templates/sample/kindgi.config.ts.tmpl +1 -1
  150. package/dist/templates/sample/package.json.tmpl +1 -1
  151. package/dist/templates/woocommerce/README.md.tmpl +9 -3
  152. package/package.json +13 -13
@@ -0,0 +1,64 @@
1
+ # Amazon Bedrock
2
+
3
+ Nova, Claude and GPT on Amazon Bedrock. The `bedrock` preset signs in as the
4
+ runtime's own AWS identity (`KINDGI_AWS_IDENTITY` says where it comes from),
5
+ so it takes no key:
6
+ ```sh
7
+ kindgi providers register --preset=bedrock --region=us-east-2
8
+ kindgi providers register --preset=bedrock --region=us-east-2 \
9
+ --models=us.anthropic.claude-haiku-4-5-20251001-v1:0 # Claude, not Nova Pro
10
+ ```
11
+ `--region` is the US Region the account uses Bedrock in: the preset's models
12
+ are US cross-region inference profiles. Its default model is Amazon Nova Pro
13
+ (`us.amazon.nova-pro-v1:0`). Claude and GPT also need the AWS account's
14
+ access to their vendor's models
15
+ (https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).
16
+
17
+ **On a runtime with `KINDGI_TENANT_HOST_ACCESS=isolated`, use a Bedrock API
18
+ key.** That runtime doesn't lend its own credentials to tenant configuration,
19
+ so it refuses the preset at registration and stores nothing:
20
+ ```text
21
+ ✗ /adapter_config/auth: adapter_config.auth = aws-identity (the default) signs in as the runtime's own AWS identity, which this deployment doesn't let tenant configuration use (KINDGI_TENANT_HOST_ACCESS). Set auth = api-key, with secret_ref naming a Bedrock API key.
22
+ ```
23
+ `--secret` doesn't change that: the preset still signs in as the runtime.
24
+ Register from a spec whose `adapter_config.auth` is `api-key` and whose
25
+ `secret_ref` names the key:
26
+
27
+ 1. **A long-term Bedrock API key**, made in the Region the provider uses. A
28
+ short-term key lasts 12 hours at most, so a registration can't keep one,
29
+ and a key works only in the Region it was made in. AWS recommends
30
+ long-term keys for exploration only: tell the person so, with AWS's page
31
+ (https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html).
32
+ 2. **Stored as a tenant secret**, with the no-echo prompt:
33
+ `kindgi secrets set BEDROCK_API_KEY --env=production --scope=tenant`.
34
+ 3. **Registered:** `kindgi providers register --spec=@bedrock.json`, with
35
+ ```json
36
+ {
37
+ "adapter_id": "@kindgi/adapter-model-bedrock",
38
+ "adapter_config": { "auth": "api-key" },
39
+ "secret_ref": { "envName": "production", "name": "BEDROCK_API_KEY" },
40
+ "metadata": {
41
+ "id": "bedrock",
42
+ "region": "us-east-2",
43
+ "models": [
44
+ { "name": "us.anthropic.claude-haiku-4-5-20251001-v1:0", "contextWindow": 200000,
45
+ "maxOutputTokens": 16000, "features": ["tool-use", "parallel-tool-use"],
46
+ "cost": { "promptUsdPer1kTokens": 0.0011, "completionUsdPer1kTokens": 0.0055 } }
47
+ ]
48
+ }
49
+ }
50
+ ```
51
+
52
+ One provider is one Region and one key: another Region is another provider,
53
+ with a key made there. The key is read when a turn calls the model, not at
54
+ registration.
55
+
56
+ The same holds for the other providers that can sign in as the runtime on
57
+ `isolated`. Gemini on Vertex AI takes a service-account key in `secret_ref`
58
+ (Path D). Azure OpenAI's `auth: entra` is refused: use the `azure-openai`
59
+ preset, with the resource's key. A provider registered before the runtime
60
+ moved to `isolated` that signs in as the runtime isn't used there: a turn
61
+ that needs it fails with `422 capability-routing-failed`. Unregister it, and
62
+ register it again with a key.
63
+
64
+ Docs: https://docs.kindgi.com/v0.3/guides/models/#with-a-bedrock-api-key
@@ -0,0 +1,125 @@
1
+ # Common mistakes
2
+
3
+ ## Contents
4
+
5
+ - 0. `adapter_id` uses the short name.
6
+ - 1. `envName` mismatch between the key and the provider's `secret_ref`.
7
+ - 2. Missing `features` on the model.
8
+ - 3. Empty `models[]`.
9
+ - 4. Setting `secret_ref` for the in-process adapter.
10
+ - 5. Registering the same provider id twice with different config.
11
+ - 6. Key not found by the runtime.
12
+ - 7. Forgetting to restart `kindgi dev` after registering a provider.
13
+ - 8. Compound `preferredProvider` strings.
14
+ - 9. Replies still come from dev-echo
15
+ - 10. A setting the adapter can't use.
16
+ - 11. A provider registered by hand under `kindgi dev`, with nothing committed.
17
+
18
+ 0. **`adapter_id` uses the short name.** The `adapter_id` field must
19
+ be the FULL npm package name of the adapter — `"@kindgi/adapter-model-anthropic"`,
20
+ NOT `"anthropic"`. Adapters are registered with the runtime under
21
+ their full package names, and a short name matches none of them, so
22
+ registering is refused: the runtime has no adapter by that name
23
+ (`✗ /adapter_id: …`). The model adapters are
24
+ `@kindgi/adapter-model-anthropic`, `@kindgi/adapter-model-gemini`,
25
+ `@kindgi/adapter-model-openai-compat`,
26
+ `@kindgi/adapter-model-azure-openai`, `@kindgi/adapter-model-bedrock` and
27
+ `@kindgi/adapter-model-in-process`; `kindgi providers presets` shows
28
+ the id each preset uses.
29
+
30
+ 1. **`envName` mismatch between the key and the provider's `secret_ref`.**
31
+ The runtime reads a provider's key in the environment its
32
+ `secret_ref.envName` names, at tenant scope. The SecretBinding refuses
33
+ to cross-resolve, so a key held under another environment gives
34
+ `secret-not-found` at agent-turn time. Where each one lands:
35
+ `kindgi secrets set` needs `--env=<name>`; `kindgi providers register
36
+ --preset` writes `--env`'s name, or `local` without it; a `--spec` file
37
+ names its own (`"secret_ref": {"envName": "production", ...}`). Under
38
+ `kindgi dev`, `local` is the project's env files (`.env`, `.env.local`)
39
+ and `.kindgi/secrets.env`; any other name is `.env.<envName>`. Match
40
+ them. On Kindgi Cloud, both are `prod`.
41
+
42
+ 2. **Missing `features` on the model.** Agent declares
43
+ `capabilities: [{needs: [{feature: 'tool-use'}]}]`; at least one
44
+ model inside `metadata.models[]` must list `"features":
45
+ ["tool-use"]` or the router filters every tuple out. If `kindgi
46
+ runs start` returns "no provider satisfies capability", check the
47
+ per-model `features` list — not a provider-level field anymore.
48
+
49
+ 3. **Empty `models[]`.** Registration rejects with `empty-models`. Every
50
+ provider row must expose at least one model. Duplicate `name` within
51
+ the same array is also rejected (`duplicate-model-name`).
52
+
53
+ 4. **Setting `secret_ref` for the in-process adapter.** `in-process`
54
+ ignores `secret_ref` — no key needed. Leaving it in is harmless but
55
+ noisy.
56
+
57
+ 5. **Registering the same provider id twice with different config.**
58
+ Returns `409 provider-already-registered`. Unregister first:
59
+ ```sh
60
+ kindgi providers unregister <provider-id>
61
+ ```
62
+ Then re-register.
63
+
64
+ 6. **Key not found by the runtime.** `kindgi dev` reads the env files
65
+ at the PACK ROOT (the directory with `kindgi.config.ts`, a Python
66
+ pack's `pyproject.toml` with `[tool.kindgi]`, or a Java or Scala pack's
67
+ `kindgi.config.json`) — `.env` and
68
+ `.env.local`, or whatever `dev.envFiles` lists; the boot log prints
69
+ which files it found. A `KINDGI_`-prefixed name is Kindgi runtime
70
+ config and never resolves as a secret. Outside `kindgi dev`, the
71
+ runtime resolves secrets through the deployment's `SecretBinding`
72
+ (a KMS- or database-backed store, for example).
73
+
74
+ 7. **Forgetting to restart `kindgi dev` after registering a provider.**
75
+ You don't need to — provider registrations go to the running runtime
76
+ over HTTP (`POST /v1/providers`), which invalidates the tenant's
77
+ cached provider set. The next `kindgi runs start` sees the new
78
+ provider.
79
+
80
+ 8. **Compound `preferredProvider` strings.** `preferredProvider` is a
81
+ provider (connection) id such as `'anthropic'`; the model is a
82
+ separate choice. A value like `'anthropic-claude-sonnet-5-5'`
83
+ (vendor + model baked together) matches no provider id, so the hint
84
+ does nothing. Pin the model with a `models: { allow: [...] }`
85
+ requirement instead.
86
+
87
+ 9. **Replies still come from dev-echo** (`⚠ dev-echo isn't a real model: …`
88
+ then `Tool responded: …`; the turn's result has the `fallback-provider`
89
+ and `dev-echo-not-a-model` warnings). dev-echo is a fallback: it
90
+ answers only when no registered provider satisfies the agent. So your
91
+ provider doesn't — check its models' `features` against the agent's
92
+ `capabilities.needs` (mistake 2), a `models` / `providers` allow-list
93
+ that names nothing registered, and the tenant's policy. `kindgi
94
+ providers list` shows what is registered.
95
+
96
+ 10. **A setting the adapter can't use.** Registering checks the spec
97
+ against its adapter (no network call, no key read) and refuses what
98
+ it can't use: `422 provider-config-invalid`, nothing stored, one line
99
+ per problem with its JSON-pointer path:
100
+ ```text
101
+ Error [invalid-request]: Provider "ollama" doesn't fit adapter @kindgi/adapter-model-openai-compat: adapter_config.api must be one of responses, chat-completions.
102
+ ✗ /adapter_config/api: adapter_config.api must be one of responses, chat-completions.
103
+ ```
104
+ Fix each `✗` line's setting and register again. A key the adapter
105
+ needs is checked too (`✗ /secret_ref: …`); whether the key works, or
106
+ the endpoint answers, isn't (the first turn finds out). So is each
107
+ `adapter_config` key: one the adapter doesn't take is refused, naming
108
+ the ones it takes (`✗ /adapter_config/timeout: adapter_config.timeout
109
+ isn't a setting of this adapter: it takes baseURL, api,
110
+ extraBody.<field>.`), and one that moved names its new place. A
111
+ registration stored before 0.1.5 wasn't checked: `kindgi doctor`
112
+ names its problems (`GET /v1/providers/<id>/check`); unregister it
113
+ and register it again. A stored registration with a key its adapter
114
+ doesn't take still builds, without reading it: the check lists it in
115
+ `warnings`, apart from `issues`, and `kindgi doctor` shows it as a
116
+ warning.
117
+
118
+ 11. **A provider registered by hand under `kindgi dev`, with nothing
119
+ committed.** `kindgi providers register` puts it in this worktree's dev
120
+ database only. Another worktree, a `kindgi dev --reset`, or a
121
+ teammate's `kindgi dev` has no provider, and its turns land on
122
+ dev-echo (mistake 9). Declare the provider in the pack's config and
123
+ commit it (step 2 of your path). `.kindgi/dev/providers.json` isn't the file to
124
+ commit: it's `kindgi dev`'s local record of what it registered, and
125
+ `.kindgi/` is gitignored.
@@ -0,0 +1,58 @@
1
+ # Mental model: keys, registration and fallbacks
2
+
3
+ ```
4
+ Project .env / .env.local dotenv SecretBinding runtime ProviderRegistry
5
+ ───────────────────────── ───────────────────── ────────────────────────
6
+ ANTHROPIC_API_KEY=sk-... → resolve('local', hydrated per tenant on first
7
+ 'ANTHROPIC_API_KEY') access; each row =
8
+ { metadata, adapter_id,
9
+ secret_ref?,
10
+ adapter_config? }
11
+ │ │
12
+ ▼ ▼
13
+ adapter factory ──── resolves apiKey lazily via closure
14
+ │
15
+ ▼
16
+ ModelProvider ────── router picks a (provider, model)
17
+ tuple when an agent's
18
+ capabilities.needs matches
19
+ ```
20
+
21
+ Three moving parts:
22
+ 1. **API key on disk** — in `kindgi dev` (environment `local`) the dotenv
23
+ secret binding reads the project's own env files: `.env`, then
24
+ `.env.local` on top (change the list with `dev.envFiles` in
25
+ `kindgi.config.ts`, `envFiles` under `[tool.kindgi.dev]` in a Python
26
+ pack's `pyproject.toml`, or `dev.envFiles` in a Java or Scala pack's
27
+ `kindgi.config.json`), then Kindgi's own `.kindgi/secrets.env` on top.
28
+ A key already in the app's `.env` just works. `kindgi secrets set`
29
+ (interactive, no-echo) writes `.kindgi/secrets.env`, a file the app
30
+ doesn't load (a framework loads `.env.local` into every route); `--app`
31
+ writes the app's file instead, for a value the app reads too (a webhook
32
+ signing secret). For non-sensitive values (log levels, region names,
33
+ feature flags), `kindgi env set NAME VALUE --env=local` writes the app's
34
+ `.env.local` with a positional value — never route real secrets
35
+ through it. `KINDGI_*`
36
+ names configure Kindgi itself and are never resolvable as secrets.
37
+ 2. **Provider registration** — declared in the pack's config, which is
38
+ committed, and registered by `kindgi dev` at each boot; on a runtime
39
+ `kindgi dev` doesn't run, `kindgi providers register` (`POST /v1/providers`)
40
+ 3. **Agent's `capabilities.needs`** — matched at the (provider, model) tuple level at turn time
41
+
42
+ **Registration body:** `{ metadata, adapter_id, secret_ref?, adapter_config? }`.
43
+ `secret_ref` points at the credential; `adapter_config` holds the adapter's
44
+ non-secret connection settings (a cloud project, a base URL) as flat string,
45
+ number or boolean values. Both are stored with the provider and handed to the
46
+ runtime; `kindgi providers list` / `get` show only `metadata`. Never put a
47
+ credential in `adapter_config`.
48
+
49
+ **Shape rule:** `ProviderMetadata.id` names the CONNECTION (e.g. `anthropic`,
50
+ `groq`, `local-onnx`); per-model fields (`name`, `contextWindow`, `cost`,
51
+ `features`) live inside `metadata.models[]`. One row can expose many models
52
+ under the same API key.
53
+
54
+ **Fallbacks:** `"fallback": true` in `metadata` makes a provider a
55
+ fallback — the router considers it only when no other provider satisfies
56
+ the agent's capability, and the turn's result then carries a
57
+ `fallback-provider` warning. `dev-echo` is one; a cheap local model can be
58
+ yours.
@@ -0,0 +1,36 @@
1
+ # On Kindgi Cloud: the key and its provider go under `prod`
2
+
3
+ A pack deployed with `kindgi deploy --hosted` runs on your workspace's
4
+ runtime on Kindgi Cloud, and that runtime serves the `prod` environment,
5
+ before and after you go live. The other files' examples use `--env=local`, for
6
+ `kindgi dev`. For Kindgi Cloud, name `prod` instead:
7
+
8
+ ```sh
9
+ kindgi secrets set ANTHROPIC_API_KEY --env=prod --scope=tenant # a no-echo prompt
10
+ kindgi providers register --preset=anthropic --env=prod
11
+ kindgi deploy --hosted --env=prod
12
+ ```
13
+
14
+ - The runtime reads a provider's key in the environment its
15
+ `secret_ref.envName` names, at tenant scope. Keep the key and the
16
+ provider both on `prod`. A provider registered without `--env` reads
17
+ `local`, not the `prod` key: `register` refuses when the pack's own env
18
+ files lack the key (its message names `--env`), and otherwise the first
19
+ turn can't find the key (mistake 1 in `common-mistakes.md`). By hand, `provider.json` has
20
+ `"secret_ref": { "envName": "prod", … }`.
21
+ - `kindgi secrets set` has no default environment: name `--env` every time.
22
+ - The deployment `kindgi deploy` sends names no environment. Its
23
+ `--env=prod` picks the pack's own `prod` settings, such as its signing
24
+ key.
25
+ - `kindgi deploy` doesn't register providers, and the providers declared in
26
+ the pack's config are `kindgi dev`'s only. Register once on `prod`, by
27
+ hand, and again when you add a provider or change one.
28
+ - OpenAI, the Gemini API, Groq and OpenRouter take the same two lines,
29
+ with their preset and key: `openai` and `OPENAI_API_KEY`, `gemini-api`
30
+ and `GEMINI_API_KEY`, `groq` and `GROQ_API_KEY`, `openrouter` and
31
+ `OPENROUTER_API_KEY`. Bedrock, Vertex AI and Azure OpenAI don't fit
32
+ them: see `bedrock.md` and `path-d-vertex.md`, and `kindgi providers
33
+ presets` for `azure-openai`'s settings.
34
+
35
+ The whole flow, from signing the CLI in to going live:
36
+ https://docs.kindgi.com/v0.3/hosted/deploy-your-agent/#your-model-key-and-its-provider
@@ -0,0 +1,216 @@
1
+ # Path A — Hosted, native Anthropic
2
+
3
+ ## Contents
4
+
5
+ - Step 1 — set the key
6
+ - Step 2 — declare it in the pack's config, and commit it
7
+ - Staging and production: register by hand, once per runtime
8
+ - Step 2 (by hand) — write `provider.json`
9
+ - Step 3 — register
10
+ - Step 4 — verify
11
+ - Step 5 — run
12
+ - The other one-key presets
13
+
14
+ Best fidelity to Anthropic's API (prompt caching, latest models, tool
15
+ use). Requires an `ANTHROPIC_API_KEY`.
16
+
17
+ A model's `structured-output` feature is a routing label: the model can
18
+ follow a JSON schema natively, but Kindgi's typed outputs use instructions,
19
+ then parse, check against the schema and repair, on every provider.
20
+
21
+ **Step 1 — set the key:**
22
+ ```sh
23
+ kindgi secrets set ANTHROPIC_API_KEY --env=local --scope=tenant
24
+ # Prompts twice, echo disabled: paste the key, then again to confirm.
25
+ ```
26
+ Under `kindgi dev`, this writes to `.kindgi/secrets.env` at the pack root
27
+ via the dotenv secret binding — or add `ANTHROPIC_API_KEY=…` to that file yourself; `kindgi dev`
28
+ also reads the app's `.env` / `.env.local`. If the pack lives inside an app
29
+ whose env file already has the key, it works as it is; `kindgi secrets copy`
30
+ gives Kindgi its own copy and never edits the app's files (the app may use
31
+ the key itself: leave removing it to the person). Keep env files gitignored. For pipelines/CI, pipe the value with
32
+ `echo -n "$KEY" | kindgi secrets set ANTHROPIC_API_KEY --env=local --scope=tenant --from-stdin`,
33
+ or read from a mode-0600 file with `--from-file <path>`. Never pass a
34
+ credential on argv.
35
+
36
+ For a pack on Kindgi Cloud, `--env=prod` instead: the key goes to your
37
+ workspace's runtime, not to a file (`kindgi-cloud.md`).
38
+
39
+ **Step 2 — declare it in the pack's config, and commit it.** `kindgi dev`
40
+ registers what the config declares on every boot: in every git worktree
41
+ (each has its own dev database), after `--reset`, and on a teammate's
42
+ machine. The declaration holds a key's name, never the key, so it goes in
43
+ git with the rest of the config. Committing it is how a teammate's
44
+ `kindgi dev`, or another worktree's, gets the same provider:
45
+ ```ts
46
+ // in kindgi.config.ts
47
+ providers: [
48
+ { preset: 'anthropic', models: ['claude-sonnet-5-5'] }, // key ANTHROPIC_API_KEY, from the env files
49
+ { preset: 'gemini', project: 'acme-gcp', models: ['gemini-3.8-flash'] },
50
+ { spec: { /* the provider.json body below */ } },
51
+ ],
52
+ ```
53
+ ```toml
54
+ # in pyproject.toml: one table per provider, same keys
55
+ [[tool.kindgi.providers]]
56
+ preset = "anthropic"
57
+ models = ["claude-sonnet-5-5"]
58
+ ```
59
+ In a Java or Scala pack's `kindgi.config.json`, the same keys:
60
+ `"providers": [{"preset": "anthropic", "models": ["claude-sonnet-5-5"]}]`.
61
+ - A preset entry takes `models`, the settings its preset asks for (`project`
62
+ for `gemini`; `resourceName` and `deployments` for `azure-openai`; `region`
63
+ for `bedrock`), `secret` (the key's name, in place of the preset's) and
64
+ `maxOutputTokens`, spelled the same in `pyproject.toml` and
65
+ `kindgi.config.json`. Its own settings are required and another preset's
66
+ are refused. `deployments` is a map of model to deployment
67
+ (`{ "gpt-6.1-sol": "gpt-6-1-sol" }`, a `[tool.kindgi.providers.deployments]`
68
+ table in `pyproject.toml`, model names quoted), not the `--deployments` flag's
69
+ `model=deployment,…`, and it names exactly the models the entry registers;
70
+ a `spec` entry is a `--spec` body. A
71
+ key is always a secret's name (`secret_ref`); a credential in
72
+ `adapter_config` is refused.
73
+ - Each boot prints `Providers from kindgi.config.ts:` (the pack's config file) with one line each:
74
+ `registered`, `unchanged`, `registered again (changed in kindgi.config.ts)`,
75
+ `unregistered (no longer in kindgi.config.ts)`, or ⚠ `not registered: <KEY>
76
+ is not in .env, .env.local, .kindgi/secrets.env` (set the key, then
77
+ restart: the config isn't watched).
78
+ - A declaration applies at the next boot: the config isn't watched, so
79
+ restart `kindgi dev` after changing it. Each person, and each worktree,
80
+ sets the key in its own env files (step 1).
81
+ - A provider with that id that `kindgi dev` didn't register is left as it is;
82
+ if its region or models differ, a ⚠ line names the
83
+ `kindgi providers unregister` that lets the config's version apply.
84
+ - `.kindgi/dev/providers.json` is `kindgi dev`'s own record of what it
85
+ registered. `.kindgi/` is gitignored, so that record stays in this
86
+ worktree, and it isn't where a provider is declared.
87
+
88
+ Before pinning a Claude model, check its status on Anthropic's model
89
+ deprecations page (https://platform.claude.com/docs/en/about-claude/model-deprecations): a turn routed to a retired model fails. Prefer the
90
+ preset's default model. `anthropic` without `models` registers Opus 5.5,
91
+ Sonnet 5.5 (the default), Haiku 5.5 and Haiku 4.5. Each
92
+ preset names a default model (`metadata.defaultModel`, marked `(default)`
93
+ when it registers), which an agent with no preference gets. A preset
94
+ registered before 0.1.4 has none: unregister it and register it again.
95
+ The Claude 5.5 and GPT-6 models take no `temperature` (`"sampling": false`:
96
+ the call goes without it, with a `sampling-unsupported` warning), and a
97
+ model's `thinking` says how it thinks and the levels it takes (the presets
98
+ list each model's). An agent asks for a level with `thinking` in its model
99
+ settings; one the model doesn't take is rounded up, or to its highest, with
100
+ a `thinking-level-adjusted` warning. Thinking counts against
101
+ `maxOutputTokens` and bills as output.
102
+ The preset carries the models, context windows, default output caps (what
103
+ a call asks for when its agent sets no `maxOutputTokens`; not the model's own
104
+ limit) and current prices (`kindgi providers presets` lists the presets and
105
+ when their prices were checked); an entry's `maxOutputTokens` sets another cap. That's
106
+ all for Anthropic; go to step 4. The rest of this path is a spec of your
107
+ own, by hand.
108
+
109
+ **Staging and production: register by hand, once per runtime.** The
110
+ declaration drives `kindgi dev` only. A runtime `kindgi dev` doesn't run
111
+ (staging, production, Kindgi Cloud) gets its providers from
112
+ `kindgi providers register` against that runtime, once, and again when you
113
+ add a provider or change one. A registration is the runtime's, shared by
114
+ every environment it serves: register once in all when one runtime serves
115
+ both staging and prod, and once on each when they're separate runtimes. The
116
+ key isn't shared: set it first in each environment that runs the pack
117
+ (`kindgi secrets set ANTHROPIC_API_KEY --env=<environment>`), then:
118
+ ```sh
119
+ kindgi providers register --preset=anthropic --env=<env> # the preset's models
120
+ kindgi providers register --preset=anthropic --models=claude-sonnet-5-5 --env=<env> # just one
121
+ ```
122
+ - `--env` names one of the pack's environments. On a runtime that keeps
123
+ its values under one env, the key goes in that environment's project, and
124
+ `register` with it prints the `kindgi secrets set` line, to run again with
125
+ each other environment's name. On a runtime that serves several
126
+ environments, or with an `--env` that isn't one of the pack's,
127
+ `kindgi secrets set` asks for a `--scope`. On Kindgi Cloud, it's `prod`
128
+ (`kindgi-cloud.md`; mistake 1 in `common-mistakes.md`). `--max-output-tokens=<n>` sets
129
+ another output cap.
130
+ - To change a provider there, unregister it first (mistake 5 in `common-mistakes.md`), then
131
+ register it again.
132
+ - `kindgi deploy` doesn't register providers. `kindgi promote` checks the
133
+ target first and stops (exit 1) while it has no provider, naming
134
+ `kindgi providers register --preset=<name>`.
135
+ - Nothing in git records what a runtime has registered:
136
+ `kindgi providers list` against it shows it.
137
+ - Under `kindgi dev`, `kindgi providers register` puts a provider in this
138
+ worktree's dev database only, and leaves nothing to commit. Use it to try a
139
+ provider, then declare it.
140
+
141
+ **Step 2 (by hand) — write `provider.json`** at the pack root, and commit it:
142
+ like the declaration, it names its key (`secret_ref`) and never holds it.
143
+ Under `kindgi dev`, declare its body as a `spec` entry; on another runtime,
144
+ register it with `--spec` (step 3). One connection,
145
+ two models — matches how the Anthropic SDK actually works (the API
146
+ key is per-vendor; the model is per-call):
147
+ ```json
148
+ {
149
+ "metadata": {
150
+ "id": "anthropic",
151
+ "region": "us-east-1",
152
+ "models": [
153
+ {
154
+ "name": "claude-opus-5-5",
155
+ "contextWindow": 1000000,
156
+ "features": ["tool-use", "structured-output"],
157
+ "cost": {
158
+ "promptUsdPer1kTokens": 0.004,
159
+ "completionUsdPer1kTokens": 0.02
160
+ },
161
+ "description": "Most capable Opus — long-running agentic and knowledge work."
162
+ },
163
+ {
164
+ "name": "claude-sonnet-5-5",
165
+ "contextWindow": 1000000,
166
+ "features": ["tool-use", "structured-output"],
167
+ "cost": {
168
+ "promptUsdPer1kTokens": 0.002,
169
+ "completionUsdPer1kTokens": 0.01
170
+ },
171
+ "description": "Balanced performance/cost."
172
+ }
173
+ ],
174
+ "description": "Anthropic Claude via native adapter."
175
+ },
176
+ "adapter_id": "@kindgi/adapter-model-anthropic",
177
+ "secret_ref": { "envName": "local", "name": "ANTHROPIC_API_KEY" }
178
+ }
179
+ ```
180
+
181
+ > ⚠ **Units gotcha:** the field is `promptUsdPer1kTokens` (per THOUSAND
182
+ > tokens), but every vendor pricing page (Anthropic, OpenAI, Groq)
183
+ > advertises rates PER MILLION. Divide by 1000 before you paste. Sonnet
184
+ > 5.5 is "$2 / MTok input" → `0.002`, "$10 / MTok output" → `0.01`. A
185
+ > misplaced factor makes real cost look 1000× real; a $0.15 budget
186
+ > blows in the first turn.
187
+
188
+ **Step 3 — register:**
189
+ ```sh
190
+ kindgi providers register --spec=@provider.json
191
+ ```
192
+ Returns `{providerId: "anthropic"}` on success. Idempotent in the sense
193
+ that re-registering the same id returns `provider-already-registered`;
194
+ unregister first if the config actually changed.
195
+
196
+ **Step 4 — verify:**
197
+ ```sh
198
+ kindgi providers list
199
+ ```
200
+
201
+ **Step 5 — run:** any agent whose `capabilities: [{needs: [{feature:
202
+ 'tool-use'}]}]` is now routed to a (`anthropic`, `<one of the models>`)
203
+ tuple. The router picks by score; prefer a provider with
204
+ `preferredProvider` and pin a model with a `models: { allow: [...] }`
205
+ capability requirement (`router.md`).
206
+
207
+ Nothing to switch off: `dev-echo` is a fallback, so the new provider
208
+ answers every agent it satisfies. A turn that still lands on dev-echo
209
+ carries the `fallback-provider` and `dev-echo-not-a-model` warnings — see
210
+ mistake 9 in `common-mistakes.md`.
211
+
212
+ **The other one-key presets** work the same way, with their own key:
213
+ `--preset=openai` (`OPENAI_API_KEY`), `--preset=gemini-api` (`GEMINI_API_KEY`,
214
+ a Google AI Studio key; `gemini` is Vertex AI), `--preset=groq`
215
+ (`GROQ_API_KEY`) and `--preset=openrouter` (`OPENROUTER_API_KEY`).
216
+ `kindgi providers presets` lists them with their models.
@@ -0,0 +1,127 @@
1
+ # Path B — Hosted via OpenAI-compat
2
+
3
+ ## Contents
4
+
5
+ - Step 1 — set the key
6
+ - Step 2 — `provider.json`
7
+ - Steps 3 to 5 — register, verify, run
8
+ - Local via Ollama
9
+ - Any model you serve yourself
10
+
11
+ Works with **any** OpenAI-compatible endpoint. Same adapter, different
12
+ `baseURL`:
13
+
14
+ | Provider | baseURL |
15
+ |---|---|
16
+ | OpenAI | `https://api.openai.com/v1` |
17
+ | Groq | `https://api.groq.com/openai/v1` |
18
+ | Together | `https://api.together.xyz/v1` |
19
+ | Fireworks | `https://api.fireworks.ai/inference/v1` |
20
+ | DeepSeek | `https://api.deepseek.com/v1` |
21
+ | LiteLLM proxy | `http://localhost:4000/v1` |
22
+ | OpenRouter (a hosted gateway) | `https://openrouter.ai/api/v1` |
23
+
24
+ The connection carries the `baseURL` (in `adapter_config`);
25
+ each endpoint is a separate provider row because each has its own API
26
+ key + region. Within one row, list every model that endpoint exposes.
27
+
28
+ **Step 1 — set the key:**
29
+ ```sh
30
+ kindgi secrets set GROQ_API_KEY --env=local --scope=tenant
31
+ # Interactive prompt; paste and enter.
32
+ ```
33
+
34
+ **Step 2 — `provider.json`** (Groq, exposing two Llama variants):
35
+ ```json
36
+ {
37
+ "metadata": {
38
+ "id": "groq",
39
+ "region": "us-central-1",
40
+ "models": [
41
+ {
42
+ "name": "llama-3.3-70b-versatile",
43
+ "contextWindow": 128000,
44
+ "features": ["tool-use"],
45
+ "cost": {
46
+ "promptUsdPer1kTokens": 0.00059,
47
+ "completionUsdPer1kTokens": 0.00079
48
+ }
49
+ },
50
+ {
51
+ "name": "llama-3.1-8b-instant",
52
+ "contextWindow": 128000,
53
+ "features": ["tool-use"],
54
+ "cost": {
55
+ "promptUsdPer1kTokens": 0.00005,
56
+ "completionUsdPer1kTokens": 0.00008
57
+ },
58
+ "description": "Fast + cheap tier — routing, classification."
59
+ }
60
+ ],
61
+ "description": "Groq-hosted Llama via OpenAI-compat."
62
+ },
63
+ "adapter_id": "@kindgi/adapter-model-openai-compat",
64
+ "secret_ref": { "envName": "local", "name": "GROQ_API_KEY" },
65
+ "adapter_config": { "baseURL": "https://api.groq.com/openai/v1" }
66
+ }
67
+ ```
68
+
69
+ **Steps 3 to 5 — register, verify, run:**
70
+ ```sh
71
+ kindgi providers register --spec=@provider.json
72
+ kindgi providers list
73
+ ```
74
+ Then run an agent whose `capabilities.needs` one of the listed models'
75
+ `features` satisfy. Registering the same id again returns
76
+ `provider-already-registered`: unregister first when the config changed
77
+ (mistake 5 in `common-mistakes.md`).
78
+
79
+ ## Local via Ollama
80
+
81
+ For bigger local models — Ollama runs them, we point at the OpenAI-compat
82
+ endpoint it exposes:
83
+
84
+ ```json
85
+ {
86
+ "metadata": {
87
+ "id": "ollama",
88
+ "region": "local",
89
+ "models": [
90
+ {
91
+ "name": "llama3",
92
+ "contextWindow": 8192,
93
+ "features": ["tool-use"],
94
+ "cost": {
95
+ "promptUsdPer1kTokens": 0,
96
+ "completionUsdPer1kTokens": 0
97
+ }
98
+ }
99
+ ],
100
+ "description": "Local Ollama Llama 3 8B."
101
+ },
102
+ "adapter_id": "@kindgi/adapter-model-openai-compat",
103
+ "adapter_config": { "baseURL": "http://localhost:11434/v1" }
104
+ }
105
+ ```
106
+
107
+ Ollama doesn't check a key, so the row has no `secret_ref`: without one,
108
+ the adapter sends a placeholder key, as local servers expect.
109
+
110
+ **Any model you serve yourself** (Ollama, vLLM, llama.cpp's
111
+ `llama-server`, LM Studio) must do two things for an agent:
112
+ - **Call tools in the OpenAI format.** Serve it with tool calling on
113
+ (vLLM `--enable-auto-tool-choice --tool-call-parser <the model's>`,
114
+ `llama-server --jinja`), and pick a model that supports tools.
115
+ - **Answer without its thinking.** A thinking model (Qwen and others)
116
+ writes its reasoning first unless asked not to, and a typed answer then
117
+ isn't JSON (`output-schema-violation`). Turn thinking off on the server
118
+ (vLLM `--default-chat-template-kwargs '{"enable_thinking": false}'`,
119
+ `llama-server --reasoning off`), or, for a shared server you can't
120
+ reconfigure, per request from the provider row:
121
+ `"extraBody.chat_template_kwargs.enable_thinking": false` in
122
+ `adapter_config`. `adapter_config` is flat: one key per request field,
123
+ dots nest.
124
+
125
+ Assumes Ollama is installed + the model is pulled (`ollama pull llama3`).
126
+ See ollama.com for install / hardware requirements — Llama 3 8B needs
127
+ ~8GB RAM, Llama 3 70B needs ~48GB VRAM or ~140GB RAM.