contracts API
SDK 0.4.0. This reference describes the supported authoring interface.
HostId
HostId = NewType('HostId', str)
TransportNodeId
TransportNodeId = NewType('TransportNodeId', str)
CapabilityNodeId
CapabilityNodeId = NewType('CapabilityNodeId', str)
BundleId
BundleId = NewType('BundleId', str)
CapabilityId
CapabilityId = NewType('CapabilityId', str)
CallId
CallId = NewType('CallId', str)
OperationId
OperationId = NewType('OperationId', str)
ProviderResourceId
ProviderResourceId = NewType('ProviderResourceId', str)
IdempotencyKey
IdempotencyKey = NewType('IdempotencyKey', str)
Identifier
Identifier = Annotated[str, Field(min_length=1, max_length=128, pattern='^[a-zA-Z0-9._:@-]+$')]
Digest
Digest = Annotated[str, Field(pattern='^[a-f0-9]{64}$')]
Revision
Revision = Annotated[str, Field(pattern='^[a-f0-9]{16}$')]
MAX_FRAME_BYTES
MAX_FRAME_BYTES = 65536
Largest single message on the local wire, in either direction.
MAX_MANIFEST_BYTES
MAX_MANIFEST_BYTES = 131072
Largest canonical manifest: the one ceiling on how much a capability declares.
A signed runtime release carries its manifest within the same bound, and the publisher refuses a larger one before anything is signed, so an author meets the limit at build time rather than as a capability that will not start.
MAX_STARTUP_BYTES
MAX_STARTUP_BYTES = MAX_MANIFEST_BYTES + MAX_FRAME_BYTES
Largest startup record: the manifest plus one frame of room for the installation's identity, its settings and its credential path.
PROTOCOL
PROTOCOL = 4
The manifest and wire protocol this SDK speaks.
Protocol 4 adds isolated, bounded duplex media channels for managed streams.
Protocol 3 adds the host's serve address to the startup record
(Startup.serve_host), and its owners carry an installation's settings
across a schema change that still accepts them. Protocol 2 bounds the child's
startup record by the manifest's own limit and answers the hello with the
manifest's digest. Protocol 1, no longer accepted, read the record with one
wire frame and echoed every descriptor in the hello.
ACCEPTED_PROTOCOLS
ACCEPTED_PROTOCOLS: tuple[int, ...] = (3, 4)
Protocols a host or owner built from this SDK accepts.
The current protocol and, once there is one, the previous: a capability built against the previous SDK keeps installing for one release cycle, and a refusal names the exact mismatch rather than failing somewhere in a range. The window never has more than two members, so both are always tested.
QUALIFIED_SKULK_VERSION
QUALIFIED_SKULK_VERSION = '2.0.0'
The Skulk™ release this SDK is qualified against, the version in
skulk-baseline.json. A manifest admits it by default, and the owner checks
legacy manifests against it because they carry no core-attested version.
accepted_protocol
Refuse a protocol outside the window, naming what this SDK accepts.
def accepted_protocol(value: int) -> int:
...
Protocol
Protocol = Annotated[int, AfterValidator(accepted_protocol), Field(json_schema_extra={'enum': list(ACCEPTED_PROTOCOLS)})]
A protocol number inside the accepted window.
Contract
Strict immutable envelope; serialize at ownership boundaries.
Descriptor
Public capability descriptor with four independently typed I/O modes.
Descriptor.chunk_schemas_match_mode
Require precisely the chunk schemas consumed by the selected I/O mode.
def chunk_schemas_match_mode(self) -> Self:
...
Descriptor.qualified_id
Return the exact public negotiation key.
def qualified_id(self) -> str:
...
Descriptor.revision
Match the pinned public canonical descriptor revision algorithm.
def revision(self) -> str:
...
Fields
id: Identifier
version: str
title: str
description: str
input_schema: dict[str, JsonValue]
output_schema: dict[str, JsonValue] | None
io_mode: Literal['unary', 'server_streaming', 'client_streaming', 'bidirectional']
input_chunk_schema: dict[str, JsonValue] | None
output_chunk_schema: dict[str, JsonValue] | None
annotations: dict[str, str] | None
| Field | Description | Declared defaults and constraints |
|---|---|---|
id | Public capability identifier. | — |
version | Semantic version. | pattern="^\d+\.\d+\.\d+$" |
title | Operator title. | min_length=1; max_length=128 |
description | Capability behavior. | min_length=1; max_length=2048 |
input_schema | Public input JSON Schema. | — |
output_schema | Public final-result JSON Schema. | default=null |
io_mode | — | default="unary" |
input_chunk_schema | — | default=null |
output_chunk_schema | — | default=null |
annotations | — | default=null |
Bounds
Hard local admission, liveness, restart and output limits.
Fields
max_children: int
concurrency: Literal[1]
startup_seconds: float
health_seconds: float
call_seconds: float
stream_seconds: float
shutdown_seconds: float
restart_budget: int
backoff_seconds: float
log_bytes: Literal[0]
| Field | Description | Declared defaults and constraints |
|---|---|---|
max_children | — | default=4; ge=1; le=16 |
concurrency | — | default=1 |
startup_seconds | — | default=5.0; gt=0; le=30 |
health_seconds | — | default=1.0; gt=0; le=10 |
call_seconds | — | default=5.0; gt=0; le=30 |
stream_seconds | Single deadline ceiling for a streaming call, including cleanup. | default=300.0; gt=0; le=300 |
shutdown_seconds | — | default=1.0; gt=0; le=5 |
restart_budget | — | default=3; ge=0; le=10 |
backoff_seconds | — | default=0.1; gt=0; le=10 |
log_bytes | No child log payload retention. | default=0 |
Surface
One declared operator-facing web surface of a capability node.
Identity, kind and permissions are immutable manifest facts; readiness and
the volatile endpoint arrive in correlated health replies. proxied
surfaces are declared so the manifest is complete, but their endpoints are
withheld from every projection until the proxy contract is qualified.
Surface.kind_specific_fields
Require proxied-only fields to stay at their defaults for links.
def kind_specific_fields(self) -> Self:
...
Fields
surface_id: SurfaceId
title: str
kind: Literal['proxied', 'link']
entry: str
websocket: bool
| Field | Description | Declared defaults and constraints |
|---|---|---|
surface_id | — | — |
title | — | min_length=1; max_length=64 |
kind | — | — |
entry | — | default="/"; max_length=256 |
websocket | — | default=false |
SurfaceReport
Volatile readiness of one declared surface, reported with health.
A complete snapshot is expected: a declared surface absent from the reply is not ready and any earlier endpoint is withdrawn.
SurfaceReport.link_urls_are_public
Validate a link endpoint as soon as it is reported.
def link_urls_are_public(self) -> Self:
...
Fields
surface_id: SurfaceId
ready: bool
port: int | None
url: str | None
| Field | Description | Declared defaults and constraints |
|---|---|---|
surface_id | — | — |
ready | — | — |
port | — | default=null; ge=1024; le=65535 |
url | — | default=null |
OperationBounds
Limits for durable operations a node runs outside the invocation slot.
Fields
max_queued: int
max_runtime_seconds: int
stale_after_seconds: int
retain: int
log_bytes: int
reservations: int
| Field | Description | Declared defaults and constraints |
|---|---|---|
max_queued | — | default=4; ge=1; le=64 |
max_runtime_seconds | — | default=3600; ge=1; le=86400 |
stale_after_seconds | — | default=30; ge=1; le=3600 |
retain | — | default=64; ge=1; le=1024 |
log_bytes | — | default=262144; ge=0 |
reservations | Replay-fence capacity. Reaching it refuses new starts rather than forgetting old ids, which would make them replayable. | default=65536; ge=64; le=1000000 |
StewardExposure
Trusted private manifest classification; never inferred from tool text.
read exposures become direct steward tools; lifecycle and
operation exposures become inert proposals that need an approval. A
declaration is not evidence of enforcement: the owner still validates the
manifest and the child still checks authority at dispatch.
Fields
qualified_id: Identifier
behavior: Literal['read', 'lifecycle', 'operation']
risk: Literal['observation', 'billable', 'effect']
provider_selection: Literal['runpod-simulator', 'runpod-witness-experimental'] | None
summary: str | None
| Field | Description | Declared defaults and constraints |
|---|---|---|
qualified_id | — | — |
behavior | — | — |
risk | — | — |
provider_selection | Governed provider for lifecycle exposures; None only for read and operation exposures that select no provider. | default="runpod-simulator" |
summary | Model-facing tool description; omitted means the descriptor's. | default=null; max_length=256 |
CredentialInput
One plugin-declared write-only credential; values are never manifest data.
Fields
credential_id: str
title: str
description: str
required: bool
| Field | Description | Declared defaults and constraints |
|---|---|---|
credential_id | Stable node-local credential reference. | pattern="^[a-z0-9][a-z0-9_-]{0,127}$" |
title | Owner-facing credential label. | min_length=1; max_length=128 |
description | What this credential authorizes and where to obtain it. | max_length=2048 |
required | Whether readiness requires a usable value. | default=true |
Manifest
Owner-installed immutable bundle contract; no secrets or PATH discovery.
Manifest.unique_contracts
Reject duplicate contracts and malformed compatibility requirements.
def unique_contracts(self) -> Self:
...
Fields
protocol: Protocol
bundle_id: Identifier
bundle_version: str
skulk_requires: str
executable: str
executable_sha256: Digest
arguments: tuple[str, ...]
descriptors: tuple[Descriptor, ...]
bounds: Bounds
effect: Literal['read', 'governed']
steward: tuple[StewardExposure, ...]
title: str | None
surfaces: tuple[Surface, ...]
operations: OperationBounds | None
configuration_schema: dict[str, JsonValue] | None
credential_inputs: tuple[CredentialInput, ...]
preflight_profile: Literal['local', 'runpod-native'] | None
| Field | Description | Declared defaults and constraints |
|---|---|---|
protocol | — | — |
bundle_id | — | — |
bundle_version | — | pattern="^\d+\.\d+\.\d+$" |
skulk_requires | — | max_length=128 |
executable | Absolute approved executable. | min_length=1; max_length=4096 |
executable_sha256 | — | — |
arguments | — | max_length=16 |
descriptors | — | min_length=1; max_length=8 |
bounds | — | — |
effect | — | default="read" |
steward | — | default=[]; max_length=8 |
title | Operator-facing bundle title; the bundle id otherwise. | default=null; min_length=1; max_length=64 |
surfaces | Declared web surfaces; readiness rides health replies. | default=[]; max_length=4 |
operations | Durable-operation limits; required by operation descriptors. | default=null |
configuration_schema | Ordinary-settings schema; configured bundles start disabled. | default=null |
credential_inputs | Write-only inputs for the provisioned node credential store. | default=[]; max_length=16 |
preflight_profile | Signed owner preflight profile enforced at enable and restart. | default=null |
Message
Every IPC message pins a protocol revision inside the accepted window.
Fields
protocol: Protocol
| Field | Description | Declared defaults and constraints |
|---|---|---|
protocol | — | — |
Hello
Authenticated startup identity and exact manifest agreement.
The child answers with the digest of the manifest it read from its startup record rather than echoing the manifest back: the check is the same, and the message stays small however much a capability declares.
Fields
kind: Literal['hello']
host_id: Identifier
transport_node_id: Identifier
capability_node_id: Identifier
bundle_id: Identifier
bundle_version: str
token: str
manifest_sha256: Digest
| Field | Description | Declared defaults and constraints |
|---|---|---|
kind | — | default="hello" |
host_id | — | — |
transport_node_id | — | — |
capability_node_id | — | — |
bundle_id | — | — |
bundle_version | — | — |
token | — | min_length=64; max_length=64 |
manifest_sha256 | SHA-256 of the canonical manifest the child read from its startup record (manifest_digest); the owner compares it with its own. | — |
Health
Correlated challenge/response; readiness is not inferred from a PID.
Health.unique_surface_reports
Refuse a reply that reports one surface twice.
def unique_surface_reports(self) -> Self:
...
Fields
kind: Literal['health']
nonce: Identifier
ready: bool
surfaces: tuple[SurfaceReport, ...]
| Field | Description | Declared defaults and constraints |
|---|---|---|
kind | — | default="health" |
nonce | — | — |
ready | — | — |
surfaces | Complete readiness snapshot of the declared surfaces. | default=[]; max_length=4 |
Invoke
One bounded unary invocation; execution time is a remaining local budget.
Fields
kind: Literal['invoke']
call_id: Identifier
capability_id: Identifier
version: str
descriptor_revision: Revision
remaining_seconds: float
payload: dict[str, JsonValue]
| Field | Description | Declared defaults and constraints |
|---|---|---|
kind | — | default="invoke" |
call_id | — | — |
capability_id | — | — |
version | — |