@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.
- package/README.md +12 -5
- package/dist/cli.js +4 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +75 -19
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/approval-wait.d.ts +90 -0
- package/dist/commands/approval-wait.d.ts.map +1 -0
- package/dist/commands/approval-wait.js +154 -0
- package/dist/commands/approval-wait.js.map +1 -0
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +131 -14
- package/dist/commands/artifacts.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +48 -5
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/deploy.js +7 -3
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/deployments.d.ts.map +1 -1
- package/dist/commands/deployments.js +36 -13
- package/dist/commands/deployments.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +47 -14
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/eval-runs.d.ts.map +1 -1
- package/dist/commands/eval-runs.js +21 -9
- package/dist/commands/eval-runs.js.map +1 -1
- package/dist/commands/helpers.d.ts +31 -1
- package/dist/commands/helpers.d.ts.map +1 -1
- package/dist/commands/helpers.js +45 -2
- package/dist/commands/helpers.js.map +1 -1
- package/dist/commands/init.js +5 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mail-triggers.d.ts.map +1 -1
- package/dist/commands/mail-triggers.js +27 -3
- package/dist/commands/mail-triggers.js.map +1 -1
- package/dist/commands/promote.d.ts.map +1 -1
- package/dist/commands/promote.js +133 -11
- package/dist/commands/promote.js.map +1 -1
- package/dist/commands/provenance.d.ts.map +1 -1
- package/dist/commands/provenance.js +13 -5
- package/dist/commands/provenance.js.map +1 -1
- package/dist/commands/providers.d.ts.map +1 -1
- package/dist/commands/providers.js +47 -4
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/schedules.d.ts.map +1 -1
- package/dist/commands/schedules.js +25 -9
- package/dist/commands/schedules.js.map +1 -1
- package/dist/commands/skills.d.ts +16 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +122 -36
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/webhooks.d.ts.map +1 -1
- package/dist/commands/webhooks.js +21 -5
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +7 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -0
- package/dist/context.js.map +1 -1
- package/dist/dev/runtime-image.d.ts +1 -1
- package/dist/dev/runtime-image.js +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +14 -1
- package/dist/errors.js.map +1 -1
- package/dist/exports/plan.d.ts.map +1 -1
- package/dist/exports/plan.js +50 -0
- package/dist/exports/plan.js.map +1 -1
- package/dist/init/augment-scaffolder.d.ts +1 -1
- package/dist/init/augment-scaffolder.js +9 -8
- package/dist/init/augment-scaffolder.js.map +1 -1
- package/dist/init/java-augment.d.ts.map +1 -1
- package/dist/init/java-augment.js +7 -6
- package/dist/init/java-augment.js.map +1 -1
- package/dist/init/python-augment.d.ts.map +1 -1
- package/dist/init/python-augment.js +7 -6
- package/dist/init/python-augment.js.map +1 -1
- package/dist/init/scala-augment.js +7 -6
- package/dist/init/scala-augment.js.map +1 -1
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -1
- package/dist/providers/presets/anthropic.json +15 -3
- package/dist/providers/presets/azure-openai.json +10 -2
- package/dist/providers/presets/bedrock.json +6 -2
- package/dist/providers/presets/gemini-api.json +6 -2
- package/dist/providers/presets/openai.json +15 -3
- package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +21 -9
- package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +5 -3
- package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +202 -68
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +12 -188
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/common-mistakes.md +44 -0
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/how-it-works.md +41 -0
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/other-clients.md +19 -0
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/postgres.md +45 -0
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/several-servers.md +32 -0
- package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +49 -906
- package/dist/sdk-skills/kindgi-authoring-providers/bedrock.md +64 -0
- package/dist/sdk-skills/kindgi-authoring-providers/common-mistakes.md +125 -0
- package/dist/sdk-skills/kindgi-authoring-providers/keys-and-registration.md +58 -0
- package/dist/sdk-skills/kindgi-authoring-providers/kindgi-cloud.md +36 -0
- package/dist/sdk-skills/kindgi-authoring-providers/path-a-anthropic.md +216 -0
- package/dist/sdk-skills/kindgi-authoring-providers/path-b-openai-compat.md +127 -0
- package/dist/sdk-skills/kindgi-authoring-providers/path-c-onnx.md +97 -0
- package/dist/sdk-skills/kindgi-authoring-providers/path-d-vertex.md +95 -0
- package/dist/sdk-skills/kindgi-authoring-providers/router.md +113 -0
- package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +12 -387
- package/dist/sdk-skills/kindgi-authoring-tools/common-mistakes.md +135 -0
- package/dist/sdk-skills/kindgi-authoring-tools/declarative-http.md +34 -0
- package/dist/sdk-skills/kindgi-authoring-tools/imperative-handler.md +65 -0
- package/dist/sdk-skills/kindgi-authoring-tools/iterating-and-testing.md +45 -0
- package/dist/sdk-skills/kindgi-authoring-tools/secrets-and-connections.md +79 -0
- package/dist/sdk-skills/kindgi-authoring-tools/tool-flags.md +45 -0
- package/dist/sdk-skills/kindgi-fix-corrections/SKILL.md +13 -178
- package/dist/sdk-skills/kindgi-fix-corrections/make-the-change.md +25 -0
- package/dist/sdk-skills/kindgi-fix-corrections/publish-and-promote.md +76 -0
- package/dist/sdk-skills/kindgi-fix-corrections/pull-corrections.md +48 -0
- package/dist/sdk-skills/kindgi-fix-corrections/worked-example.md +27 -0
- package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +10 -180
- package/dist/sdk-skills/kindgi-framework-feedback/common-mistakes.md +19 -0
- package/dist/sdk-skills/kindgi-framework-feedback/editing-feedback-file.md +33 -0
- package/dist/sdk-skills/kindgi-framework-feedback/fields-and-entry-shape.md +53 -0
- package/dist/sdk-skills/kindgi-framework-feedback/hearing-back.md +24 -0
- package/dist/sdk-skills/kindgi-framework-feedback/sending.md +50 -0
- package/dist/sdk-skills/kindgi-getting-started/SKILL.md +24 -21
- package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +12 -4
- package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +6 -4
- package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +33 -23
- package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +19 -12
- package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +16 -16
- package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +18 -6
- package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +6 -4
- package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +39 -30
- package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +19 -9
- package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +24 -21
- package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +12 -4
- package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +6 -4
- package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +34 -23
- package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +15 -9
- package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +16 -16
- package/dist/sdk-skills/kindgi-using/SKILL.md +11 -11
- package/dist/templates/sample/README.md.tmpl +8 -7
- package/dist/templates/sample/agents/echo-agent/index.ts.tmpl +1 -1
- package/dist/templates/sample/kindgi.config.ts.tmpl +1 -1
- package/dist/templates/sample/package.json.tmpl +1 -1
- package/dist/templates/woocommerce/README.md.tmpl +9 -3
- package/package.json +13 -13
|
@@ -1,33 +1,25 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kindgi-authoring-providers
|
|
3
3
|
description: >
|
|
4
|
-
Wire an LLM model provider so a Kindgi pack's agents
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Default Credentials, no
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Groq / Llama / Gemini", "wire Anthropic", "use Vertex", "use Bedrock", "set up an API key for the agent",
|
|
20
|
-
"give the pack on Kindgi Cloud its model key",
|
|
21
|
-
"register the provider on staging",
|
|
22
|
-
or when an agent has been authored but the pack has no provider
|
|
23
|
-
registered yet, or another worktree or a teammate's `kindgi dev` has
|
|
24
|
-
none. Authoring agents themselves is covered by
|
|
25
|
-
kindgi-authoring-agents; getting-started is covered by
|
|
26
|
-
kindgi-getting-started.
|
|
4
|
+
Wire an LLM model provider so a Kindgi pack's agents call a real model:
|
|
5
|
+
Anthropic, the OpenAI-compatible adapter (OpenAI, Groq, OpenRouter,
|
|
6
|
+
vLLM, Ollama, any OpenAI-compatible endpoint), Gemini on Vertex AI
|
|
7
|
+
(Application Default Credentials, no key), Amazon Bedrock, or a local
|
|
8
|
+
in-process ONNX model. Covers where the key lives (`kindgi secrets
|
|
9
|
+
set`'s no-echo prompt, or the project's `.env` files, read at turn
|
|
10
|
+
time), one provider row with several models under `metadata.models[]`,
|
|
11
|
+
and how the router picks a (provider, model) per turn. Load this when
|
|
12
|
+
the user asks to "register a provider", "use Claude / GPT / Groq / Llama
|
|
13
|
+
/ Gemini", "wire Anthropic", "use Vertex", "use Bedrock", "set up an API
|
|
14
|
+
key for the agent", "give the pack on Kindgi Cloud its model key",
|
|
15
|
+
"register the provider on staging", or when an agent's replies come from
|
|
16
|
+
dev-echo because the pack, another worktree or a teammate's `kindgi dev`
|
|
17
|
+
has no provider yet. Authoring agents is kindgi-authoring-agents; first
|
|
18
|
+
steps are kindgi-getting-started.
|
|
27
19
|
type: core
|
|
28
20
|
library: "@kindgi/sdk"
|
|
29
|
-
version: "0.
|
|
30
|
-
sdk_version: "0.
|
|
21
|
+
version: "0.10.1"
|
|
22
|
+
sdk_version: "0.3.0-rc.0"
|
|
31
23
|
pack_languages: [node, python, java, scala]
|
|
32
24
|
sources:
|
|
33
25
|
- packages/adapters/model-anthropic/src/provider.ts
|
|
@@ -39,6 +31,7 @@ sources:
|
|
|
39
31
|
- packages/secrets-dotenv/src/index.ts
|
|
40
32
|
---
|
|
41
33
|
|
|
34
|
+
|
|
42
35
|
# Wiring a model provider for a Kindgi pack
|
|
43
36
|
|
|
44
37
|
> **Running `kindgi`:** in a Node project the CLI is a devDependency
|
|
@@ -57,876 +50,34 @@ agent turn. It is a **fallback** provider: it answers only when no other
|
|
|
57
50
|
registered provider fits the agent, so registering a real one takes over
|
|
58
51
|
with nothing else to change. This skill covers wiring a real one.
|
|
59
52
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
Project .env / .env.local dotenv SecretBinding runtime ProviderRegistry
|
|
64
|
-
───────────────────────── ───────────────────── ────────────────────────
|
|
65
|
-
ANTHROPIC_API_KEY=sk-... → resolve('local', hydrated per tenant on first
|
|
66
|
-
'ANTHROPIC_API_KEY') access; each row =
|
|
67
|
-
{ metadata, adapter_id,
|
|
68
|
-
secret_ref?,
|
|
69
|
-
adapter_config? }
|
|
70
|
-
│ │
|
|
71
|
-
▼ ▼
|
|
72
|
-
adapter factory ──── resolves apiKey lazily via closure
|
|
73
|
-
│
|
|
74
|
-
▼
|
|
75
|
-
ModelProvider ────── router picks a (provider, model)
|
|
76
|
-
tuple when an agent's
|
|
77
|
-
capabilities.needs matches
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Three moving parts:
|
|
81
|
-
1. **API key on disk** — in `kindgi dev` (environment `local`) the dotenv
|
|
82
|
-
secret binding reads the project's own env files: `.env`, then
|
|
83
|
-
`.env.local` on top (change the list with `dev.envFiles` in
|
|
84
|
-
`kindgi.config.ts`, `envFiles` under `[tool.kindgi.dev]` in a Python
|
|
85
|
-
pack's `pyproject.toml`, or `dev.envFiles` in a Java or Scala pack's
|
|
86
|
-
`kindgi.config.json`), then Kindgi's own `.kindgi/secrets.env` on top.
|
|
87
|
-
A key already in the app's `.env` just works. `kindgi secrets set`
|
|
88
|
-
(interactive, no-echo) writes `.kindgi/secrets.env`, a file the app
|
|
89
|
-
doesn't load (a framework loads `.env.local` into every route); `--app`
|
|
90
|
-
writes the app's file instead, for a value the app reads too (a webhook
|
|
91
|
-
signing secret). For non-sensitive values (log levels, region names,
|
|
92
|
-
feature flags), `kindgi env set NAME VALUE --env=local` writes the app's
|
|
93
|
-
`.env.local` with a positional value — never route real secrets
|
|
94
|
-
through it. `KINDGI_*`
|
|
95
|
-
names configure Kindgi itself and are never resolvable as secrets.
|
|
96
|
-
2. **Provider registration** — declared in the pack's config, which is
|
|
97
|
-
committed, and registered by `kindgi dev` at each boot; on a runtime
|
|
98
|
-
`kindgi dev` doesn't run, `kindgi providers register` (`POST /v1/providers`)
|
|
99
|
-
3. **Agent's `capabilities.needs`** — matched at the (provider, model) tuple level at turn time
|
|
100
|
-
|
|
101
|
-
**Registration body:** `{ metadata, adapter_id, secret_ref?, adapter_config? }`.
|
|
102
|
-
`secret_ref` points at the credential; `adapter_config` holds the adapter's
|
|
103
|
-
non-secret connection settings (a cloud project, a base URL) as flat string,
|
|
104
|
-
number or boolean values. Both are stored with the provider and handed to the
|
|
105
|
-
runtime; `kindgi providers list` / `get` show only `metadata`. Never put a
|
|
106
|
-
credential in `adapter_config`.
|
|
107
|
-
|
|
108
|
-
**Shape rule:** `ProviderMetadata.id` names the CONNECTION (e.g. `anthropic`,
|
|
109
|
-
`groq`, `local-onnx`); per-model fields (`name`, `contextWindow`, `cost`,
|
|
110
|
-
`features`) live inside `metadata.models[]`. One row can expose many models
|
|
111
|
-
under the same API key.
|
|
112
|
-
|
|
113
|
-
**Fallbacks:** `"fallback": true` in `metadata` makes a provider a
|
|
114
|
-
fallback — the router considers it only when no other provider satisfies
|
|
115
|
-
the agent's capability, and the turn's result then carries a
|
|
116
|
-
`fallback-provider` warning. `dev-echo` is one; a cheap local model can be
|
|
117
|
-
yours.
|
|
118
|
-
|
|
119
|
-
## On Kindgi Cloud: the key and its provider go under `prod`
|
|
120
|
-
|
|
121
|
-
A pack deployed with `kindgi deploy --hosted` runs on your workspace's
|
|
122
|
-
runtime on Kindgi Cloud, and that runtime serves the `prod` environment,
|
|
123
|
-
before and after you go live. The examples below use `--env=local`, for
|
|
124
|
-
`kindgi dev`. For Kindgi Cloud, name `prod` instead:
|
|
125
|
-
|
|
126
|
-
```sh
|
|
127
|
-
kindgi secrets set ANTHROPIC_API_KEY --env=prod --scope=tenant # a no-echo prompt
|
|
128
|
-
kindgi providers register --preset=anthropic --env=prod
|
|
129
|
-
kindgi deploy --hosted --env=prod
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
- The runtime reads a provider's key in the environment its
|
|
133
|
-
`secret_ref.envName` names, at tenant scope. Keep the key and the
|
|
134
|
-
provider both on `prod`. A provider registered without `--env` reads
|
|
135
|
-
`local`, not the `prod` key: `register` refuses when the pack's own env
|
|
136
|
-
files lack the key (its message names `--env`), and otherwise the first
|
|
137
|
-
turn can't find the key (mistake 1). By hand, `provider.json` has
|
|
138
|
-
`"secret_ref": { "envName": "prod", … }`.
|
|
139
|
-
- `kindgi secrets set` has no default environment: name `--env` every time.
|
|
140
|
-
- The deployment `kindgi deploy` sends names no environment. Its
|
|
141
|
-
`--env=prod` picks the pack's own `prod` settings, such as its signing
|
|
142
|
-
key.
|
|
143
|
-
- `kindgi deploy` doesn't register providers, and the providers declared in
|
|
144
|
-
the pack's config are `kindgi dev`'s only. Register once on `prod`, by
|
|
145
|
-
hand, and again when you add a provider or change one.
|
|
146
|
-
- OpenAI, the Gemini API, Groq and OpenRouter take the same two lines,
|
|
147
|
-
with their preset and key: `openai` and `OPENAI_API_KEY`, `gemini-api`
|
|
148
|
-
and `GEMINI_API_KEY`, `groq` and `GROQ_API_KEY`, `openrouter` and
|
|
149
|
-
`OPENROUTER_API_KEY`. Bedrock, Vertex AI and Azure OpenAI don't fit
|
|
150
|
-
them: see Amazon Bedrock and Path D below, and `kindgi providers
|
|
151
|
-
presets` for `azure-openai`'s settings.
|
|
152
|
-
|
|
153
|
-
The whole flow, from signing the CLI in to going live:
|
|
154
|
-
https://docs.kindgi.com/v0.2/hosted/deploy-your-agent/#your-model-key-and-its-provider
|
|
155
|
-
|
|
156
|
-
## Path A — Hosted, native Anthropic
|
|
157
|
-
|
|
158
|
-
Best fidelity to Anthropic's API (prompt caching, latest models, tool
|
|
159
|
-
use). Requires an `ANTHROPIC_API_KEY`.
|
|
160
|
-
|
|
161
|
-
A model's `structured-output` feature is a routing label: the model can
|
|
162
|
-
follow a JSON schema natively, but Kindgi's typed outputs use instructions,
|
|
163
|
-
then parse, check against the schema and repair, on every provider.
|
|
164
|
-
|
|
165
|
-
**Step 1 — set the key:**
|
|
166
|
-
```sh
|
|
167
|
-
kindgi secrets set ANTHROPIC_API_KEY --env=local --scope=tenant
|
|
168
|
-
# Prompts twice, echo disabled: paste the key, then again to confirm.
|
|
169
|
-
```
|
|
170
|
-
Under `kindgi dev`, this writes to `.kindgi/secrets.env` at the pack root
|
|
171
|
-
via the dotenv secret binding — or add `ANTHROPIC_API_KEY=…` to that file yourself; `kindgi dev`
|
|
172
|
-
also reads the app's `.env` / `.env.local`. If the pack lives inside an app
|
|
173
|
-
whose env file already has the key, it works as it is; `kindgi secrets copy`
|
|
174
|
-
gives Kindgi its own copy and never edits the app's files (the app may use
|
|
175
|
-
the key itself: leave removing it to the person). Keep env files gitignored. For pipelines/CI, pipe the value with
|
|
176
|
-
`echo -n "$KEY" | kindgi secrets set ANTHROPIC_API_KEY --env=local --scope=tenant --from-stdin`,
|
|
177
|
-
or read from a mode-0600 file with `--from-file <path>`. Never pass a
|
|
178
|
-
credential on argv.
|
|
179
|
-
|
|
180
|
-
For a pack on Kindgi Cloud, `--env=prod` instead: the key goes to your
|
|
181
|
-
workspace's runtime, not to a file (On Kindgi Cloud, above).
|
|
182
|
-
|
|
183
|
-
**Step 2 — declare it in the pack's config, and commit it.** `kindgi dev`
|
|
184
|
-
registers what the config declares on every boot: in every git worktree
|
|
185
|
-
(each has its own dev database), after `--reset`, and on a teammate's
|
|
186
|
-
machine. The declaration holds a key's name, never the key, so it goes in
|
|
187
|
-
git with the rest of the config. Committing it is how a teammate's
|
|
188
|
-
`kindgi dev`, or another worktree's, gets the same provider:
|
|
189
|
-
```ts
|
|
190
|
-
// in kindgi.config.ts
|
|
191
|
-
providers: [
|
|
192
|
-
{ preset: 'anthropic', models: ['claude-sonnet-5-5'] }, // key ANTHROPIC_API_KEY, from the env files
|
|
193
|
-
{ preset: 'gemini', project: 'acme-gcp', models: ['gemini-3.8-flash'] },
|
|
194
|
-
{ spec: { /* the provider.json body below */ } },
|
|
195
|
-
],
|
|
196
|
-
```
|
|
197
|
-
```toml
|
|
198
|
-
# in pyproject.toml: one table per provider, same keys
|
|
199
|
-
[[tool.kindgi.providers]]
|
|
200
|
-
preset = "anthropic"
|
|
201
|
-
models = ["claude-sonnet-5-5"]
|
|
202
|
-
```
|
|
203
|
-
In a Java or Scala pack's `kindgi.config.json`, the same keys:
|
|
204
|
-
`"providers": [{"preset": "anthropic", "models": ["claude-sonnet-5-5"]}]`.
|
|
205
|
-
- A preset entry takes `models`, the settings its preset asks for (`project`
|
|
206
|
-
for `gemini`; `resourceName` and `deployments` for `azure-openai`; `region`
|
|
207
|
-
for `bedrock`), `secret` (the key's name, in place of the preset's) and
|
|
208
|
-
`maxOutputTokens`, spelled the same in `pyproject.toml` and
|
|
209
|
-
`kindgi.config.json`. Its own settings are required and another preset's
|
|
210
|
-
are refused. `deployments` is a map of model to deployment
|
|
211
|
-
(`{ "gpt-6.1-sol": "gpt-6-1-sol" }`, a `[tool.kindgi.providers.deployments]`
|
|
212
|
-
table in `pyproject.toml`, model names quoted), not the `--deployments` flag's
|
|
213
|
-
`model=deployment,…`, and it names exactly the models the entry registers;
|
|
214
|
-
a `spec` entry is a `--spec` body. A
|
|
215
|
-
key is always a secret's name (`secret_ref`); a credential in
|
|
216
|
-
`adapter_config` is refused.
|
|
217
|
-
- Each boot prints `Providers from kindgi.config.ts:` (the pack's config file) with one line each:
|
|
218
|
-
`registered`, `unchanged`, `registered again (changed in kindgi.config.ts)`,
|
|
219
|
-
`unregistered (no longer in kindgi.config.ts)`, or ⚠ `not registered: <KEY>
|
|
220
|
-
is not in .env, .env.local, .kindgi/secrets.env` (set the key, then
|
|
221
|
-
restart: the config isn't watched).
|
|
222
|
-
- A declaration applies at the next boot: the config isn't watched, so
|
|
223
|
-
restart `kindgi dev` after changing it. Each person, and each worktree,
|
|
224
|
-
sets the key in its own env files (step 1).
|
|
225
|
-
- A provider with that id that `kindgi dev` didn't register is left as it is;
|
|
226
|
-
if its region or models differ, a ⚠ line names the
|
|
227
|
-
`kindgi providers unregister` that lets the config's version apply.
|
|
228
|
-
- `.kindgi/dev/providers.json` is `kindgi dev`'s own record of what it
|
|
229
|
-
registered. `.kindgi/` is gitignored, so that record stays in this
|
|
230
|
-
worktree, and it isn't where a provider is declared.
|
|
231
|
-
|
|
232
|
-
Before pinning a Claude model, check its status on Anthropic's model
|
|
233
|
-
deprecations page (https://platform.claude.com/docs/en/about-claude/model-deprecations): a turn routed to a retired model fails. Prefer the
|
|
234
|
-
preset's default model. `anthropic` without `models` registers Opus 5.5,
|
|
235
|
-
Sonnet 5.5 (the default), Haiku 5.5 and Haiku 4.5. Each
|
|
236
|
-
preset names a default model (`metadata.defaultModel`, marked `(default)`
|
|
237
|
-
when it registers), which an agent with no preference gets. A preset
|
|
238
|
-
registered before 0.1.4 has none: unregister it and register it again.
|
|
239
|
-
The Claude 5.5 and GPT-6 models take no `temperature` (`"sampling": false`:
|
|
240
|
-
the call goes without it, with a `sampling-unsupported` warning), and a
|
|
241
|
-
model's `thinking` says how it thinks; thinking counts against
|
|
242
|
-
`maxOutputTokens` and bills as output.
|
|
243
|
-
The preset carries the models, context windows, default output caps (what
|
|
244
|
-
a call asks for when its agent sets no `maxOutputTokens`; not the model's own
|
|
245
|
-
limit) and current prices (`kindgi providers presets` lists the presets and
|
|
246
|
-
when their prices were checked); an entry's `maxOutputTokens` sets another cap. That's
|
|
247
|
-
all for Anthropic; go to step 4. The rest of this path is a spec of your
|
|
248
|
-
own, by hand.
|
|
249
|
-
|
|
250
|
-
**Staging and production: register by hand, once per runtime.** The
|
|
251
|
-
declaration drives `kindgi dev` only. A runtime `kindgi dev` doesn't run
|
|
252
|
-
(staging, production, Kindgi Cloud) gets its providers from
|
|
253
|
-
`kindgi providers register` against that runtime, once, and again when you
|
|
254
|
-
add a provider or change one. A registration is the runtime's, shared by
|
|
255
|
-
every environment it serves: register once in all when one runtime serves
|
|
256
|
-
both staging and prod, and once on each when they're separate runtimes. The
|
|
257
|
-
key isn't shared: set it first in each environment that runs the pack
|
|
258
|
-
(`kindgi secrets set ANTHROPIC_API_KEY --env=<environment>`), then:
|
|
259
|
-
```sh
|
|
260
|
-
kindgi providers register --preset=anthropic --env=<env> # the preset's models
|
|
261
|
-
kindgi providers register --preset=anthropic --models=claude-sonnet-5-5 --env=<env> # just one
|
|
262
|
-
```
|
|
263
|
-
- `--env` names one of the pack's environments. On a runtime that keeps
|
|
264
|
-
its values under one env, the key goes in that environment's project, and
|
|
265
|
-
`register` with it prints the `kindgi secrets set` line, to run again with
|
|
266
|
-
each other environment's name. On a runtime that serves several
|
|
267
|
-
environments, or with an `--env` that isn't one of the pack's,
|
|
268
|
-
`kindgi secrets set` asks for a `--scope`. On Kindgi Cloud, it's `prod`
|
|
269
|
-
(On Kindgi Cloud, above; mistake 1). `--max-output-tokens=<n>` sets
|
|
270
|
-
another output cap.
|
|
271
|
-
- To change a provider there, unregister it first (mistake 5), then
|
|
272
|
-
register it again.
|
|
273
|
-
- `kindgi deploy` doesn't register providers. `kindgi promote` checks the
|
|
274
|
-
target first and stops (exit 1) while it has no provider, naming
|
|
275
|
-
`kindgi providers register --preset=<name>`.
|
|
276
|
-
- Nothing in git records what a runtime has registered:
|
|
277
|
-
`kindgi providers list` against it shows it.
|
|
278
|
-
- Under `kindgi dev`, `kindgi providers register` puts a provider in this
|
|
279
|
-
worktree's dev database only, and leaves nothing to commit. Use it to try a
|
|
280
|
-
provider, then declare it.
|
|
281
|
-
|
|
282
|
-
**Step 2 (by hand) — write `provider.json`** at the pack root, and commit it:
|
|
283
|
-
like the declaration, it names its key (`secret_ref`) and never holds it.
|
|
284
|
-
Under `kindgi dev`, declare its body as a `spec` entry; on another runtime,
|
|
285
|
-
register it with `--spec` (step 3). One connection,
|
|
286
|
-
two models — matches how the Anthropic SDK actually works (the API
|
|
287
|
-
key is per-vendor; the model is per-call):
|
|
288
|
-
```json
|
|
289
|
-
{
|
|
290
|
-
"metadata": {
|
|
291
|
-
"id": "anthropic",
|
|
292
|
-
"region": "us-east-1",
|
|
293
|
-
"models": [
|
|
294
|
-
{
|
|
295
|
-
"name": "claude-opus-5-5",
|
|
296
|
-
"contextWindow": 1000000,
|
|
297
|
-
"features": ["tool-use", "structured-output"],
|
|
298
|
-
"cost": {
|
|
299
|
-
"promptUsdPer1kTokens": 0.004,
|
|
300
|
-
"completionUsdPer1kTokens": 0.02
|
|
301
|
-
},
|
|
302
|
-
"description": "Most capable Opus — long-running agentic and knowledge work."
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
"name": "claude-sonnet-5-5",
|
|
306
|
-
"contextWindow": 1000000,
|
|
307
|
-
"features": ["tool-use", "structured-output"],
|
|
308
|
-
"cost": {
|
|
309
|
-
"promptUsdPer1kTokens": 0.002,
|
|
310
|
-
"completionUsdPer1kTokens": 0.01
|
|
311
|
-
},
|
|
312
|
-
"description": "Balanced performance/cost."
|
|
313
|
-
}
|
|
314
|
-
],
|
|
315
|
-
"description": "Anthropic Claude via native adapter."
|
|
316
|
-
},
|
|
317
|
-
"adapter_id": "@kindgi/adapter-model-anthropic",
|
|
318
|
-
"secret_ref": { "envName": "local", "name": "ANTHROPIC_API_KEY" }
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
> ⚠ **Units gotcha:** the field is `promptUsdPer1kTokens` (per THOUSAND
|
|
323
|
-
> tokens), but every vendor pricing page (Anthropic, OpenAI, Groq)
|
|
324
|
-
> advertises rates PER MILLION. Divide by 1000 before you paste. Sonnet
|
|
325
|
-
> 5.5 is "$2 / MTok input" → `0.002`, "$10 / MTok output" → `0.01`. A
|
|
326
|
-
> misplaced factor makes real cost look 1000× real; a $0.15 budget
|
|
327
|
-
> blows in the first turn.
|
|
328
|
-
|
|
329
|
-
**Step 3 — register:**
|
|
330
|
-
```sh
|
|
331
|
-
kindgi providers register --spec=@provider.json
|
|
332
|
-
```
|
|
333
|
-
Returns `{providerId: "anthropic"}` on success. Idempotent in the sense
|
|
334
|
-
that re-registering the same id returns `provider-already-registered`;
|
|
335
|
-
unregister first if the config actually changed.
|
|
336
|
-
|
|
337
|
-
**Step 4 — verify:**
|
|
338
|
-
```sh
|
|
339
|
-
kindgi providers list
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
**Step 5 — run:** any agent whose `capabilities: [{needs: [{feature:
|
|
343
|
-
'tool-use'}]}]` is now routed to a (`anthropic`, `<one of the models>`)
|
|
344
|
-
tuple. The router picks by score; prefer a provider with
|
|
345
|
-
`preferredProvider` and pin a model with a `models: { allow: [...] }`
|
|
346
|
-
capability requirement (see "How the router picks…" below).
|
|
347
|
-
|
|
348
|
-
Nothing to switch off: `dev-echo` is a fallback, so the new provider
|
|
349
|
-
answers every agent it satisfies. A turn that still lands on dev-echo
|
|
350
|
-
carries the `fallback-provider` and `dev-echo-not-a-model` warnings — see
|
|
351
|
-
mistake 9.
|
|
53
|
+
## How it fits together
|
|
352
54
|
|
|
353
|
-
**The
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
`
|
|
55
|
+
1. **The API key** sits in Kindgi's own `.kindgi/secrets.env`
|
|
56
|
+
(`kindgi secrets set NAME --env=local --scope=tenant`, a no-echo prompt)
|
|
57
|
+
or the project's `.env` / `.env.local`. The runtime reads it through the
|
|
58
|
+
dotenv secret binding at turn time. Never put a credential in
|
|
59
|
+
`adapter_config`.
|
|
60
|
+
2. **The provider** is declared in the pack's config, committed, and
|
|
61
|
+
registered by `kindgi dev` at each boot. On a runtime `kindgi dev`
|
|
62
|
+
doesn't run, `kindgi providers register` registers it. One row is one
|
|
63
|
+
connection (`metadata.id`, such as `anthropic`), its models under
|
|
64
|
+
`metadata.models[]`.
|
|
65
|
+
3. **The agent's `capabilities.needs`** is matched against each
|
|
66
|
+
(provider, model) at turn time.
|
|
358
67
|
|
|
359
|
-
##
|
|
68
|
+
## Your case: read this file
|
|
360
69
|
|
|
361
|
-
|
|
362
|
-
`baseURL`:
|
|
363
|
-
|
|
364
|
-
| Provider | baseURL |
|
|
70
|
+
| Your case | Read |
|
|
365
71
|
|---|---|
|
|
366
|
-
| OpenAI |
|
|
367
|
-
|
|
|
368
|
-
|
|
|
369
|
-
|
|
|
370
|
-
|
|
|
371
|
-
|
|
|
372
|
-
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
each endpoint is a separate provider row because each has its own API
|
|
376
|
-
key + region. Within one row, list every model that endpoint exposes.
|
|
377
|
-
|
|
378
|
-
**Step 1 — set the key:**
|
|
379
|
-
```sh
|
|
380
|
-
kindgi secrets set GROQ_API_KEY --env=local --scope=tenant
|
|
381
|
-
# Interactive prompt; paste and enter.
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
**Step 2 — `provider.json`** (Groq, exposing two Llama variants):
|
|
385
|
-
```json
|
|
386
|
-
{
|
|
387
|
-
"metadata": {
|
|
388
|
-
"id": "groq",
|
|
389
|
-
"region": "us-central-1",
|
|
390
|
-
"models": [
|
|
391
|
-
{
|
|
392
|
-
"name": "llama-3.3-70b-versatile",
|
|
393
|
-
"contextWindow": 128000,
|
|
394
|
-
"features": ["tool-use"],
|
|
395
|
-
"cost": {
|
|
396
|
-
"promptUsdPer1kTokens": 0.00059,
|
|
397
|
-
"completionUsdPer1kTokens": 0.00079
|
|
398
|
-
}
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
"name": "llama-3.1-8b-instant",
|
|
402
|
-
"contextWindow": 128000,
|
|
403
|
-
"features": ["tool-use"],
|
|
404
|
-
"cost": {
|
|
405
|
-
"promptUsdPer1kTokens": 0.00005,
|
|
406
|
-
"completionUsdPer1kTokens": 0.00008
|
|
407
|
-
},
|
|
408
|
-
"description": "Fast + cheap tier — routing, classification."
|
|
409
|
-
}
|
|
410
|
-
],
|
|
411
|
-
"description": "Groq-hosted Llama via OpenAI-compat."
|
|
412
|
-
},
|
|
413
|
-
"adapter_id": "@kindgi/adapter-model-openai-compat",
|
|
414
|
-
"secret_ref": { "envName": "local", "name": "GROQ_API_KEY" },
|
|
415
|
-
"adapter_config": { "baseURL": "https://api.groq.com/openai/v1" }
|
|
416
|
-
}
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
**Steps 3–5** same as Path A.
|
|
420
|
-
|
|
421
|
-
## Path C — Local via in-process ONNX (runtime from source only)
|
|
422
|
-
|
|
423
|
-
> ⚠️ **Not in the runtime image, so not under `kindgi dev`.** The adapter
|
|
424
|
-
> runs ONNX through `onnxruntime-node`, which ships glibc binaries only,
|
|
425
|
-
> and the Kindgi runtime image is Alpine (musl): the adapter can't load
|
|
426
|
-
> there (`Error loading shared library ld-linux-…`). `kindgi dev` runs
|
|
427
|
-
> that image, so this path fails under it. It works only when the
|
|
428
|
-
> runtime itself runs from source on macOS or a glibc Linux. **For a
|
|
429
|
-
> local model under `kindgi dev`, use Ollama** ([Local via Ollama](#local-via-ollama-via-path-b)).
|
|
430
|
-
|
|
431
|
-
> ⚠️ **Dev-only.** The in-process ONNX adapter writes weights to
|
|
432
|
-
> `~/.cache/huggingface/hub/` — a per-machine cache with no production
|
|
433
|
-
> recipe (no volume-mount recipe, no image-bake pattern, no offline
|
|
434
|
-
> mode, no SHA pinning). Good for smoke tests and CI runners that run
|
|
435
|
-
> the runtime from source and keep the same disk between runs. **Do not
|
|
436
|
-
> ship packs that rely on this adapter to production.** Use hosted
|
|
437
|
-
> providers (Path A) or Ollama (Path B) instead.
|
|
438
|
-
|
|
439
|
-
No API key. No network. Bundled with the framework — the adapter ships
|
|
440
|
-
`smollm2-360m` by default (~273 MB weights, cached at
|
|
441
|
-
`~/.cache/huggingface/hub/models--HuggingFaceTB--SmolLM2-360M-Instruct/`
|
|
442
|
-
after `kindgi adapters prepare`).
|
|
443
|
-
|
|
444
|
-
**Not for reasoning-heavy agents.** SmolLM 360M is fine for smoke
|
|
445
|
-
tests, canary agents, dev/CI. Real work needs a hosted model or a
|
|
446
|
-
larger local model via Ollama (Path B).
|
|
447
|
-
|
|
448
|
-
**`provider.json`** (single-model):
|
|
449
|
-
```json
|
|
450
|
-
{
|
|
451
|
-
"metadata": {
|
|
452
|
-
"id": "local-onnx",
|
|
453
|
-
"region": "in-process",
|
|
454
|
-
"models": [
|
|
455
|
-
{
|
|
456
|
-
"name": "smollm2-360m",
|
|
457
|
-
"contextWindow": 2048,
|
|
458
|
-
"features": ["tool-use"],
|
|
459
|
-
"cost": {
|
|
460
|
-
"promptUsdPer1kTokens": 0,
|
|
461
|
-
"completionUsdPer1kTokens": 0
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
],
|
|
465
|
-
"description": "Local ONNX smollm2-360m — dev + smoke tests."
|
|
466
|
-
},
|
|
467
|
-
"adapter_id": "@kindgi/adapter-model-in-process"
|
|
468
|
-
}
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
Multi-model variant — the in-process adapter loads each pipeline lazily,
|
|
472
|
-
so listing several models keeps memory low until they're actually
|
|
473
|
-
invoked:
|
|
474
|
-
|
|
475
|
-
```json
|
|
476
|
-
{
|
|
477
|
-
"metadata": {
|
|
478
|
-
"id": "local-onnx",
|
|
479
|
-
"region": "in-process",
|
|
480
|
-
"models": [
|
|
481
|
-
{ "name": "smollm2-135m", "contextWindow": 2048, "features": [],
|
|
482
|
-
"cost": { "promptUsdPer1kTokens": 0, "completionUsdPer1kTokens": 0 } },
|
|
483
|
-
{ "name": "smollm2-360m", "contextWindow": 2048, "features": ["tool-use"],
|
|
484
|
-
"cost": { "promptUsdPer1kTokens": 0, "completionUsdPer1kTokens": 0 } },
|
|
485
|
-
{ "name": "qwen3-0.6b", "contextWindow": 32768, "features": ["tool-use", "long-context"],
|
|
486
|
-
"cost": { "promptUsdPer1kTokens": 0, "completionUsdPer1kTokens": 0 } }
|
|
487
|
-
]
|
|
488
|
-
},
|
|
489
|
-
"adapter_id": "@kindgi/adapter-model-in-process"
|
|
490
|
-
}
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
No `secret_ref` needed. Register + **prepare** + run:
|
|
494
|
-
```sh
|
|
495
|
-
kindgi providers register --spec=@provider.json
|
|
496
|
-
kindgi adapters prepare @kindgi/adapter-model-in-process --model=smollm2-360m
|
|
497
|
-
kindgi runs start --agent=<agent-id> --input='{...}'
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
**Always `prepare` before `runs start`.** It downloads the ONNX weights
|
|
501
|
-
(~273 MB for smollm2-360m, ~30s on a typical connection) and streams
|
|
502
|
-
per-file progress. Skipping it works — the first model call downloads
|
|
503
|
-
lazily — but that stalls a request path on a multi-hundred-MB
|
|
504
|
-
fetch with no observability, which is bad in dev and unacceptable in
|
|
505
|
-
production. Skip only for scripted teardown where the model is already
|
|
506
|
-
cached (`~/.cache/huggingface/hub/models--HuggingFaceTB--SmolLM2-360M-Instruct/`).
|
|
507
|
-
|
|
508
|
-
`prepare` is idempotent: subsequent invocations are cache hits and
|
|
509
|
-
return almost instantly, so put it in the script that boots your
|
|
510
|
-
from-source runtime.
|
|
511
|
-
|
|
512
|
-
Multi-model providers: prepare each model separately.
|
|
513
|
-
```sh
|
|
514
|
-
kindgi adapters prepare @kindgi/adapter-model-in-process --model=smollm2-135m
|
|
515
|
-
kindgi adapters prepare @kindgi/adapter-model-in-process --model=smollm2-360m
|
|
516
|
-
kindgi adapters prepare @kindgi/adapter-model-in-process --model=qwen3-0.6b
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
## Local via Ollama (via Path B)
|
|
520
|
-
|
|
521
|
-
For bigger local models — Ollama runs them, we point at the OpenAI-compat
|
|
522
|
-
endpoint it exposes:
|
|
523
|
-
|
|
524
|
-
```json
|
|
525
|
-
{
|
|
526
|
-
"metadata": {
|
|
527
|
-
"id": "ollama",
|
|
528
|
-
"region": "local",
|
|
529
|
-
"models": [
|
|
530
|
-
{
|
|
531
|
-
"name": "llama3",
|
|
532
|
-
"contextWindow": 8192,
|
|
533
|
-
"features": ["tool-use"],
|
|
534
|
-
"cost": {
|
|
535
|
-
"promptUsdPer1kTokens": 0,
|
|
536
|
-
"completionUsdPer1kTokens": 0
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
],
|
|
540
|
-
"description": "Local Ollama Llama 3 8B."
|
|
541
|
-
},
|
|
542
|
-
"adapter_id": "@kindgi/adapter-model-openai-compat",
|
|
543
|
-
"adapter_config": { "baseURL": "http://localhost:11434/v1" }
|
|
544
|
-
}
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
Ollama doesn't check a key, so the row has no `secret_ref`: without one,
|
|
548
|
-
the adapter sends a placeholder key, as local servers expect.
|
|
549
|
-
|
|
550
|
-
**Any model you serve yourself** (Ollama, vLLM, llama.cpp's
|
|
551
|
-
`llama-server`, LM Studio) must do two things for an agent:
|
|
552
|
-
- **Call tools in the OpenAI format.** Serve it with tool calling on
|
|
553
|
-
(vLLM `--enable-auto-tool-choice --tool-call-parser <the model's>`,
|
|
554
|
-
`llama-server --jinja`), and pick a model that supports tools.
|
|
555
|
-
- **Answer without its thinking.** A thinking model (Qwen and others)
|
|
556
|
-
writes its reasoning first unless asked not to, and a typed answer then
|
|
557
|
-
isn't JSON (`output-schema-violation`). Turn thinking off on the server
|
|
558
|
-
(vLLM `--default-chat-template-kwargs '{"enable_thinking": false}'`,
|
|
559
|
-
`llama-server --reasoning off`), or, for a shared server you can't
|
|
560
|
-
reconfigure, per request from the provider row:
|
|
561
|
-
`"extraBody.chat_template_kwargs.enable_thinking": false` in
|
|
562
|
-
`adapter_config`. `adapter_config` is flat: one key per request field,
|
|
563
|
-
dots nest.
|
|
564
|
-
|
|
565
|
-
Assumes Ollama is installed + the model is pulled (`ollama pull llama3`).
|
|
566
|
-
See ollama.com for install / hardware requirements — Llama 3 8B needs
|
|
567
|
-
~8GB RAM, Llama 3 70B needs ~48GB VRAM or ~140GB RAM.
|
|
568
|
-
|
|
569
|
-
## Path D — Gemini on Vertex AI
|
|
570
|
-
|
|
571
|
-
Gemini through Google Cloud's Vertex AI. No API key: the adapter uses
|
|
572
|
-
**Google Application Default Credentials** — your `gcloud` login on a
|
|
573
|
-
laptop, the attached service account on Cloud Run (and other Google Cloud
|
|
574
|
-
runtimes). The same registration works in both.
|
|
575
|
-
|
|
576
|
-
**Step 1 — credentials:**
|
|
577
|
-
```sh
|
|
578
|
-
gcloud auth application-default login # once per laptop
|
|
579
|
-
```
|
|
580
|
-
The account (locally) or the service account (deployed) needs the
|
|
581
|
-
**Vertex AI User** role (`roles/aiplatform.user`) in the project. Running
|
|
582
|
-
outside Google Cloud: put a service-account key (its JSON) in a secret
|
|
583
|
-
(`kindgi secrets set GEMINI_SA_KEY --env=local --scope=tenant`) and add
|
|
584
|
-
`"secret_ref": { "envName": "local", "name": "GEMINI_SA_KEY" }`. A runtime
|
|
585
|
-
with `KINDGI_TENANT_HOST_ACCESS=isolated` requires that key: it doesn't lend
|
|
586
|
-
its own credentials to tenant configuration.
|
|
587
|
-
|
|
588
|
-
**Step 2 — `provider.json`:**
|
|
589
|
-
```json
|
|
590
|
-
{
|
|
591
|
-
"metadata": {
|
|
592
|
-
"id": "gemini",
|
|
593
|
-
"region": "global",
|
|
594
|
-
"models": [
|
|
595
|
-
{
|
|
596
|
-
"name": "gemini-3.8-flash",
|
|
597
|
-
"contextWindow": 1048576,
|
|
598
|
-
"features": ["tool-use", "structured-output", "long-context"],
|
|
599
|
-
"maxOutputTokens": 65536,
|
|
600
|
-
"thinking": { "mode": "adaptive", "lowest": "low" },
|
|
601
|
-
"cost": { "promptUsdPer1kTokens": 0.00075, "completionUsdPer1kTokens": 0.00375 }
|
|
602
|
-
},
|
|
603
|
-
{
|
|
604
|
-
"name": "gemini-3.5-flash-lite",
|
|
605
|
-
"contextWindow": 1048576,
|
|
606
|
-
"features": ["tool-use", "structured-output", "long-context"],
|
|
607
|
-
"maxOutputTokens": 65536,
|
|
608
|
-
"thinking": { "mode": "adaptive", "lowest": "minimal" },
|
|
609
|
-
"cost": { "promptUsdPer1kTokens": 0.0003, "completionUsdPer1kTokens": 0.0025 }
|
|
610
|
-
}
|
|
611
|
-
]
|
|
612
|
-
},
|
|
613
|
-
"adapter_id": "@kindgi/adapter-model-gemini",
|
|
614
|
-
"adapter_config": { "project": "<your-gcp-project-id>" }
|
|
615
|
-
}
|
|
616
|
-
```
|
|
617
|
-
- `adapter_config.project` is required: the Google Cloud project Vertex
|
|
618
|
-
bills and authorises against.
|
|
619
|
-
- `metadata.region` is the Vertex location: `global`, or a region such as
|
|
620
|
-
`us-central1` or `northamerica-northeast1` when data must stay in one
|
|
621
|
-
place. `unspecified` means `global`. Different locations are different
|
|
622
|
-
provider rows. Check that the location serves the model: Gemini 3.8 Flash
|
|
623
|
-
isn't served from `us-central1`.
|
|
624
|
-
- Don't register `gemini-2.5-pro` or `gemini-2.5-flash`: Vertex AI retires
|
|
625
|
-
both on 2026-10-20.
|
|
626
|
-
- Rates are per 1K tokens, from Google's published pricing; check them
|
|
627
|
-
before relying on budgets. Thinking tokens bill as output, and Gemini 3.8
|
|
628
|
-
Flash thinks by default. `gemini-3.8-flash`'s rates above are Google's
|
|
629
|
-
launch price, through 2026-12-31 ($0.0015 / $0.0075 from 2027-01-01).
|
|
630
|
-
`longContext` (`{ thresholdTokens, promptUsdPer1kTokens,
|
|
631
|
-
completionUsdPer1kTokens }` in a model's `cost`) switches the whole call
|
|
632
|
-
to the higher rates past the threshold; `cachedPromptMultiplier` (default 0.25) prices cached
|
|
633
|
-
prompt tokens.
|
|
634
|
-
- `thinking` is how the model thinks, as the preset has it. `lowest` is
|
|
635
|
-
the least level it takes, which a judge's call asks for.
|
|
636
|
-
- To make a model think less, set `adapter_config.thinkingLevels`, a level
|
|
637
|
-
for each model it names: `"thinkingLevels": "gemini-3.8-flash=low"`. The
|
|
638
|
-
levels are `minimal`, `low`, `medium` and `high`. A named model needs
|
|
639
|
-
`thinking` in its entry and a level no lower than its `lowest`, or the
|
|
640
|
-
registration is refused. A model it doesn't name thinks as Google sets.
|
|
641
|
-
It takes effect from the 0.2.0-rc.1 adapter on; an older one ignores it.
|
|
642
|
-
|
|
643
|
-
**Step 3 — register and check:**
|
|
644
|
-
```sh
|
|
645
|
-
kindgi providers register --spec=@provider.json
|
|
646
|
-
kindgi providers list
|
|
647
|
-
```
|
|
648
|
-
Or skip step 2: `kindgi providers register --preset=gemini --project=<your-gcp-project-id>`
|
|
649
|
-
registers both models above.
|
|
650
|
-
Then pin it from an agent with `preferredProvider: 'gemini'` (and a model
|
|
651
|
-
with `preferredModel`; in Python, `preferred_provider="gemini"` and
|
|
652
|
-
`preferred_model=…`; in Java, `.set("preferredProvider", "gemini")`), or let
|
|
653
|
-
the router pick by capability.
|
|
654
|
-
|
|
655
|
-
## Amazon Bedrock
|
|
656
|
-
|
|
657
|
-
Nova, Claude and GPT on Amazon Bedrock. The `bedrock` preset signs in as the
|
|
658
|
-
runtime's own AWS identity (`KINDGI_AWS_IDENTITY` says where it comes from),
|
|
659
|
-
so it takes no key:
|
|
660
|
-
```sh
|
|
661
|
-
kindgi providers register --preset=bedrock --region=us-east-2
|
|
662
|
-
kindgi providers register --preset=bedrock --region=us-east-2 \
|
|
663
|
-
--models=us.anthropic.claude-haiku-4-5-20251001-v1:0 # Claude, not Nova Pro
|
|
664
|
-
```
|
|
665
|
-
`--region` is the US Region the account uses Bedrock in: the preset's models
|
|
666
|
-
are US cross-region inference profiles. Its default model is Amazon Nova Pro
|
|
667
|
-
(`us.amazon.nova-pro-v1:0`). Claude and GPT also need the AWS account's
|
|
668
|
-
access to their vendor's models
|
|
669
|
-
(https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).
|
|
670
|
-
|
|
671
|
-
**On a runtime with `KINDGI_TENANT_HOST_ACCESS=isolated`, use a Bedrock API
|
|
672
|
-
key.** That runtime doesn't lend its own credentials to tenant configuration,
|
|
673
|
-
so it refuses the preset at registration and stores nothing:
|
|
674
|
-
```text
|
|
675
|
-
✗ /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.
|
|
676
|
-
```
|
|
677
|
-
`--secret` doesn't change that: the preset still signs in as the runtime.
|
|
678
|
-
Register from a spec whose `adapter_config.auth` is `api-key` and whose
|
|
679
|
-
`secret_ref` names the key:
|
|
680
|
-
|
|
681
|
-
1. **A long-term Bedrock API key**, made in the Region the provider uses. A
|
|
682
|
-
short-term key lasts 12 hours at most, so a registration can't keep one,
|
|
683
|
-
and a key works only in the Region it was made in. AWS recommends
|
|
684
|
-
long-term keys for exploration only: tell the person so, with AWS's page
|
|
685
|
-
(https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html).
|
|
686
|
-
2. **Stored as a tenant secret**, with the no-echo prompt:
|
|
687
|
-
`kindgi secrets set BEDROCK_API_KEY --env=production --scope=tenant`.
|
|
688
|
-
3. **Registered:** `kindgi providers register --spec=@bedrock.json`, with
|
|
689
|
-
```json
|
|
690
|
-
{
|
|
691
|
-
"adapter_id": "@kindgi/adapter-model-bedrock",
|
|
692
|
-
"adapter_config": { "auth": "api-key" },
|
|
693
|
-
"secret_ref": { "envName": "production", "name": "BEDROCK_API_KEY" },
|
|
694
|
-
"metadata": {
|
|
695
|
-
"id": "bedrock",
|
|
696
|
-
"region": "us-east-2",
|
|
697
|
-
"models": [
|
|
698
|
-
{ "name": "us.anthropic.claude-haiku-4-5-20251001-v1:0", "contextWindow": 200000,
|
|
699
|
-
"maxOutputTokens": 16000, "features": ["tool-use", "parallel-tool-use"],
|
|
700
|
-
"cost": { "promptUsdPer1kTokens": 0.0011, "completionUsdPer1kTokens": 0.0055 } }
|
|
701
|
-
]
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
One provider is one Region and one key: another Region is another provider,
|
|
707
|
-
with a key made there. The key is read when a turn calls the model, not at
|
|
708
|
-
registration.
|
|
709
|
-
|
|
710
|
-
The same holds for the other providers that can sign in as the runtime on
|
|
711
|
-
`isolated`. Gemini on Vertex AI takes a service-account key in `secret_ref`
|
|
712
|
-
(Path D). Azure OpenAI's `auth: entra` is refused: use the `azure-openai`
|
|
713
|
-
preset, with the resource's key. A provider registered before the runtime
|
|
714
|
-
moved to `isolated` that signs in as the runtime isn't used there: a turn
|
|
715
|
-
that needs it fails with `422 capability-routing-failed`. Unregister it, and
|
|
716
|
-
register it again with a key.
|
|
717
|
-
|
|
718
|
-
Docs: https://docs.kindgi.com/v0.2/guides/models/#with-a-bedrock-api-key
|
|
719
|
-
|
|
720
|
-
## How the router picks between multiple providers + models
|
|
721
|
-
|
|
722
|
-
When an agent turn fires, the router expands each registered provider
|
|
723
|
-
into one entry per model (`metadata.models[]`), filters the resulting
|
|
724
|
-
(provider, model) tuples against the agent's `capabilities.needs` (and
|
|
725
|
-
tenant policy), then sorts survivors in this order:
|
|
726
|
-
|
|
727
|
-
1. **Preferred provider / model.** Tuples matching the agent's
|
|
728
|
-
`preferredProvider` and `preferredModel` are promoted to the front.
|
|
729
|
-
- Both set → promote the exact tuple.
|
|
730
|
-
- Only `preferredModel` set → promote any provider exposing that model.
|
|
731
|
-
- Only `preferredProvider` set → promote every model of that provider.
|
|
732
|
-
`defineAgent` takes both (`preferredProvider`, `preferredModel`), and
|
|
733
|
-
so does a Python `Agent` (`preferred_provider=`, `preferred_model=`) and
|
|
734
|
-
a Java `Agent.define(…)` (`set("preferredProvider", …)`).
|
|
735
|
-
2. **`capability.prefer[]` weights.** If the agent's capability
|
|
736
|
-
declares `prefer: [{feature: 'thinking', weight: 3}, ...]`, tuples
|
|
737
|
-
with matching model features (or provider attributes) get higher
|
|
738
|
-
scores. Sorted by summed score, descending.
|
|
739
|
-
3. **Deterministic tiebreak.** When scores tie, tuples sort by provider
|
|
740
|
-
id, then the provider's `defaultModel` before its other models, then
|
|
741
|
-
model name — replay-safe and stable. A provider without a
|
|
742
|
-
`defaultModel` falls back to its first model by name.
|
|
743
|
-
|
|
744
|
-
**Practical rule:** preferences are soft — they rank, they don't
|
|
745
|
-
exclude. To guarantee which model runs, make it a hard requirement in
|
|
746
|
-
the capability: `{ models: { allow: ['claude-sonnet-5-5'] } }` (and
|
|
747
|
-
`{ providers: { allow: ['anthropic'] } }` to pin the connection). If no
|
|
748
|
-
registered tuple satisfies it, the turn fails with
|
|
749
|
-
`capability-routing-failed` instead of silently using another model.
|
|
750
|
-
|
|
751
|
-
**A/B testing a specific agent across models within one Anthropic
|
|
752
|
-
registration:**
|
|
753
|
-
|
|
754
|
-
```ts
|
|
755
|
-
// agents/weather-agent-sonnet/index.ts
|
|
756
|
-
defineAgent({
|
|
757
|
-
id: 'my-pack.weather-agent-sonnet',
|
|
758
|
-
// …same name, instructions, tools, retrieval and guardrails as the opus variant
|
|
759
|
-
capabilities: [
|
|
760
|
-
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['claude-sonnet-5-5'] } }] },
|
|
761
|
-
],
|
|
762
|
-
preferredProvider: 'anthropic',
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
// agents/weather-agent-opus/index.ts
|
|
766
|
-
defineAgent({
|
|
767
|
-
id: 'my-pack.weather-agent-opus',
|
|
768
|
-
// …
|
|
769
|
-
capabilities: [
|
|
770
|
-
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['claude-opus-5-5'] } }] },
|
|
771
|
-
],
|
|
772
|
-
preferredProvider: 'anthropic',
|
|
773
|
-
});
|
|
774
|
-
```
|
|
775
|
-
|
|
776
|
-
The same pair in a Python pack (`kindgi.Agent`; module-level, one file each):
|
|
777
|
-
|
|
778
|
-
```python
|
|
779
|
-
# agents/weather_agent_sonnet.py
|
|
780
|
-
weather_agent_sonnet = Agent(
|
|
781
|
-
id="my-pack.weather-agent-sonnet",
|
|
782
|
-
# …same version, name, instructions, tools and guardrails as the opus variant
|
|
783
|
-
capabilities=[
|
|
784
|
-
{"needs": [{"feature": "tool-use"}, {"models": {"allow": ["claude-sonnet-5-5"]}}]},
|
|
785
|
-
],
|
|
786
|
-
preferred_provider="anthropic",
|
|
787
|
-
)
|
|
788
|
-
|
|
789
|
-
# agents/weather_agent_opus.py
|
|
790
|
-
weather_agent_opus = Agent(
|
|
791
|
-
id="my-pack.weather-agent-opus",
|
|
792
|
-
# …
|
|
793
|
-
capabilities=[
|
|
794
|
-
{"needs": [{"feature": "tool-use"}, {"models": {"allow": ["claude-opus-5-5"]}}]},
|
|
795
|
-
],
|
|
796
|
-
preferred_provider="anthropic",
|
|
797
|
-
)
|
|
798
|
-
```
|
|
799
|
-
|
|
800
|
-
Both agents share the tool + instructions; only the pinned model
|
|
801
|
-
differs. One Anthropic provider registration + one API key covers
|
|
802
|
-
both. Register the provider once, then invoke each agent to compare
|
|
803
|
-
outputs on the same inputs.
|
|
804
|
-
|
|
805
|
-
**A/B testing across vendors:**
|
|
806
|
-
|
|
807
|
-
```ts
|
|
808
|
-
defineAgent({
|
|
809
|
-
id: 'my-pack.weather-agent-groq',
|
|
810
|
-
// …
|
|
811
|
-
capabilities: [
|
|
812
|
-
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['llama-3.3-70b-versatile'] } }] },
|
|
813
|
-
],
|
|
814
|
-
preferredProvider: 'groq',
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
defineAgent({
|
|
818
|
-
id: 'my-pack.weather-agent-anthropic',
|
|
819
|
-
// …
|
|
820
|
-
capabilities: [
|
|
821
|
-
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['claude-sonnet-5-5'] } }] },
|
|
822
|
-
],
|
|
823
|
-
preferredProvider: 'anthropic',
|
|
824
|
-
});
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
## Common mistakes
|
|
828
|
-
|
|
829
|
-
0. **`adapter_id` uses the short name.** The `adapter_id` field must
|
|
830
|
-
be the FULL npm package name of the adapter — `"@kindgi/adapter-model-anthropic"`,
|
|
831
|
-
NOT `"anthropic"`. Adapters are registered with the runtime under
|
|
832
|
-
their full package names, and a short name matches none of them, so
|
|
833
|
-
registering is refused: the runtime has no adapter by that name
|
|
834
|
-
(`✗ /adapter_id: …`). The model adapters are
|
|
835
|
-
`@kindgi/adapter-model-anthropic`, `@kindgi/adapter-model-gemini`,
|
|
836
|
-
`@kindgi/adapter-model-openai-compat`,
|
|
837
|
-
`@kindgi/adapter-model-azure-openai`, `@kindgi/adapter-model-bedrock` and
|
|
838
|
-
`@kindgi/adapter-model-in-process`; `kindgi providers presets` shows
|
|
839
|
-
the id each preset uses.
|
|
840
|
-
|
|
841
|
-
1. **`envName` mismatch between the key and the provider's `secret_ref`.**
|
|
842
|
-
The runtime reads a provider's key in the environment its
|
|
843
|
-
`secret_ref.envName` names, at tenant scope. The SecretBinding refuses
|
|
844
|
-
to cross-resolve, so a key held under another environment gives
|
|
845
|
-
`secret-not-found` at agent-turn time. Where each one lands:
|
|
846
|
-
`kindgi secrets set` needs `--env=<name>`; `kindgi providers register
|
|
847
|
-
--preset` writes `--env`'s name, or `local` without it; a `--spec` file
|
|
848
|
-
names its own (`"secret_ref": {"envName": "production", ...}`). Under
|
|
849
|
-
`kindgi dev`, `local` is the project's env files (`.env`, `.env.local`)
|
|
850
|
-
and `.kindgi/secrets.env`; any other name is `.env.<envName>`. Match
|
|
851
|
-
them. On Kindgi Cloud, both are `prod`.
|
|
852
|
-
|
|
853
|
-
2. **Missing `features` on the model.** Agent declares
|
|
854
|
-
`capabilities: [{needs: [{feature: 'tool-use'}]}]`; at least one
|
|
855
|
-
model inside `metadata.models[]` must list `"features":
|
|
856
|
-
["tool-use"]` or the router filters every tuple out. If `kindgi
|
|
857
|
-
runs start` returns "no provider satisfies capability", check the
|
|
858
|
-
per-model `features` list — not a provider-level field anymore.
|
|
859
|
-
|
|
860
|
-
3. **Empty `models[]`.** Registration rejects with `empty-models`. Every
|
|
861
|
-
provider row must expose at least one model. Duplicate `name` within
|
|
862
|
-
the same array is also rejected (`duplicate-model-name`).
|
|
863
|
-
|
|
864
|
-
4. **Setting `secret_ref` for the in-process adapter.** `in-process`
|
|
865
|
-
ignores `secret_ref` — no key needed. Leaving it in is harmless but
|
|
866
|
-
noisy.
|
|
867
|
-
|
|
868
|
-
5. **Registering the same provider id twice with different config.**
|
|
869
|
-
Returns `409 provider-already-registered`. Unregister first:
|
|
870
|
-
```sh
|
|
871
|
-
kindgi providers unregister <provider-id>
|
|
872
|
-
```
|
|
873
|
-
Then re-register.
|
|
874
|
-
|
|
875
|
-
6. **Key not found by the runtime.** `kindgi dev` reads the env files
|
|
876
|
-
at the PACK ROOT (the directory with `kindgi.config.ts`, a Python
|
|
877
|
-
pack's `pyproject.toml` with `[tool.kindgi]`, or a Java or Scala pack's
|
|
878
|
-
`kindgi.config.json`) — `.env` and
|
|
879
|
-
`.env.local`, or whatever `dev.envFiles` lists; the boot log prints
|
|
880
|
-
which files it found. A `KINDGI_`-prefixed name is Kindgi runtime
|
|
881
|
-
config and never resolves as a secret. Outside `kindgi dev`, the
|
|
882
|
-
runtime resolves secrets through the deployment's `SecretBinding`
|
|
883
|
-
(a KMS- or database-backed store, for example).
|
|
884
|
-
|
|
885
|
-
7. **Forgetting to restart `kindgi dev` after registering a provider.**
|
|
886
|
-
You don't need to — provider registrations go to the running runtime
|
|
887
|
-
over HTTP (`POST /v1/providers`), which invalidates the tenant's
|
|
888
|
-
cached provider set. The next `kindgi runs start` sees the new
|
|
889
|
-
provider.
|
|
890
|
-
|
|
891
|
-
8. **Compound `preferredProvider` strings.** `preferredProvider` is a
|
|
892
|
-
provider (connection) id such as `'anthropic'`; the model is a
|
|
893
|
-
separate choice. A value like `'anthropic-claude-sonnet-5-5'`
|
|
894
|
-
(vendor + model baked together) matches no provider id, so the hint
|
|
895
|
-
does nothing. Pin the model with a `models: { allow: [...] }`
|
|
896
|
-
requirement instead.
|
|
897
|
-
|
|
898
|
-
9. **Replies still come from dev-echo** (`⚠ dev-echo isn't a real model: …`
|
|
899
|
-
then `Tool responded: …`; the turn's result has the `fallback-provider`
|
|
900
|
-
and `dev-echo-not-a-model` warnings). dev-echo is a fallback: it
|
|
901
|
-
answers only when no registered provider satisfies the agent. So your
|
|
902
|
-
provider doesn't — check its models' `features` against the agent's
|
|
903
|
-
`capabilities.needs` (mistake 2), a `models` / `providers` allow-list
|
|
904
|
-
that names nothing registered, and the tenant's policy. `kindgi
|
|
905
|
-
providers list` shows what is registered.
|
|
906
|
-
|
|
907
|
-
10. **A setting the adapter can't use.** Registering checks the spec
|
|
908
|
-
against its adapter (no network call, no key read) and refuses what
|
|
909
|
-
it can't use: `422 provider-config-invalid`, nothing stored, one line
|
|
910
|
-
per problem with its JSON-pointer path:
|
|
911
|
-
```text
|
|
912
|
-
Error [invalid-request]: Provider "ollama" doesn't fit adapter @kindgi/adapter-model-openai-compat: adapter_config.api must be one of responses, chat-completions.
|
|
913
|
-
✗ /adapter_config/api: adapter_config.api must be one of responses, chat-completions.
|
|
914
|
-
```
|
|
915
|
-
Fix each `✗` line's setting and register again. A key the adapter
|
|
916
|
-
needs is checked too (`✗ /secret_ref: …`); whether the key works, or
|
|
917
|
-
the endpoint answers, isn't (the first turn finds out). A
|
|
918
|
-
registration stored before 0.1.5 wasn't checked: `kindgi doctor`
|
|
919
|
-
names its problems (`GET /v1/providers/<id>/check`); unregister it
|
|
920
|
-
and register it again.
|
|
921
|
-
|
|
922
|
-
11. **A provider registered by hand under `kindgi dev`, with nothing
|
|
923
|
-
committed.** `kindgi providers register` puts it in this worktree's dev
|
|
924
|
-
database only. Another worktree, a `kindgi dev --reset`, or a
|
|
925
|
-
teammate's `kindgi dev` has no provider, and its turns land on
|
|
926
|
-
dev-echo (mistake 9). Declare the provider in the pack's config and
|
|
927
|
-
commit it (step 2). `.kindgi/dev/providers.json` isn't the file to
|
|
928
|
-
commit: it's `kindgi dev`'s local record of what it registered, and
|
|
929
|
-
`.kindgi/` is gitignored.
|
|
72
|
+
| Anthropic, or another one-key preset: OpenAI, the Gemini API, Groq, OpenRouter | [path-a-anthropic.md](path-a-anthropic.md) |
|
|
73
|
+
| Any OpenAI-compatible endpoint by hand, or a local model through Ollama | [path-b-openai-compat.md](path-b-openai-compat.md) |
|
|
74
|
+
| A local in-process ONNX model, with the runtime run from source | [path-c-onnx.md](path-c-onnx.md) |
|
|
75
|
+
| Gemini on Vertex AI, signed in with Application Default Credentials | [path-d-vertex.md](path-d-vertex.md) |
|
|
76
|
+
| Amazon Bedrock | [bedrock.md](bedrock.md) |
|
|
77
|
+
| The pack on Kindgi Cloud: the key and the provider on `prod` | [kindgi-cloud.md](kindgi-cloud.md) |
|
|
78
|
+
| Where keys are read from, the registration body, fallbacks | [keys-and-registration.md](keys-and-registration.md) |
|
|
79
|
+
| Several providers or models: which one answers | [router.md](router.md) |
|
|
80
|
+
| An error, or replies still from dev-echo | [common-mistakes.md](common-mistakes.md) |
|
|
930
81
|
|
|
931
82
|
## Verifying end-to-end
|
|
932
83
|
|
|
@@ -937,8 +88,9 @@ kindgi dev
|
|
|
937
88
|
# 1. Set the key (interactive, no-echo prompt)
|
|
938
89
|
kindgi secrets set ANTHROPIC_API_KEY --env=local --scope=tenant
|
|
939
90
|
|
|
940
|
-
# 2. Declare the provider in the pack's config (step 2
|
|
941
|
-
# restart `kindgi dev`: its boot prints
|
|
91
|
+
# 2. Declare the provider in the pack's config (step 2 of your path),
|
|
92
|
+
# commit it, then restart `kindgi dev`: its boot prints
|
|
93
|
+
# `anthropic: registered`
|
|
942
94
|
|
|
943
95
|
# 3. Confirm it's there (list shows nested models per provider)
|
|
944
96
|
kindgi providers list
|
|
@@ -954,19 +106,10 @@ there: set the key with `--env=prod` (step 1), register the provider by
|
|
|
954
106
|
hand (`kindgi providers register --preset=anthropic --env=prod`), deploy
|
|
955
107
|
with `kindgi deploy --hosted --env=prod`, then run the agent.
|
|
956
108
|
|
|
957
|
-
If the run completes with `status: "completed"`, the whole chain works
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
## References
|
|
963
|
-
|
|
964
|
-
- `packages/adapters/model-anthropic/src/provider.ts` — Anthropic adapter
|
|
965
|
-
- `packages/adapters/model-openai-compat/src/provider.ts` — Universal adapter, full list of tested endpoints in header comment
|
|
966
|
-
- `packages/adapters/model-in-process/src/provider.ts` — Local ONNX adapter
|
|
967
|
-
- `packages/adapters/model-bedrock/src/config.ts` — Amazon Bedrock's settings, and how it signs in
|
|
968
|
-
- `packages/api/src/routes/providers.ts` — `POST /v1/providers` route
|
|
969
|
-
- `packages/secrets-dotenv/src/index.ts` — Dev-mode secret binding
|
|
109
|
+
If the run completes with `status: "completed"`, the whole chain works.
|
|
110
|
+
`secret-not-found` points at the key, "no provider satisfies capability" at
|
|
111
|
+
the model's `features`, and dev-echo's canned reply at mistake 9 in
|
|
112
|
+
[common-mistakes.md](common-mistakes.md).
|
|
970
113
|
|
|
971
114
|
## When the framework itself is the problem
|
|
972
115
|
|