@kindgi/specs 0.0.0-bootstrap.0 → 0.1.1

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.
@@ -0,0 +1,277 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://kindgi.com/schemas/v1/pack-index.schema.json",
4
+ "$comment": "schema-version: 1.4.0",
5
+ "title": "Pack index",
6
+ "description": "The `index.json` a pack build emits: the pack's tools, guardrails, agents and flows as data, plus where each tool handler and guardrail check lives. A runtime registers the pack's primitives from it, and a pack service loads the modules it names and resolves every call by id. Any indexer (the TypeScript `kindgi-index`, the Python `python -m kindgi.pack index`) emits this shape. Determinism: every list is sorted by `id` (code-unit order), keys are sorted at every level, the file is UTF-8 JSON indented by two spaces with a trailing newline, and integral numbers carry no fraction, so the same source indexes to the same bytes. Consumers refuse an envelope `v` they don't recognize.",
7
+ "type": "object",
8
+ "required": [
9
+ "v",
10
+ "packId",
11
+ "packVersion",
12
+ "artifactVersion",
13
+ "publishedAt",
14
+ "tools",
15
+ "guardrails",
16
+ "agents",
17
+ "flows"
18
+ ],
19
+ "additionalProperties": false,
20
+ "properties": {
21
+ "v": {
22
+ "const": 1,
23
+ "description": "Envelope version. Additive fields on an existing entry shape don't bump it."
24
+ },
25
+ "packId": {
26
+ "type": "string",
27
+ "minLength": 1,
28
+ "description": "The pack's id (`pack.id` in the pack config)."
29
+ },
30
+ "packVersion": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "description": "The pack's version (`pack.version` in the pack config)."
34
+ },
35
+ "artifactVersion": {
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "description": "This build of the pack. A pack build pins it; a local indexer defaults to `YYYYMMDD.N` (UTC date, N counting up from the previous index of the same day)."
39
+ },
40
+ "publishedAt": {
41
+ "type": "string",
42
+ "format": "date-time",
43
+ "description": "When the index was built — ISO 8601 UTC with milliseconds (`2026-09-20T14:32:07.104Z`). A pack build pins it for reproducible output."
44
+ },
45
+ "tools": {
46
+ "type": "array",
47
+ "items": { "$ref": "#/$defs/tool" },
48
+ "description": "Tools with handler code, sorted by `id`."
49
+ },
50
+ "guardrails": {
51
+ "type": "array",
52
+ "items": { "$ref": "#/$defs/guardrail" },
53
+ "description": "Guardrails whose check is pack code, sorted by `id`."
54
+ },
55
+ "agents": {
56
+ "type": "array",
57
+ "items": { "$ref": "#/$defs/agent" },
58
+ "description": "Agents, sorted by `id`."
59
+ },
60
+ "flows": {
61
+ "type": "array",
62
+ "items": { "$ref": "#/$defs/flow" },
63
+ "description": "Flows, sorted by `id`."
64
+ },
65
+ "env": {
66
+ "type": "object",
67
+ "required": ["required", "optional"],
68
+ "additionalProperties": false,
69
+ "description": "The process environment the pack's code reads (`env` in `kindgi.config`; `[tool.kindgi.env]` in `pyproject.toml`). Absent when the pack declares none. A deployment injects exactly these names. With a `required` name unset or empty, the pack service isn't ready (unless its env check is `warn`); `/readyz` and `/v1/info` name it. Not `needsSpec.env`: that is per-call context.",
70
+ "properties": {
71
+ "required": {
72
+ "type": "array",
73
+ "items": { "$ref": "#/$defs/envName" },
74
+ "uniqueItems": true,
75
+ "description": "Names the pack service needs, set and non-empty, to be ready. Sorted."
76
+ },
77
+ "optional": {
78
+ "type": "array",
79
+ "items": { "$ref": "#/$defs/envName" },
80
+ "uniqueItems": true,
81
+ "description": "Names the pack reads when present. Sorted. Never also in `required`."
82
+ }
83
+ }
84
+ }
85
+ },
86
+ "$defs": {
87
+ "envName": {
88
+ "type": "string",
89
+ "pattern": "^(?!KINDGI_)[A-Za-z_][A-Za-z0-9_]*$",
90
+ "description": "A process environment variable name. `KINDGI_*` names configure Kindgi and are never a pack's."
91
+ },
92
+ "modulePath": {
93
+ "type": "string",
94
+ "minLength": 1,
95
+ "description": "The source file the primitive was declared in, relative to the pack root: forward slashes, no leading `./` (`tools/echo/index.ts`, `tools/ledger.py`). A pack service resolves it against its module root; a build may point it at a bundle instead. Several entries may share one module (a Python module can declare several tools)."
96
+ },
97
+ "jsonSchema": {
98
+ "type": "object",
99
+ "description": "A JSON Schema (Draft 2020-12) in wire form. Open: any JSON Schema keyword is allowed, so this node carries no `additionalProperties` restriction."
100
+ },
101
+ "openObject": {
102
+ "type": "object",
103
+ "description": "An object whose shape is defined by the primitive's own schema (`tool.schema.json`, `guardrail.schema.json`, `agent.schema.json`, `flow.schema.json`); the index carries it as declared."
104
+ },
105
+ "tool": {
106
+ "type": "object",
107
+ "required": ["id", "input", "output", "modulePath"],
108
+ "additionalProperties": false,
109
+ "properties": {
110
+ "id": {
111
+ "type": "string",
112
+ "minLength": 1,
113
+ "description": "Tool id — what a pack service resolves an `invoke` by."
114
+ },
115
+ "description": {
116
+ "type": "string",
117
+ "description": "What the tool does — the model reads it."
118
+ },
119
+ "version": {
120
+ "type": "string",
121
+ "description": "The tool's version. A caller that names a version gets `tool-version-mismatch` when it differs."
122
+ },
123
+ "input": {
124
+ "$ref": "#/$defs/jsonSchema",
125
+ "description": "JSON Schema the input must satisfy; the pack service validates before running the handler."
126
+ },
127
+ "output": {
128
+ "$ref": "#/$defs/jsonSchema",
129
+ "description": "JSON Schema the handler's return value must satisfy; the pack service validates it."
130
+ },
131
+ "effects": {
132
+ "type": "array",
133
+ "items": { "$ref": "#/$defs/openObject" },
134
+ "description": "Declared side effects (`tool.schema.json` `effects`)."
135
+ },
136
+ "needs": {
137
+ "type": "array",
138
+ "items": { "$ref": "#/$defs/openObject" },
139
+ "description": "Declared needs (`tool.schema.json` `needs`)."
140
+ },
141
+ "needsSpec": {
142
+ "$ref": "#/$defs/openObject",
143
+ "description": "Typed needs (`tool.schema.json` `needsSpec`)."
144
+ },
145
+ "sandbox": {
146
+ "type": "string",
147
+ "description": "Isolation posture (`tool.schema.json` `sandbox`)."
148
+ },
149
+ "limits": {
150
+ "$ref": "#/$defs/openObject",
151
+ "description": "Resource limits (`tool.schema.json` `limits`)."
152
+ },
153
+ "network": {
154
+ "$ref": "#/$defs/openObject",
155
+ "description": "Network policy (`tool.schema.json` `network`)."
156
+ },
157
+ "mutating": {
158
+ "type": "boolean",
159
+ "description": "Whether the tool may change something (`tool.schema.json` `mutating`). `false` makes it read-only: it runs in a dry run, and per-tool approval gates don't ask before it by default. Absent means it may."
160
+ },
161
+ "spec": {
162
+ "$ref": "#/$defs/openObject",
163
+ "description": "A declarative tool's spec (`tool.schema.json` `spec`, e.g. `kind: 'http'`). A runtime runs a tool that has one itself, resolving its `secretRef`s, rather than calling the pack service."
164
+ },
165
+ "modulePath": { "$ref": "#/$defs/modulePath" }
166
+ }
167
+ },
168
+ "guardrail": {
169
+ "type": "object",
170
+ "required": ["id", "kind", "action", "checkModulePath"],
171
+ "additionalProperties": false,
172
+ "properties": {
173
+ "id": { "type": "string", "minLength": 1, "description": "Guardrail id." },
174
+ "name": { "type": "string", "description": "Human-readable name." },
175
+ "kind": {
176
+ "type": "string",
177
+ "minLength": 1,
178
+ "description": "How the guardrail is checked (`guardrail.schema.json` `kind`)."
179
+ },
180
+ "action": {
181
+ "$ref": "#/$defs/openObject",
182
+ "description": "What a violation does (`guardrail.schema.json` `action`, with `on-violation`)."
183
+ },
184
+ "severity": {
185
+ "type": "string",
186
+ "description": "Severity (`guardrail.schema.json` `severity`)."
187
+ },
188
+ "scope": {
189
+ "$ref": "#/$defs/openObject",
190
+ "description": "When the guardrail applies (`guardrail.schema.json` `scope`)."
191
+ },
192
+ "checkModulePath": { "$ref": "#/$defs/modulePath" },
193
+ "checkId": {
194
+ "type": "string",
195
+ "minLength": 1,
196
+ "description": "The check's id — what a pack service resolves a `check-invoke` by. Absent: the guardrail's `id`."
197
+ },
198
+ "configSchema": {
199
+ "$ref": "#/$defs/jsonSchema",
200
+ "description": "JSON Schema of the check's config."
201
+ },
202
+ "config": {
203
+ "$ref": "#/$defs/openObject",
204
+ "description": "What the check is configured with (`guardrail.schema.json` `config`)."
205
+ },
206
+ "sandbox": { "type": "string", "description": "Isolation posture." },
207
+ "limits": { "$ref": "#/$defs/openObject", "description": "Resource limits." },
208
+ "network": { "$ref": "#/$defs/openObject", "description": "Network policy." }
209
+ }
210
+ },
211
+ "agent": {
212
+ "type": "object",
213
+ "required": ["id", "version", "name", "instructions", "capabilities", "tools", "modulePath"],
214
+ "additionalProperties": false,
215
+ "description": "An agent as declared (`agent.schema.json`); the runtime validates it in full when it registers the pack.",
216
+ "properties": {
217
+ "id": { "type": "string", "minLength": 1 },
218
+ "version": { "type": "string", "minLength": 1 },
219
+ "name": { "type": "string" },
220
+ "instructions": { "type": "string" },
221
+ "capabilities": { "type": "array" },
222
+ "tools": {
223
+ "type": "array",
224
+ "items": {
225
+ "type": "object",
226
+ "required": ["id", "version"],
227
+ "additionalProperties": false,
228
+ "properties": {
229
+ "id": { "type": "string", "minLength": 1 },
230
+ "version": { "type": "string", "description": "Semver range." }
231
+ }
232
+ }
233
+ },
234
+ "retrieval": { "type": "array" },
235
+ "guardrails": { "type": "array", "items": { "type": "string" } },
236
+ "budget": { "$ref": "#/$defs/openObject" },
237
+ "parameters": { "type": "array" },
238
+ "preferredProvider": { "type": "string" },
239
+ "preferredModel": { "type": "string" },
240
+ "description": { "type": "string" },
241
+ "tags": { "type": "array", "items": { "type": "string" } },
242
+ "conversationPolicy": { "$ref": "#/$defs/openObject" },
243
+ "output": {
244
+ "$ref": "#/$defs/openObject",
245
+ "description": "Typed output (`{ schema, name?, maxRepairs? }`), its schema already JSON Schema."
246
+ },
247
+ "toolErrors": {
248
+ "$ref": "#/$defs/openObject",
249
+ "description": "How the agent's turns retry failed tool calls (`{ maxRetries?, retryOn? }`, `agent.schema.json` `toolErrors`)."
250
+ },
251
+ "modulePath": { "$ref": "#/$defs/modulePath" }
252
+ }
253
+ },
254
+ "flow": {
255
+ "type": "object",
256
+ "required": ["id", "version", "nodes", "edges", "kernelPayloadVersion", "modulePath"],
257
+ "additionalProperties": false,
258
+ "description": "A flow as declared (`flow.schema.json`), plus the kernel payload version.",
259
+ "properties": {
260
+ "id": { "type": "string", "minLength": 1 },
261
+ "version": { "type": "string", "minLength": 1 },
262
+ "name": { "type": "string" },
263
+ "description": { "type": "string" },
264
+ "nodes": { "type": "array" },
265
+ "edges": { "type": "array" },
266
+ "maxParallelism": { "type": "integer", "minimum": 1 },
267
+ "metadata": { "$ref": "#/$defs/openObject" },
268
+ "output": { "$ref": "#/$defs/openObject" },
269
+ "kernelPayloadVersion": {
270
+ "const": 1,
271
+ "description": "Version of the flow payload inside the index, independent of the envelope `v`."
272
+ },
273
+ "modulePath": { "$ref": "#/$defs/modulePath" }
274
+ }
275
+ }
276
+ }
277
+ }
@@ -0,0 +1,228 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://kindgi.com/schemas/v1/pack-protocol.schema.json",
4
+ "$comment": "schema-version: 2.2.0",
5
+ "title": "Pack protocol",
6
+ "description": "Pack protocol v2 — the messages a runtime exchanges with a pack service to run pack code (tool handlers and guardrail checks). One request, one response. Transport (HTTP): `POST /v1/invoke` takes a request and answers 200 with a response; `GET /v1/info` (token) answers `info`; `GET /healthz` (no token) answers 200 while the process is up; `GET /readyz` (no token) answers 200 once every module the index names has loaded and the service isn't draining. Headers: `kindgi-pack-token` (required on `/v1/invoke` and `/v1/info`; `Authorization` is deliberately not used, since platforms like Cloud Run put their own identity token there), `kindgi-timeout-ms` (relative deadline; default 120000), `kindgi-run-id`, `kindgi-request-id`, `kindgi-protocol`; the answer to an invoke carries `kindgi-duration-ms` and `kindgi-artifact-version`. Every outcome of running pack code is a response message with status 200 — a validation failure, a throw, an unknown tool, `deadline-exceeded`, `cancelled` (the caller closed the connection). Non-2xx statuses are transport-level only: 401 (bad token), 404, 405, 413 (body over 10 MiB), 415 (not `application/json`), 503 with `Retry-After` (not ready, draining, or at the concurrency cap — the call provably did not run), 500 (the service itself failed). Process contract: a pack service reads `--index`, `--module-root` and `--host` arguments, `KINDGI_PACK_SERVICE_TOKEN`, `PORT` (`0` picks a free port) and `KINDGI_PACK_SERVICE_MAX_CONCURRENCY`; it removes `KINDGI_PACK_SERVICE_TOKEN` from its process environment before it loads pack code, which never sees it; it loads every module before listening and exits 1 with a `{\"kind\":\"boot-failed\",\"problems\":[…]}` JSON line on stderr when one fails; once listening it writes `{\"kind\":\"listening\",\"port\":N,…}` on stderr; SIGTERM drains in-flight calls (up to 8 s; `/readyz` and new invokes answer 503 meanwhile) and exits 0.",
7
+ "oneOf": [
8
+ { "$ref": "#/$defs/request" },
9
+ { "$ref": "#/$defs/response" },
10
+ { "$ref": "#/$defs/info" }
11
+ ],
12
+ "$defs": {
13
+ "version": {
14
+ "const": 2,
15
+ "description": "Protocol version of every message."
16
+ },
17
+ "request": {
18
+ "oneOf": [{ "$ref": "#/$defs/toolInvoke" }, { "$ref": "#/$defs/checkInvoke" }]
19
+ },
20
+ "response": {
21
+ "oneOf": [
22
+ { "$ref": "#/$defs/toolResult" },
23
+ { "$ref": "#/$defs/checkResult" },
24
+ { "$ref": "#/$defs/error" }
25
+ ]
26
+ },
27
+ "callContext": {
28
+ "type": "object",
29
+ "required": ["tenantId", "runId"],
30
+ "additionalProperties": false,
31
+ "description": "Per-call context a handler receives. Serializable only: a pack service adds its own cancellation (an abort signal, a cancellation token) on top.",
32
+ "properties": {
33
+ "tenantId": { "type": "string", "description": "Tenant the call runs for." },
34
+ "runId": { "type": "string", "description": "The kernel run the call belongs to." },
35
+ "requestId": {
36
+ "type": "string",
37
+ "description": "The individual call — e.g. the model's tool-call id."
38
+ },
39
+ "env": {
40
+ "type": "object",
41
+ "description": "Resolved environment values for the call (open)."
42
+ },
43
+ "secrets": { "type": "object", "description": "Resolved secrets for the call (open)." },
44
+ "config": { "type": "object", "description": "Resolved configuration for the call (open)." }
45
+ }
46
+ },
47
+ "toolInvoke": {
48
+ "type": "object",
49
+ "required": ["v", "kind", "tool", "input", "ctx"],
50
+ "additionalProperties": false,
51
+ "description": "Run a tool handler. The pack service validates `input` against the indexed input schema, runs the handler, validates its return value against the indexed output schema.",
52
+ "properties": {
53
+ "v": { "$ref": "#/$defs/version" },
54
+ "kind": { "const": "invoke" },
55
+ "tool": {
56
+ "type": "object",
57
+ "required": ["id"],
58
+ "additionalProperties": false,
59
+ "properties": {
60
+ "id": {
61
+ "type": "string",
62
+ "minLength": 1,
63
+ "description": "Tool id, resolved from the pack service's own index."
64
+ },
65
+ "version": {
66
+ "type": "string",
67
+ "description": "When set, the pack service refuses a different indexed version (`tool-version-mismatch`)."
68
+ }
69
+ }
70
+ },
71
+ "input": { "description": "The tool's input (any JSON)." },
72
+ "ctx": { "$ref": "#/$defs/callContext" }
73
+ }
74
+ },
75
+ "checkInvoke": {
76
+ "type": "object",
77
+ "required": ["v", "kind", "check", "config", "trace"],
78
+ "additionalProperties": false,
79
+ "description": "Run a guardrail check: `evaluate(config, trace)`.",
80
+ "properties": {
81
+ "v": { "$ref": "#/$defs/version" },
82
+ "kind": { "const": "check-invoke" },
83
+ "check": {
84
+ "type": "object",
85
+ "required": ["id"],
86
+ "additionalProperties": false,
87
+ "properties": {
88
+ "id": {
89
+ "type": "string",
90
+ "minLength": 1,
91
+ "description": "Check id (the indexed guardrail's `checkId`, else its `id`)."
92
+ }
93
+ }
94
+ },
95
+ "config": { "type": "object", "description": "The guardrail's config (open)." },
96
+ "trace": {
97
+ "description": "The run trace the check evaluates (`RunTrace` in `@kindgi/guardrails`)."
98
+ }
99
+ }
100
+ },
101
+ "toolResult": {
102
+ "type": "object",
103
+ "required": ["v", "kind", "output"],
104
+ "additionalProperties": false,
105
+ "properties": {
106
+ "v": { "$ref": "#/$defs/version" },
107
+ "kind": { "const": "result" },
108
+ "output": {
109
+ "description": "The handler's return value, valid against the tool's output schema."
110
+ }
111
+ }
112
+ },
113
+ "checkResult": {
114
+ "type": "object",
115
+ "required": ["v", "kind", "result"],
116
+ "additionalProperties": false,
117
+ "properties": {
118
+ "v": { "$ref": "#/$defs/version" },
119
+ "kind": { "const": "check-result" },
120
+ "result": {
121
+ "type": "object",
122
+ "required": ["passed"],
123
+ "description": "`CheckResult` — open beyond the listed fields.",
124
+ "properties": {
125
+ "passed": { "type": "boolean" },
126
+ "reason": { "type": "string" },
127
+ "judgeResponse": { "type": "string" },
128
+ "attributes": { "type": "object" }
129
+ }
130
+ }
131
+ }
132
+ },
133
+ "errorCode": {
134
+ "enum": [
135
+ "input-validation-failed",
136
+ "output-validation-failed",
137
+ "handler-import-failed",
138
+ "handler-shape-invalid",
139
+ "handler-throw",
140
+ "check-shape-invalid",
141
+ "malformed-message",
142
+ "unknown-protocol-version",
143
+ "unexpected-message-kind",
144
+ "tool-not-in-pack",
145
+ "check-not-in-pack",
146
+ "tool-version-mismatch",
147
+ "deadline-exceeded",
148
+ "cancelled"
149
+ ],
150
+ "description": "Why running pack code didn't produce a result."
151
+ },
152
+ "issue": {
153
+ "type": "object",
154
+ "required": ["instancePath", "message"],
155
+ "description": "One validation issue, Ajv-shaped. `keyword` names the failing JSON Schema keyword; it is absent when the failure came from a model's own validation (a Zod refinement, a pydantic validator) rather than a schema keyword. Open: an implementation may add fields.",
156
+ "properties": {
157
+ "instancePath": {
158
+ "type": "string",
159
+ "description": "JSON Pointer to the failing value (`\"\"` for the root, `/items/0/name`)."
160
+ },
161
+ "schemaPath": {
162
+ "type": "string",
163
+ "description": "URI fragment of the failing schema keyword (`#/properties/name/type`)."
164
+ },
165
+ "keyword": {
166
+ "type": "string",
167
+ "description": "The failing keyword (`type`, `required`, `additionalProperties`, …)."
168
+ },
169
+ "params": {
170
+ "type": "object",
171
+ "description": "Keyword parameters, as Ajv reports them: `required` → `{ missingProperty }`, `additionalProperties` → `{ additionalProperty }`, `type` → `{ type }`, `enum` → `{ allowedValues }`, limits → `{ limit }`, `pattern` → `{ pattern }`, `format` → `{ format }`."
172
+ },
173
+ "message": {
174
+ "type": "string",
175
+ "description": "Human-readable message (`must have required property 'name'`)."
176
+ }
177
+ }
178
+ },
179
+ "error": {
180
+ "type": "object",
181
+ "required": ["v", "kind", "code", "message"],
182
+ "additionalProperties": false,
183
+ "properties": {
184
+ "v": { "$ref": "#/$defs/version" },
185
+ "kind": { "const": "error" },
186
+ "code": { "$ref": "#/$defs/errorCode" },
187
+ "message": { "type": "string" },
188
+ "toolId": { "type": "string", "description": "Present when the error is about a tool." },
189
+ "checkId": { "type": "string", "description": "Present when the error is about a check." },
190
+ "cause": {
191
+ "description": "The serialized throw for `handler-throw` / `handler-import-failed` (`{ name, message, stack }` for an error object)."
192
+ },
193
+ "issues": {
194
+ "type": "array",
195
+ "items": { "$ref": "#/$defs/issue" },
196
+ "description": "Present for `input-validation-failed` / `output-validation-failed`."
197
+ }
198
+ }
199
+ },
200
+ "info": {
201
+ "type": "object",
202
+ "required": ["protocol", "packId", "packVersion", "artifactVersion", "tools", "checks"],
203
+ "additionalProperties": false,
204
+ "description": "The answer to `GET /v1/info`.",
205
+ "properties": {
206
+ "protocol": { "$ref": "#/$defs/version" },
207
+ "packId": { "type": "string" },
208
+ "packVersion": { "type": "string" },
209
+ "artifactVersion": { "type": "string" },
210
+ "tools": {
211
+ "type": "array",
212
+ "items": {
213
+ "type": "object",
214
+ "required": ["id"],
215
+ "additionalProperties": false,
216
+ "properties": { "id": { "type": "string" }, "version": { "type": "string" } }
217
+ }
218
+ },
219
+ "checks": { "type": "array", "items": { "type": "string" } },
220
+ "missingEnv": {
221
+ "type": "array",
222
+ "items": { "type": "string" },
223
+ "description": "The index's required env names this process lacks (unset or empty), sorted. Empty when none is missing. Under the `strict` env check the service isn't ready while any is listed."
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }