Pack protocol
@kindgi/specs/pack-protocol.schema.json, schema version 2.2.0.
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.
Type: request or response or info
Definitions
Section titled “Definitions”version
Section titled “version”Protocol version of every message.
Type: 2
request
Section titled “request”Type: toolInvoke or checkInvoke
response
Section titled “response”Type: toolResult or checkResult or error
callContext
Section titled “callContext”Per-call context a handler receives. Serializable only: a pack service adds its own cancellation (an abort signal, a cancellation token) on top.
tenantId(string, required): Tenant the call runs for.runId(string, required): The kernel run the call belongs to.requestId(string): The individual call — e.g. the model's tool-call id.env(object): Resolved environment values for the call (open).secrets(object): Resolved secrets for the call (open).config(object): Resolved configuration for the call (open).
toolInvoke
Section titled “toolInvoke”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.
v(version, required)kind("invoke", required)tool(object, required)id(string, required): Tool id, resolved from the pack service's own index.version(string): When set, the pack service refuses a different indexed version (tool-version-mismatch).
input(object, required): The tool's input (any JSON).ctx(callContext, required)
checkInvoke
Section titled “checkInvoke”Run a guardrail check: evaluate(config, trace).
v(version, required)kind("check-invoke", required)check(object, required)id(string, required): Check id (the indexed guardrail'scheckId, else itsid).
config(object, required): The guardrail's config (open).trace(object, required): The run trace the check evaluates (RunTracein@kindgi/guardrails).
toolResult
Section titled “toolResult”v(version, required)kind("result", required)output(object, required): The handler's return value, valid against the tool's output schema.
checkResult
Section titled “checkResult”v(version, required)kind("check-result", required)result(object, required):CheckResult— open beyond the listed fields.passed(boolean, required)reason(string)judgeResponse(string)attributes(object)
errorCode
Section titled “errorCode”Why running pack code didn't produce a result.
Type: "input-validation-failed" | "output-validation-failed" | "handler-import-failed" | "handler-shape-invalid" | "handler-throw" | "check-shape-invalid" | "malformed-message" | "unknown-protocol-version" | "unexpected-message-kind" | "tool-not-in-pack" | "check-not-in-pack" | "tool-version-mismatch" | "deadline-exceeded" | "cancelled"
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.
instancePath(string, required): JSON Pointer to the failing value (""for the root,/items/0/name).schemaPath(string): URI fragment of the failing schema keyword (#/properties/name/type).keyword(string): The failing keyword (type,required,additionalProperties, …).params(object): Keyword parameters, as Ajv reports them:required→{ missingProperty },additionalProperties→{ additionalProperty },type→{ type },enum→{ allowedValues }, limits →{ limit },pattern→{ pattern },format→{ format }.message(string, required): Human-readable message (must have required property 'name').
v(version, required)kind("error", required)code(errorCode, required)message(string, required)toolId(string): Present when the error is about a tool.checkId(string): Present when the error is about a check.cause(object): The serialized throw forhandler-throw/handler-import-failed({ name, message, stack }for an error object).issues(array of issue): Present forinput-validation-failed/output-validation-failed.
The answer to GET /v1/info.
protocol(version, required)packId(string, required)packVersion(string, required)artifactVersion(string, required)tools(array of object, required)id(string, required)version(string)
checks(array of string, required)missingEnv(array of string): The index's required env names this process lacks (unset or empty), sorted. Empty when none is missing. Under thestrictenv check the service isn't ready while any is listed.