Connector author contract¶
Kata external-root connectors are executables that implement the versioned
kata.connector.v1 JSON protocol. Provider-specific credentials and APIs stay
inside the connector.
This page is the contract for connector authors: the wire protocol, the public
Go SDK, and the conformance kit. Operators configure connector instances with
[[connector]] tables in <KATA_HOME>/config.toml (see the
configuration reference) and manage bindings with the
kata connector and kata bridge commands (see the
CLI reference).
Process and framing¶
Kata starts one fresh connector process for each RPC. It writes exactly one JSON request to standard input, closes the request stream, and expects exactly one JSON response on standard output. Extra JSON, malformed responses, mismatched request IDs, an unsupported protocol version, or output beyond the bounded response limit fail the call. Diagnostic output is not part of the protocol.
Every request contains:
{
"protocol": "kata.connector.v1",
"id": "opaque-request-id",
"method": "read_root",
"instance": "notes",
"settings": {"workspace": "example-workspace"},
"params": {"root_key": "opaque-root-key"}
}
The response repeats protocol and id, then returns exactly one of result
or error:
{
"protocol": "kata.connector.v1",
"id": "opaque-request-id",
"error": {
"code": "root_unavailable",
"message": "The external root is temporarily unavailable"
}
}
Errors must be safe, bounded operator text: a lowercase structured code and a
message without credentials, absolute paths, command lines, stack traces,
standard-output/error dumps, or control characters. The process client redacts
values supplied through the instance's explicit connector.env mapping. The
connector remains responsible for returning safe errors.
Methods and capabilities¶
All handlers implement these methods:
| Method | Purpose |
|---|---|
describe |
Return stable connector/account identity, protocol, capabilities, and optional settings schema. |
resolve_root |
Turn an operator-provided locator into a canonical root. |
read_root |
Read title, body, lifecycle state, revision, timestamps, actor, and optional fields. |
list_comments |
Return the root's canonical comment observations. |
complete_root |
Complete the external root and return verified readback. |
publish_comment |
Publish one comment and return its provider identity and timestamps. |
list_fields |
Discover canonical external field descriptors. |
read_fields |
Read selected canonical field values. |
write_fields |
Write selected fields, optionally with compare-and-set preconditions, then return canonical readback. |
publish_comment is advertised with the publish_comment capability. The
field methods are advertised with fields. Compare-and-set field writes are
advertised separately with conditional_fields. Kata rejects a conditional
write when the connector does not advertise that capability; it does not retry
the write without its preconditions. A connector may return a structured
unsupported error for optional methods whose capability it does not advertise.
Root keys, account identities, connector IDs, actor IDs, comment IDs, field IDs, and schema revisions are opaque stable identities. Do not encode Kata issue UIDs, refs, project IDs, binding IDs, branches, or other Kata-owned identity inside provider metadata. Field descriptor IDs and schema revisions must already be canonical: surrounding whitespace is invalid.
Root and comment revisions are opaque change tokens. A revision advances when
the canonical root or comment changes and remains stable while that observation
is unchanged; clients compare revisions for equality rather than ordering.
Timestamps use RFC 3339.
Field values use the portable date, local_datetime, instant, and null
kinds accepted by the conformance transcripts; a descriptor lists
the exact kinds it accepts and whether it is nullable and writable.
Protocol v1 write_fields requests always contain fields. Connectors that
advertise conditional_fields may also receive expected; when present, the
two objects have identical field-ID keysets. The connector writes only when
every current value equals its canonical expected value. Otherwise it changes
nothing and returns a field_conflict error. A request without expected is
an unconditional write.
Go SDK¶
Go connectors can implement pkg/connector.Handler and serve one request with
connector.ServeOne:
func main() {
if err := connector.ServeOne(context.Background(), os.Stdin, os.Stdout, handler); err != nil {
os.Exit(1)
}
}
connector.InvocationFromContext returns the configured instance ID and a copy
of its raw settings for the current call. Treat settings as non-secret operator
configuration; read credentials from the explicitly mapped child environment.
Conformance¶
The public pkg/connector/conformance package runs the same behavior against a
disposable provider root through the connector's real protocol boundary. A
fixture implements Exchange, Invocation, RootLocator, Reset, ExternalState,
MutateComment, and InjectFault, then
calls:
Invocation returns the configured instance ID and raw JSON settings used for
every transcript request. This lets a fixture exercise settings required by its
declared configuration schema through the real protocol boundary.
The committed transcripts under
pkg/connector/conformance/testdata/protocol-v1/ are language-neutral. Other
languages should drive those JSON cases against their executable and preserve
the same identity, mutation, error-safety, ordering, replay, and readback
invariants. The publication case injects a process exit after the provider
mutation but before the response, retries the same operation_id, and requires
provider state to change only once. The required-methods case edits an existing
provider comment and requires its stable ID to keep a changed revision across
subsequent unchanged reads.
Current boundaries¶
- The external root owns title and body while a binding is active.
- Kata planning-field mappings are limited to
scheduled_onanddeadline_onin protocol v1. - Kata uses one process per RPC for isolation and bounded cleanup.
- The browser UI has no bridge indicator yet.