The cyrnel sdk package exports a small set of typescript types that
describe the data cyrnel exchanges between the host, adapters, and
environments. Everything else builds on these.
JSONSchema
type JSONSchema = Record<string, unknown>;
A free-form JSON document. Cyrnel internally validates payloads against the
schema, any valid JSON schema format is fair game. Adapters and environments
treat schemas as opaque.
ServiceDefinition
interface ServiceDefinition {
name: string;
description: string;
configSchema: JSONSchema;
secretsSchema: JSONSchema;
tools: ToolDefinition[];
adapterDomain: Record<string, unknown>;
}
The shape an adapter returns from generateDefinition. Cyrnel persists this
into the services table along with an id, hash, source,
adapter, and enabled flag. See Services.
configSchema describes per-service configuration (validated on PATCH).
secretsSchema describes per-service secrets (validated on PATCH).
adapterDomain is opaque to cyrnel. Adapters use it to carry
install-time information that the runtime needs at invoke time.
interface ToolDefinition {
id: string;
name: string;
description: string;
inputSchema: JSONSchema;
outputSchema: JSONSchema;
adapterDomain: Record<string, unknown>;
}
The shape of each entry in ServiceDefinition.tools. id must be a
valid TypeScript identifier; it is what process code addresses.
type ToolState = Omit<
ToolDefinition,
"id" | "name" | "description" | "inputSchema" | "outputSchema"
>;
interface ServiceState
extends Omit<
ServiceDefinition,
"name" | "description" | "configSchema" | "secretsSchema" | "tools"
> {
id: string;
tools: Record<string, ToolState>;
config: Record<string, unknown>;
secrets: Record<string, unknown>;
}
The snapshot cyrnel hands to an adapter through
AdapterModule.hydrateService. It carries everything the adapter needs to
serve invocations:
adapterDomain: The bag the adapter populated in generateDefinition.
tools: Per-tool adapterDomain keyed by tool id.
config: Validated configuration object (defaults applied).
secrets: Decrypted secrets object (defaults applied).
Adapters should treat this as the source of truth and refresh their
internal state every time hydrateService is called.
interface InvokeInput {
serviceId: string;
toolId: string;
parameters: Record<string, unknown>;
}
The payload of every tool call:
- Environment modules receive it through
EnvironmentBindings.invokeTool.
- Adapter modules receive it through
AdapterModule.invoke.
- The host validates
parameters against the tool’s inputSchema before
the adapter sees it (adapter-side validation is optional but
recommended).
interface ToolDocsInput {
serviceId: string;
toolId: string;
description: string;
inputSchema: JSONSchema;
outputSchema: JSONSchema;
}
Passed to EnvironmentModule.generateToolDocs when the API serves
GET /tools/:serviceId/:toolId/docs. The environment is expected to
return Markdown.
Execution constants
const EXECUTION_STATES = ["queued", "running"] as const;
type ExecutionState = (typeof EXECUTION_STATES)[number];
const EXECUTION_EXIT_STATES = [
"failed",
"success",
"timeout",
"canceled",
] as const;
type ExecutionExitState = (typeof EXECUTION_EXIT_STATES)[number];
The vocabulary an environment uses to report progress. ProcessService
adds idle and terminating on top, those are host-side states, not
environment-reported ones. See Execution and
Processes. Last modified on June 24, 2026