@kindgi/cli 0.2.0 → 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.d.ts.map +1 -1
- package/dist/dev/runtime-image.js +1 -1
- package/dist/dev/runtime-image.js.map +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
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Path C — Local via in-process ONNX (runtime from source only)
|
|
2
|
+
|
|
3
|
+
> ⚠️ **Not in the runtime image, so not under `kindgi dev`.** The adapter
|
|
4
|
+
> runs ONNX through `onnxruntime-node`, which ships glibc binaries only,
|
|
5
|
+
> and the Kindgi runtime image is Alpine (musl): the adapter can't load
|
|
6
|
+
> there (`Error loading shared library ld-linux-…`). `kindgi dev` runs
|
|
7
|
+
> that image, so this path fails under it. It works only when the
|
|
8
|
+
> runtime itself runs from source on macOS or a glibc Linux. **For a
|
|
9
|
+
> local model under `kindgi dev`, use Ollama** (`path-b-openai-compat.md`).
|
|
10
|
+
|
|
11
|
+
> ⚠️ **Dev-only.** The in-process ONNX adapter writes weights to
|
|
12
|
+
> `~/.cache/huggingface/hub/` — a per-machine cache with no production
|
|
13
|
+
> recipe (no volume-mount recipe, no image-bake pattern, no offline
|
|
14
|
+
> mode, no SHA pinning). Good for smoke tests and CI runners that run
|
|
15
|
+
> the runtime from source and keep the same disk between runs. **Do not
|
|
16
|
+
> ship packs that rely on this adapter to production.** Use hosted
|
|
17
|
+
> providers (Path A) or Ollama (Path B) instead.
|
|
18
|
+
|
|
19
|
+
No API key. No network. Bundled with the framework — the adapter ships
|
|
20
|
+
`smollm2-360m` by default (~273 MB weights, cached at
|
|
21
|
+
`~/.cache/huggingface/hub/models--HuggingFaceTB--SmolLM2-360M-Instruct/`
|
|
22
|
+
after `kindgi adapters prepare`).
|
|
23
|
+
|
|
24
|
+
**Not for reasoning-heavy agents.** SmolLM 360M is fine for smoke
|
|
25
|
+
tests, canary agents, dev/CI. Real work needs a hosted model or a
|
|
26
|
+
larger local model via Ollama (Path B).
|
|
27
|
+
|
|
28
|
+
**`provider.json`** (single-model):
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"metadata": {
|
|
32
|
+
"id": "local-onnx",
|
|
33
|
+
"region": "in-process",
|
|
34
|
+
"models": [
|
|
35
|
+
{
|
|
36
|
+
"name": "smollm2-360m",
|
|
37
|
+
"contextWindow": 2048,
|
|
38
|
+
"features": ["tool-use"],
|
|
39
|
+
"cost": {
|
|
40
|
+
"promptUsdPer1kTokens": 0,
|
|
41
|
+
"completionUsdPer1kTokens": 0
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"description": "Local ONNX smollm2-360m — dev + smoke tests."
|
|
46
|
+
},
|
|
47
|
+
"adapter_id": "@kindgi/adapter-model-in-process"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Multi-model variant — the in-process adapter loads each pipeline lazily,
|
|
52
|
+
so listing several models keeps memory low until they're actually
|
|
53
|
+
invoked:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"metadata": {
|
|
58
|
+
"id": "local-onnx",
|
|
59
|
+
"region": "in-process",
|
|
60
|
+
"models": [
|
|
61
|
+
{ "name": "smollm2-135m", "contextWindow": 2048, "features": [],
|
|
62
|
+
"cost": { "promptUsdPer1kTokens": 0, "completionUsdPer1kTokens": 0 } },
|
|
63
|
+
{ "name": "smollm2-360m", "contextWindow": 2048, "features": ["tool-use"],
|
|
64
|
+
"cost": { "promptUsdPer1kTokens": 0, "completionUsdPer1kTokens": 0 } },
|
|
65
|
+
{ "name": "qwen3-0.6b", "contextWindow": 32768, "features": ["tool-use", "long-context"],
|
|
66
|
+
"cost": { "promptUsdPer1kTokens": 0, "completionUsdPer1kTokens": 0 } }
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"adapter_id": "@kindgi/adapter-model-in-process"
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
No `secret_ref` needed. Register + **prepare** + run:
|
|
74
|
+
```sh
|
|
75
|
+
kindgi providers register --spec=@provider.json
|
|
76
|
+
kindgi adapters prepare @kindgi/adapter-model-in-process --model=smollm2-360m
|
|
77
|
+
kindgi runs start --agent=<agent-id> --input='{...}'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Always `prepare` before `runs start`.** It downloads the ONNX weights
|
|
81
|
+
(~273 MB for smollm2-360m, ~30s on a typical connection) and streams
|
|
82
|
+
per-file progress. Skipping it works — the first model call downloads
|
|
83
|
+
lazily — but that stalls a request path on a multi-hundred-MB
|
|
84
|
+
fetch with no observability, which is bad in dev and unacceptable in
|
|
85
|
+
production. Skip only for scripted teardown where the model is already
|
|
86
|
+
cached (`~/.cache/huggingface/hub/models--HuggingFaceTB--SmolLM2-360M-Instruct/`).
|
|
87
|
+
|
|
88
|
+
`prepare` is idempotent: subsequent invocations are cache hits and
|
|
89
|
+
return almost instantly, so put it in the script that boots your
|
|
90
|
+
from-source runtime.
|
|
91
|
+
|
|
92
|
+
Multi-model providers: prepare each model separately.
|
|
93
|
+
```sh
|
|
94
|
+
kindgi adapters prepare @kindgi/adapter-model-in-process --model=smollm2-135m
|
|
95
|
+
kindgi adapters prepare @kindgi/adapter-model-in-process --model=smollm2-360m
|
|
96
|
+
kindgi adapters prepare @kindgi/adapter-model-in-process --model=qwen3-0.6b
|
|
97
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Path D — Gemini on Vertex AI
|
|
2
|
+
|
|
3
|
+
Gemini through Google Cloud's Vertex AI. No API key: the adapter uses
|
|
4
|
+
**Google Application Default Credentials** — your `gcloud` login on a
|
|
5
|
+
laptop, the attached service account on Cloud Run (and other Google Cloud
|
|
6
|
+
runtimes). The same registration works in both.
|
|
7
|
+
|
|
8
|
+
**Step 1 — credentials:**
|
|
9
|
+
```sh
|
|
10
|
+
gcloud auth application-default login # once per laptop
|
|
11
|
+
```
|
|
12
|
+
The account (locally) or the service account (deployed) needs the
|
|
13
|
+
**Vertex AI User** role (`roles/aiplatform.user`) in the project. Running
|
|
14
|
+
outside Google Cloud: put a service-account key (its JSON) in a secret
|
|
15
|
+
(`kindgi secrets set GEMINI_SA_KEY --env=local --scope=tenant`) and add
|
|
16
|
+
`"secret_ref": { "envName": "local", "name": "GEMINI_SA_KEY" }`. A runtime
|
|
17
|
+
with `KINDGI_TENANT_HOST_ACCESS=isolated` requires that key: it doesn't lend
|
|
18
|
+
its own credentials to tenant configuration.
|
|
19
|
+
|
|
20
|
+
**Step 2 — `provider.json`:**
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"metadata": {
|
|
24
|
+
"id": "gemini",
|
|
25
|
+
"region": "global",
|
|
26
|
+
"models": [
|
|
27
|
+
{
|
|
28
|
+
"name": "gemini-3.8-flash",
|
|
29
|
+
"contextWindow": 1048576,
|
|
30
|
+
"features": ["tool-use", "structured-output", "long-context"],
|
|
31
|
+
"maxOutputTokens": 65536,
|
|
32
|
+
"thinking": { "mode": "adaptive", "lowest": "low" },
|
|
33
|
+
"cost": { "promptUsdPer1kTokens": 0.00075, "completionUsdPer1kTokens": 0.00375 }
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "gemini-3.5-flash-lite",
|
|
37
|
+
"contextWindow": 1048576,
|
|
38
|
+
"features": ["tool-use", "structured-output", "long-context"],
|
|
39
|
+
"maxOutputTokens": 65536,
|
|
40
|
+
"thinking": { "mode": "adaptive", "lowest": "minimal" },
|
|
41
|
+
"cost": { "promptUsdPer1kTokens": 0.0003, "completionUsdPer1kTokens": 0.0025 }
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"adapter_id": "@kindgi/adapter-model-gemini",
|
|
46
|
+
"adapter_config": { "project": "<your-gcp-project-id>" }
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
- `adapter_config.project` is required: the Google Cloud project Vertex
|
|
50
|
+
bills and authorises against.
|
|
51
|
+
- `metadata.region` is the Vertex location: `global`, or a region such as
|
|
52
|
+
`us-central1` or `northamerica-northeast1` when data must stay in one
|
|
53
|
+
place. `unspecified` means `global`. Different locations are different
|
|
54
|
+
provider rows. Check that the location serves the model: Gemini 3.8 Flash
|
|
55
|
+
isn't served from `us-central1`.
|
|
56
|
+
- Don't register `gemini-2.5-pro` or `gemini-2.5-flash`: Vertex AI retires
|
|
57
|
+
both on 2026-10-20.
|
|
58
|
+
- Rates are per 1K tokens, from Google's published pricing; check them
|
|
59
|
+
before relying on budgets. Thinking tokens bill as output, and Gemini 3.8
|
|
60
|
+
Flash thinks by default. `gemini-3.8-flash`'s rates above are Google's
|
|
61
|
+
launch price, through 2026-12-31 ($0.0015 / $0.0075 from 2027-01-01).
|
|
62
|
+
`longContext` (`{ thresholdTokens, promptUsdPer1kTokens,
|
|
63
|
+
completionUsdPer1kTokens }` in a model's `cost`) switches the whole call
|
|
64
|
+
to the higher rates past the threshold; `cachedPromptMultiplier` (default 0.25) prices cached
|
|
65
|
+
prompt tokens.
|
|
66
|
+
- `thinking` is how the model thinks, as the preset has it. `lowest` is
|
|
67
|
+
the least level it takes, which a judge's call asks for. `levels`
|
|
68
|
+
(optional) are the levels it takes besides `lowest`, least first; without
|
|
69
|
+
them it takes `low`, `medium` and `high` (plus `minimal` when `lowest` is
|
|
70
|
+
`minimal`, and none below `lowest` when that's `medium` or `high`).
|
|
71
|
+
- To make a model think less, the agent sets `thinking` in its model
|
|
72
|
+
settings (`lowest`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`).
|
|
73
|
+
For calls that ask none, set the model's `thinking.default`:
|
|
74
|
+
`"thinking": { "mode": "adaptive", "lowest": "low", "default": "low" }`.
|
|
75
|
+
A `default` the model doesn't take is refused, naming the ones it takes.
|
|
76
|
+
A model without one thinks as Google sets. It needs runtime 0.3.0 or
|
|
77
|
+
later; an older one refuses a `thinking` with `default`.
|
|
78
|
+
- `adapter_config.thinkingLevels` is no longer read. A new registration
|
|
79
|
+
with it is refused (`adapter_config.thinkingLevels isn't read here: its
|
|
80
|
+
setting is metadata.models[].thinking.default.`); a stored one builds,
|
|
81
|
+
thinking at Google's default, and `kindgi doctor` warns. Move each
|
|
82
|
+
`model=level` pair into that model's `thinking.default`, unregister the
|
|
83
|
+
provider and register it again.
|
|
84
|
+
|
|
85
|
+
**Step 3 — register and check:**
|
|
86
|
+
```sh
|
|
87
|
+
kindgi providers register --spec=@provider.json
|
|
88
|
+
kindgi providers list
|
|
89
|
+
```
|
|
90
|
+
Or skip step 2: `kindgi providers register --preset=gemini --project=<your-gcp-project-id>`
|
|
91
|
+
registers both models above.
|
|
92
|
+
Then pin it from an agent with `preferredProvider: 'gemini'` (and a model
|
|
93
|
+
with `preferredModel`; in Python, `preferred_provider="gemini"` and
|
|
94
|
+
`preferred_model=…`; in Java, `.set("preferredProvider", "gemini")`), or let
|
|
95
|
+
the router pick by capability.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# How the router picks between multiple providers + models
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- The order the router sorts (provider, model) tuples in
|
|
6
|
+
- Practical rule: preferences rank, they never exclude
|
|
7
|
+
- A/B testing a specific agent across models within one Anthropic registration
|
|
8
|
+
- A/B testing across vendors
|
|
9
|
+
|
|
10
|
+
When an agent turn fires, the router expands each registered provider
|
|
11
|
+
into one entry per model (`metadata.models[]`), filters the resulting
|
|
12
|
+
(provider, model) tuples against the agent's `capabilities.needs` (and
|
|
13
|
+
tenant policy), then sorts survivors in this order:
|
|
14
|
+
|
|
15
|
+
1. **Preferred provider / model.** Tuples matching the agent's
|
|
16
|
+
`preferredProvider` and `preferredModel` are promoted to the front.
|
|
17
|
+
- Both set → promote the exact tuple.
|
|
18
|
+
- Only `preferredModel` set → promote any provider exposing that model.
|
|
19
|
+
- Only `preferredProvider` set → promote every model of that provider.
|
|
20
|
+
`defineAgent` takes both (`preferredProvider`, `preferredModel`), and
|
|
21
|
+
so does a Python `Agent` (`preferred_provider=`, `preferred_model=`) and
|
|
22
|
+
a Java `Agent.define(…)` (`set("preferredProvider", …)`).
|
|
23
|
+
2. **`capability.prefer[]` weights.** If the agent's capability
|
|
24
|
+
declares `prefer: [{feature: 'thinking', weight: 3}, ...]`, tuples
|
|
25
|
+
with matching model features (or provider attributes) get higher
|
|
26
|
+
scores. Sorted by summed score, descending.
|
|
27
|
+
3. **Deterministic tiebreak.** When scores tie, tuples sort by provider
|
|
28
|
+
id, then the provider's `defaultModel` before its other models, then
|
|
29
|
+
model name — replay-safe and stable. A provider without a
|
|
30
|
+
`defaultModel` falls back to its first model by name.
|
|
31
|
+
|
|
32
|
+
**Practical rule:** preferences are soft — they rank, they don't
|
|
33
|
+
exclude. To guarantee which model runs, make it a hard requirement in
|
|
34
|
+
the capability: `{ models: { allow: ['claude-sonnet-5-5'] } }` (and
|
|
35
|
+
`{ providers: { allow: ['anthropic'] } }` to pin the connection). If no
|
|
36
|
+
registered tuple satisfies it, the turn fails with
|
|
37
|
+
`capability-routing-failed` instead of silently using another model.
|
|
38
|
+
|
|
39
|
+
**A/B testing a specific agent across models within one Anthropic
|
|
40
|
+
registration:**
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// agents/weather-agent-sonnet/index.ts
|
|
44
|
+
defineAgent({
|
|
45
|
+
id: 'my-pack.weather-agent-sonnet',
|
|
46
|
+
// …same name, instructions, tools, retrieval and guardrails as the opus variant
|
|
47
|
+
capabilities: [
|
|
48
|
+
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['claude-sonnet-5-5'] } }] },
|
|
49
|
+
],
|
|
50
|
+
preferredProvider: 'anthropic',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// agents/weather-agent-opus/index.ts
|
|
54
|
+
defineAgent({
|
|
55
|
+
id: 'my-pack.weather-agent-opus',
|
|
56
|
+
// …
|
|
57
|
+
capabilities: [
|
|
58
|
+
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['claude-opus-5-5'] } }] },
|
|
59
|
+
],
|
|
60
|
+
preferredProvider: 'anthropic',
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The same pair in a Python pack (`kindgi.Agent`; module-level, one file each):
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
# agents/weather_agent_sonnet.py
|
|
68
|
+
weather_agent_sonnet = Agent(
|
|
69
|
+
id="my-pack.weather-agent-sonnet",
|
|
70
|
+
# …same version, name, instructions, tools and guardrails as the opus variant
|
|
71
|
+
capabilities=[
|
|
72
|
+
{"needs": [{"feature": "tool-use"}, {"models": {"allow": ["claude-sonnet-5-5"]}}]},
|
|
73
|
+
],
|
|
74
|
+
preferred_provider="anthropic",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# agents/weather_agent_opus.py
|
|
78
|
+
weather_agent_opus = Agent(
|
|
79
|
+
id="my-pack.weather-agent-opus",
|
|
80
|
+
# …
|
|
81
|
+
capabilities=[
|
|
82
|
+
{"needs": [{"feature": "tool-use"}, {"models": {"allow": ["claude-opus-5-5"]}}]},
|
|
83
|
+
],
|
|
84
|
+
preferred_provider="anthropic",
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Both agents share the tool + instructions; only the pinned model
|
|
89
|
+
differs. One Anthropic provider registration + one API key covers
|
|
90
|
+
both. Register the provider once, then invoke each agent to compare
|
|
91
|
+
outputs on the same inputs.
|
|
92
|
+
|
|
93
|
+
**A/B testing across vendors:**
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
defineAgent({
|
|
97
|
+
id: 'my-pack.weather-agent-groq',
|
|
98
|
+
// …
|
|
99
|
+
capabilities: [
|
|
100
|
+
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['llama-3.3-70b-versatile'] } }] },
|
|
101
|
+
],
|
|
102
|
+
preferredProvider: 'groq',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
defineAgent({
|
|
106
|
+
id: 'my-pack.weather-agent-anthropic',
|
|
107
|
+
// …
|
|
108
|
+
capabilities: [
|
|
109
|
+
{ needs: [{ feature: 'tool-use' }, { models: { allow: ['claude-sonnet-5-5'] } }] },
|
|
110
|
+
],
|
|
111
|
+
preferredProvider: 'anthropic',
|
|
112
|
+
});
|
|
113
|
+
```
|