Pre-alpha documentation
Register local Rust tools without bypassing durability.
Generate digest-pinned schemas, adapt typed Rust code, freeze an exact provider snapshot, and let the durable executor own dispatch and recovery.
Run the production registry path
The checked-in example generates and pins both Rust schemas, constructs a typed adapter, freezes the provider registry and proves that the Agent-visible descriptor resolves exactly. It performs no Tool call or external I/O.
cargo run -p stateknot-runtime --example local_tool_registration --locked let mut schemas = JsonSchemaRegistryBuilder::with_default_limits();
let input = schemas.register_rust_type::<IncidentLookup>(input_id, VERSION)?;
let output = schemas.register_rust_output_type::<IncidentSummary>(output_id, VERSION)?;
let schemas = schemas.build()?;
let adapter = ToolAdapter::new(
IncidentLookupTool { descriptor: descriptor.clone() },
schemas,
)?;
let mut providers = ToolProviderRegistryBuilder::new();
providers.register(Arc::new(adapter))?;
let providers = providers.build();
let agent_tools = AgentTools::try_new([descriptor.clone()])?;
assert_eq!(providers.resolve(&descriptor)?.descriptor(), &descriptor); Close the typed contract before admission
Implement Tool with object-root Input and bounded
Output types. Use serde(deny_unknown_fields) and accurate
effect, idempotency, cancellation, reconciliation and resource-limit declarations.
register_rust_type generates the deserialization contract for input;
register_rust_output_type generates the serialization contract
for output. Both add the canonical schema ID, compute its RFC 8785 SHA-256 digest
and install an offline validator.
ToolAdapter rejects any generated-schema drift at startup.
This output helper follows current source and is absent from the published alpha.1 package. If an old output pin differs from the actual serialization schema, introduce new schema and Tool versions. Retain the old executable for admitted work; never rewrite an immutable pin.
One call is one physical attempt. Do not hide retries or describe
an ambiguous write as unapplied. Secrets belong in the implementation's client
configuration, never descriptors, events, errors or model-visible output.
Let durable evidence own execution
DurableInvocationExecutor validates policy and budget, commits
the start, resolves the exact frozen descriptor, performs one provider call,
then fences terminal evidence. Missing revisions and byte-different descriptors
fail before I/O. Unknown effects enter reconciliation; they do not become automatic
duplicate writes.
Local ToolAdapter, McpRemoteTool,
McpSkillBoundTool and A2aRemoteAgent can coexist in
the same registry. Exact identity collisions fail startup—there is no local,
remote or discovery precedence. Keep every old executable revision until its
in-flight runs drain.
Read the complete registration and operations guide or continue to durable invocation execution.