Fetch a tool manifest (latest active version)
const url = 'https://example.com/v1/tools/example';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://example.com/v1/tools/example \ --header 'Authorization: Bearer <token>'Returns the latest active version of the tool. When all versions are unregistered (retired), the head row still exists but has no active version — the response is 410 tool-gone with the id, distinct from 404 tool-not-found (never registered). An item more than one project serves (an environment order carries it to later environments) answers its newest active version that can run in a project the caller reads, and 404 when there is none. projectId narrows that to one project. An item with one project answers its latest active version.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”ToolId — dotted namespace (acme.lookup-order).
Query Parameters
Section titled “Query Parameters”The newest active version that can run in this project, a project the caller reads; 404 when there’s none, or when the caller doesn’t read the project. An item with one project answers its latest version for its own project and 404 for any other; one that names no project (under kindgi dev, a pack’s agents, flows and tools) answers it for any. With authorization off, the caller reads every project. An older runtime ignores it and answers the latest version.
Responses
Section titled “Responses”Tool manifest.
object
ToolId — dotted namespace (e.g. acme.verify-citation).
The tool’s project: every version of a tool is in the one project. Absent when the runtime doesn’t record it: a pack kindgi dev serves from disk, or a runtime before Kindgi 0.1.6.
JSON Schema (Draft 2020-12) for the tool input.
object
JSON Schema (Draft 2020-12) for the tool output.
object
object
object
object
Semantic marker: true when this tool causes observable side effects (writes state, calls external APIs with mutations, sends messages). Read-only tools set false. Absent defaults to true. Consumed by the HITL default classifier — a read-only tool passes straight through, a mutating tool asks on first use. It also decides what runs together: calls to read-only tools that a model step asks for one after another run at the same time, up to 8 at once, unless the agent sets parallelToolCalls: false; a call to a mutating tool runs on its own, and so does a call to a read-only tool that pauses or declares connections, since it may wait.
true: in a run no person started (one whose startedBy isn’t person), every call of this tool waits for a person’s yes, whatever the agent’s approval rules say, and a flow’s tool step that calls it is refused. A webhook trigger, a schedule or a mail trigger whose toolsAllowedUnattended names the tool (a project admin’s to set) lifts that, in its own runs only. A tool that uses a person’s connection, reads included, counts as declaring it. In a run a mail started, so does a tool that isn’t mutating: false, and one that uses the run’s own mailbox. Absent means false.
true when the tool may make its run wait for another system’s answer: each call gets a wait token, hands its link to that system, and answers pause; the system’s answer, valid against output, becomes the call’s result. The run waits at most 24 days (24 hours by default) and fails the call when the time passes. Only a pack tool with a handler can pause: not one with a declarative spec, nor an MCP tool. Absent means false.
true when the tool may store files for its run, such as a mail’s attachments: each call can store up to 10, the runtime checks each one’s bytes, and the tool returns the stored files in its result’s top-level files, which an agent is shown. Only a pack tool with a handler can store files: not one with a declarative spec, nor an MCP tool. Absent means false.
true when the tool may read stored files’ bytes, such as a PDF an agent was given, to parse it: each call can read a file its run may be shown, by its file value’s artifactId, as it was stored. Only a pack tool with a handler can read files: not one with a declarative spec, nor an MCP tool. Absent means false.
true when the tool’s results are text from outside that nobody checked, such as a mail someone sent: an agent reads each result as data, not instructions, in that turn and in every later turn’s history. Absent means false.
Isolation posture the runtime enforces around the handler. Optional additive field.
Sandbox-enforced resource caps at dispatch. Optional additive field.
object
Typed discriminated needs (env / secrets / config / capabilities / bindings / connections). Optional additive field.
object
object
object
object
object
object
object
Accounts at other apps the tool acts with, by the tool’s own name for each (mail). The runtime resolves them per call into the context’s connections.
object
object
The app’s entry id: google, github.
The entry’s permission keys the call needs: gmail.send.
Whose connection: person, the run’s person (the one it acts for, who started it or owns its trigger); company, the tenant’s.
Declarative HTTP-invocation spec. Attached to ToolManifest.spec under the discriminant kind: 'http'. The runtime Tool.handler is synthesized by the ‘http’ spec synthesizer to perform URL-template substitution, secret-ref resolution via ToolContext.resolveSecret, and the outbound fetch. All fields serialize cleanly to JSON.
object
URL template with {param} placeholders substituted from the tool’s input at invoke time.
object
object
object
object
object
A connection the tool declares in needsSpec.connections, by its name there: sent as Authorization: Bearer <access token>.
object
Wall-clock timeout in ms. Default 30000.
When true (default), the response body is parsed as JSON before returning to the invoker.
object
Present only on an unregistered version: a retired tool (every version unregistered) as GET /v1/tools?includeRetired=true lists it.
Where each secret it names is read, by name: recorded by the server when it was registered, never sent by a caller. null: none usable (the registrant administers no scope the secret could be read at), until an admin records it again: a tool by publishing a new version, an MCP endpoint by unregistering it and registering it again. Absent on items registered before it was recorded, or on a runtime without a secrets store.
Example
{ "effects": [ { "kind": "reads" } ], "transport": "auto", "sandbox": "none", "network": { "kind": "none" }, "needsSpec": { "connections": { "additionalProperty": { "as": "person" } } }, "codeArtifactRef": { "kind": "oci" }, "spec": { "kind": "http", "method": "GET", "authorization": { "kind": "bearer" }, "requestBody": { "kind": "json-input" } }, "secretScopes": { "additionalProperty": { "kind": "tenant" } }}projectId is not a project id (a UUID).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}No tool with that id under this tenant.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Tool retired (all versions unregistered).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The database was too busy to answer in time (database-busy); Retry-After (whole seconds) says when to try again.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}See also
GET /v1/tools/{toolId}/versions: List all versions of a toolGET /v1/tools/{toolId}/versions/{version}: Fetch a specific tool versionPOST /v1/tools/{toolId}/versions/{version}/unregister: Unregister a specific tool versionPOST /v1/tools/{toolId}/versions/{version}/reinstate: Reinstate a specific tombstoned tool version- Error code
database-busy - Every error code