> For the complete documentation index, see [llms.txt](https://docs.talus.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.talus.network/reference/toolkit/rust.md).

# Toolkit Rust

**Audience:** Nexus toolkit integrators (Rust).

**Area:** Toolkit Rust public API.

**Generated from:** Nexus SDK toolkit public API at tag `v2.1.1` commit `08bfe76e726922ce512d623fbc1d2e1bd786bcd4` (generated inventory preserved below).

This page documents the public Rust surface that the Nexus Toolkit exports for tool authors and runtime integrators. The items are grouped by source file and listed in declaration order.

#### `toolkit-rust/src/lib.rs`

**`AnyResult`**

```rust
pub type AnyResult = anyhow::Result;
```

Convenience result alias re-exported by the toolkit crate.

**`env_logger`**

```rust
pub use env_logger;
```

Re-export of the logging initialization crate used by the toolkit runtime.

**`debug`**

```rust
pub use log::debug;
```

Logging macro re-export for toolkit and tool runtime code.

**`warp`**

```rust
pub use warp;
```

HTTP framework re-export used by the toolkit runtime and bootstrap macro.

**`StatusCode`**

```rust
pub use warp::http::StatusCode;
```

HTTP status code type used throughout the toolkit runtime and tool trait helpers.

**`toolkit-rust/src/nexus_tool.rs`**

**`AuthContext`**

```rust
pub type AuthContext = nexus_sdk::signed_http::v3::wire::AuthenticatedRequest;
```

Authenticated request context available to Tools when signed HTTP is required. It contains the Leader capability ID, Leader key ID, canonical input hash, Leader signature, and deterministic nonce after request authentication.

**`NexusTool`**

```rust
pub trait NexusTool: Send + Sync + 'static
```

Trait implemented by a Nexus tool service.

**`Input`**

```rust
type Input: JsonSchema + DeserializeOwned + Send;
```

The input payload type for the tool.

**`Output`**

```rust
type Output: JsonSchema + Serialize + Send;
```

The output payload type for the tool.

**`fqn`**

```rust
fn fqn() -> ToolFqn;
```

Returns the fully qualified tool name used by the runtime and metadata endpoint.

**`timeout`**

```rust
fn timeout() -> Duration
```

Returns the tool timeout, which defaults to 10 seconds.

**`invoke`**

```rust
fn invoke(&self, input: Self::Input) -> impl Future<Output = Self::Output> + Send;
```

Runs the tool for a single invocation request.

**`encode_output`**

```rust
fn encode_output(output: Self::Output) -> AnyResult<nexus_sdk::types::OffchainToolOutput>;
```

The default implementation retains inline JSON output encoding. Override this hook to return explicit protocol ports with `OffchainToolOutput::from_ports`; it does not upload data automatically.

**`authorize`**

```rust
fn authorize(&self, _ctx: AuthContext) -> impl Future<Output = AnyResult<()>> + Send;
```

Optional policy hook that runs after signed HTTP authentication and before invocation.

**`health`**

```rust
fn health(&self) -> impl Future<Output = AnyResult<StatusCode>> + Send;
```

Returns the health status used by `GET /health`.

**`path`**

```rust
fn path() -> &'static str;
```

Returns the relative HTTP path for the tool, defaulting to the web root.

**`description`**

```rust
fn description() -> &'static str;
```

Returns the human-readable description surfaced in metadata. Implementations must provide meaningful text: SDK registration rejects an empty or whitespace-only description.

**`new`**

```rust
fn new() -> impl Future<Output = Self> + Send;
```

Constructs a tool instance, usually so dependencies can be injected for tests.

**`meta`**

```rust
fn meta(url: Url) -> Value;
```

Builds the metadata JSON used by `GET /meta`.

**`toolkit-rust/src/config.rs`**

**`ENV_TOOLKIT_CONFIG_PATH`**

```rust
pub const ENV_TOOLKIT_CONFIG_PATH: &str = "NEXUS_TOOLKIT_CONFIG_PATH";
```

Environment variable that points the runtime at its JSON config file.

**TLS runtime selection**

When both nonempty TLS credential paths are configured, `bootstrap!` terminates TLS in the toolkit runtime. It explicitly selects the Rustls `ring` provider before building the server configuration so another provider enabled by a Tool dependency cannot make provider selection ambiguous. The runtime serves plain HTTP only when both TLS variables are absent. A missing, empty, or unmatched certificate/key path is a startup configuration error.

**`SignedHttpMode`**

```rust
pub enum SignedHttpMode {
    Disabled,
    Required,
}
```

Signed HTTP policy for the toolkit runtime.

**`Disabled`**

Do not require signature headers.

**`Required`**

Reject requests that are missing or fail signature verification.

**`ToolkitRuntimeConfig`**

```rust
pub struct ToolkitRuntimeConfig { /* private fields */ }
```

Validated runtime config for the toolkit HTTP server.

**`from_env`**

```rust
pub fn from_env() -> anyhow::Result<Self>
```

Loads config from `ENV_TOOLKIT_CONFIG_PATH` when set, otherwise uses runtime defaults.

**`from_path`**

```rust
pub fn from_path(path: impl AsRef<Path>) -> anyhow::Result<Self>
```

Parses config from a JSON file on disk.

**`from_json_bytes`**

```rust
pub fn from_json_bytes(bytes: &[u8]) -> anyhow::Result<Self>
```

Parses config from JSON bytes.

**`from_json_str`**

```rust
pub fn from_json_str(json: &str) -> anyhow::Result<Self>
```

Parses config from a JSON string.

**`invoke_max_body_bytes`**

```rust
pub fn invoke_max_body_bytes(&self) -> u64
```

Returns the maximum allowed `/invoke` request body size.

**`signed_http_is_required`**

```rust
pub fn signed_http_is_required(&self) -> bool
```

Returns whether the runtime requires signed HTTP requests.

**`has_tool`**

```rust
pub fn has_tool(&self, tool_id: &str) -> bool
```

Returns whether signed HTTP configuration contains an entry for the Tool id. The entry may omit response-signing material.

**Toolkit JSON contract**

`ToolkitRuntimeConfig` has no top-level config version and uses optional per-Tool `response_signing_key`. Keep this exact JSON shape consistent across config, tests, and verification examples.

`ToolkitRuntimeConfig` reads one strict JSON object. Unknown fields fail parsing.

```json
{
  "invoke_max_body_bytes": 12582912,
  "signed_http": {
    "mode": "required",
    "allowed_leaders_path": "<path-to-allowed-leaders.json>",
    "tools": {
      "xyz.dummy.tool@1": {
        "response_signing_key": "0000000000000000000000000000000000000000000000000000000000000000",
        "replay_cache_ttl_ms": 300000
      }
    }
  }
}
```

| Field                              | Contract                                                                                                                                                                                                                                                                                  |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invoke_max_body_bytes`            | Optional request-body limit in bytes; defaults to 12 MiB. `/invoke` requires `Content-Length` within the limit.                                                                                                                                                                           |
| `signed_http.mode`                 | `disabled` or `required`; omission inside the section defaults to `required`. Omitting the whole section disables signed HTTP.                                                                                                                                                            |
| `signed_http.allowed_leaders_path` | Path to a v3 `AllowedLeadersFileV1` JSON file. A relative path resolves from the Toolkit process working directory, not from the config file. A file-backed resolver refreshes this path during key lookup and retains the prior allowlist if a refresh fails.                            |
| `signed_http.allowed_leaders`      | Inline alternative with `{ "version": 1, "leaders": [...] }`. Use one allowlist source; when both are present, inline data is selected.                                                                                                                                                   |
| `signed_http.tools`                | Nonempty map from exact Tool FQN to its runtime signing configuration.                                                                                                                                                                                                                    |
| `response_signing_key`             | Optional 32-byte Ed25519 private key encoded as hex, base64, base64url, or Sui’s 33-byte base64 form with a leading zero flag. When present, the Toolkit signs successful canonical Tool result BCS; RegisteredKey result evidence requires it. The zero key above is test material only. |
| `replay_cache_ttl_ms`              | Optional positive completed-entry lifetime; defaults to 300,000 ms.                                                                                                                                                                                                                       |

Set the config path before `bootstrap!` starts:

```bash
export NEXUS_TOOLKIT_CONFIG_PATH="$PWD/toolkit-config.json"
cargo run
```

There is no Tool KID or external replay-store field. Tool identity selects the active on-chain Tool key. Replay state is process-local memory keyed by deterministic nonce and canonical input hash: in-flight reuse is rejected, an exact completed retry returns cached canonical bytes, and completed entries expire after the configured TTL.

In `Required`, the Toolkit verifies the Leader signature over the schema-ordered canonical input hash and reconstructs that hash from the resolved body before invocation. When `response_signing_key` is configured, it signs successful canonical result BCS; without that key, request authentication still applies but the response carries no Tool signature. A signed response can still encode a semantic Tool `err` variant; consumers must decode the canonical result and distinguish `ok` from `err`. The Tool signature binds the v3 response domain, Leader signature, deterministic nonce, and domain-separated response hash. Method/path/query/raw JSON, time-window claims, status, and other headers are not signed; authenticated HTTPS protects those fields and plaintext transport.

The v3 request headers are `X-Nexus-Sig-V`, `X-Nexus-Leader-Id`, `X-Nexus-Leader-Key-Id`, `X-Nexus-Input-Hash`, `X-Nexus-Leader-Signature`, and `X-Nexus-Nonce`. A signed canonical response carries only `X-Nexus-Sig-V` and `X-Nexus-Tool-Signature`.

Gateways must forward every listed request and response header without renaming or dropping it. Set both `NEXUS_TOOL_TLS_CERT_PATH` and `NEXUS_TOOL_TLS_KEY_PATH` for direct Toolkit TLS, or protect the gateway-to-Tool hop equivalently.

**`toolkit-rust/src/serde_tracked.rs`**

**`WithSerdeErrorPath`**

```rust
pub struct WithSerdeErrorPath<T>(pub T);
```

Transparent wrapper that preserves serde error paths while serializing and deserializing the inner value.

**`toolkit-rust/src/runtime.rs`**

**`bootstrap!`**

```rust
bootstrap!(Tool);
bootstrap!([Tool, OtherTool]);
bootstrap!(([127, 0, 0, 1], 8080), Tool);
bootstrap!(([127, 0, 0, 1], 8080), [Tool, OtherTool]);
```

Macro that loads toolkit configuration, serves `GET /health`, `GET /meta`, and `POST /invoke`, and supports `--meta` for printing tool metadata without starting the server.

### Explicit output encoding and failure boundaries

A Tool can upload a result with `nexus_walrus::WalrusStorage` and return `StoredBlob::nexus_data()` in an explicit output port. Complete the upload inside the invocation before returning; choose a timeout that covers it and persist registration/recovery state when cancellation or restart must be recoverable. The operator supplies storage payment and retention policy. The Leader downloads and validates the reference; it does not upload or own the Blob.

```rust
fn encode_output(output: Self::Output) -> AnyResult<nexus_sdk::types::OffchainToolOutput> {
    let Output::Ok { result } = output;
    nexus_sdk::types::OffchainToolOutput::from_ports(
        b"ok".to_vec(), [("result".into(), result)],
    )
}
```

Here `Output::Ok.result` is a `NexusData` produced by the upload. Annotate its schema for the decoded downstream value, such as `#[schemars(with = "String")]` for a string. The runtime validates explicit ports against metadata and signs the canonical reference. Match port order to metadata order. See [Walrus storage](/reference/sdk/walrus.md) for dependencies and durable upload phases.

Inputs and outputs each have an independent 8 MiB resolved-byte budget per invocation. Inline bytes, downloaded values, every `Many` item, and 32 bytes per object ID count toward the relevant budget. The default 12 MiB HTTP request limit accommodates base64 and metadata; explicit `invoke_max_body_bytes` settings are retained and do not raise the resolved-data budget. Published Move inline limits and signed response limits still apply, so large outputs require explicit upload.

Small canonical JSON retains the existing transport. Large or formatting-sensitive values use base64 `bytes` transport to preserve the authenticated digest; the receiving runtime verifies that commitment before JSON decoding. Upgrade receiving runtimes before sending values that require this form.

With `panic = "unwind"`, the runtime contains panics during input decoding, Tool construction, authorization, invocation, and output encoding. Internal failures return a sanitized HTTP 500 without a Tool result signature or panic payload; they are not successful protocol outputs. `panic = "abort"` still terminates the process. Exceeding `NexusTool::timeout()` returns unsigned HTTP 504; the default Tool timeout is 10 seconds. A Blob already uploaded before failure remains paid and owned; follow the [post-upload failure procedure](/reference/sdk/walrus.md#upload-succeeded-but-the-invocation-failed) before retrying or cleaning up. Validate failure behavior and the next request in local tests.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.talus.network/reference/toolkit/rust.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `build a script that syncs our docs to a CMS` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
