From 55949c300d6f360c5fdf6185cfe0a17e85cddec6 Mon Sep 17 00:00:00 2001 From: kouks <3684840+kouks@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:23:18 +0000 Subject: [PATCH 1/2] Update docs from nexus-sdk (commit: 2ad7deaf97bd5847d85388e9d59cfca5ea10914a) --- nexus-sdk/cli.md | 364 +++++++++++++++--- nexus-sdk/client.md | 17 +- nexus-sdk/guides/1-tap-development.md | 81 ++++ .../guides/2-tap-scaffold-and-package.md | 170 ++++++++ nexus-sdk/guides/3-tap-transfer-tool.md | 95 +++++ .../guides/4-tap-dag-and-skill-config.md | 94 +++++ .../guides/5-tap-publish-and-register.md | 153 ++++++++ nexus-sdk/guides/6-tap-execute-and-settle.md | 188 +++++++++ nexus-sdk/guides/dag-construction.md | 87 ++++- nexus-sdk/guides/llm-openai-chat-prep-tool.md | 1 - .../guides/math-branching-dag-builder.md | 1 - nexus-sdk/guides/math-branching-dag-entry.md | 8 +- nexus-sdk/guides/math-branching-quickstart.md | 1 - nexus-sdk/guides/math-branching-with-chat.md | 8 +- nexus-sdk/guides/onchain-tool-development.md | 32 +- nexus-sdk/guides/setup.md | 7 +- nexus-sdk/guides/tool-communication.md | 55 ++- nexus-sdk/guides/tool-firewall.md | 1 - nexus-sdk/index.md | 2 +- nexus-sdk/tool-development.md | 1 - nexus-sdk/toolkit-rust.md | 18 +- 21 files changed, 1276 insertions(+), 108 deletions(-) create mode 100644 nexus-sdk/guides/1-tap-development.md create mode 100644 nexus-sdk/guides/2-tap-scaffold-and-package.md create mode 100644 nexus-sdk/guides/3-tap-transfer-tool.md create mode 100644 nexus-sdk/guides/4-tap-dag-and-skill-config.md create mode 100644 nexus-sdk/guides/5-tap-publish-and-register.md create mode 100644 nexus-sdk/guides/6-tap-execute-and-settle.md diff --git a/nexus-sdk/cli.md b/nexus-sdk/cli.md index d8d104e..921dbe6 100644 --- a/nexus-sdk/cli.md +++ b/nexus-sdk/cli.md @@ -1,6 +1,6 @@ # Nexus CLI -> concerns [`nexus-cli` repo](https://github.com/Talus-Network/nexus-sdk/tree/main/cli) +> concerns [`nexus-cli` repo][nexus-cli-repo] The Nexus CLI is a set of tools that is used by almost all Actors in the Nexus ecosystem. @@ -26,7 +26,7 @@ Create a new Tool scaffolding in a folder called ``. Which files are gener --- -**`nexus tool validate off-chain --url `** +**`nexus tool validate offchain --url `** Validate an off-chain Nexus Tool on the provided URL. This command checks whether the URL hosts a valid Nexus Tool interface: @@ -42,41 +42,57 @@ This command should also check that the URL is accessible by Leader nodes. For l --- -**`nexus tool validate on-chain --ident `** +**`nexus tool validate onchain --ident `** -{% hint style="warning" %} -The specific design for onchain tools is still in progress and as a result the implementation is not yet present. When running the command, it will panic. -{% endhint %} +Validate an on-chain Nexus Tool identified by `` (the Move module address used by the tool). --- -**`nexus tool register offchain --url --invocation-cost [mist] --collateral-coin [object_id] [--batch] [--no-save]`** +**`nexus tool register offchain (--url | --from-meta ) [--invocation-cost ] [--collateral-coin ] [--batch] [--no-save]`** -Command that makes a request to `GET /meta` to fetch the Tool definition and then submits a TX to our Tool Registry. It also locks the collateral and sets the single invocation cost of the Tool which defaults to 0 MIST. +Registers an off-chain Nexus Tool with the Tool Registry. Either `--url` (the live HTTP endpoint) or `--from-meta` (a path to a JSON metadata file as produced by the tool binary's `--meta` flag, or `-` for stdin) is required. The live-URL path makes a request to `GET /meta` to fetch the Tool definition; the `--from-meta` path skips that HTTP fetch (useful when the tool isn't reachable from the CLI host). The command then submits a TX to the Tool Registry, locks the collateral coin, and sets the single invocation cost (defaults to `0` MIST). This returns 2 OwnerCap object IDs that can be used to manage the Tool and its Gas settlement methods. -If the `--batch` flag is passed, the command accepts a URL of a webserver hosting multiple tools and register all of them at once. `nexus-toolkit` automatically generates a `GET /tools` endpoint that returns a list of URLs of all tools registered on that server. The CLI will then iterate over the list and register each tool. +If the `--batch` flag is passed, the command accepts a URL of a webserver hosting multiple tools and registers all of them at once. `nexus-toolkit` automatically generates a `GET /tools` endpoint that returns a list of URLs of all tools registered on that server. The CLI will then iterate over the list and register each tool. `--batch` is incompatible with `--from-meta`. Upon successful registration, both OwnerCap object IDs are saved to the CLI configuration file and automatically used for subsequent commands. This happens unless the `--no-save` flag is passed, in which case the OwnerCaps are not saved. +The JSON output for each registered tool includes the transaction `digest`, `tool_fqn`, the derived `tool_id` and `tool_gas_id`, `owner_cap_over_tool_id` and `owner_cap_over_gas_id`, and the fully-decoded post-registration `Tool` record under the `tool` field — the same shape `nexus tool inspect` and `nexus tool register onchain` emit. In `--batch` mode each tool's result is one entry in the top-level JSON array. + {% hint style="info" %} This command requires that a wallet is connected to the CLI... {% endhint %} --- -**`nexus tool register on-chain --package
--module --tool-fqn --description --witness-id `** +**`nexus tool register onchain --package
--module --tool-fqn --description --tool-witness-id [--workflow-authorization-cap-first] [--collateral-coin ] [--timeout ] [--no-save]`** + +Registers an on-chain Nexus Tool that resolves to a Move package, module, and witness object on Sui. The CLI introspects the Move module's `execute` entry function to auto-generate the input schema and its `Output` enum for the output schema; both can be customized interactively when stdin is a TTY (skipped in `--json` mode). The tool's `Tool` and `ToolGas` object IDs are derived locally from the FQN and surfaced in the JSON response alongside the `OwnerCap` returned by the on-chain call. + +Registration is partially idempotent — the Move-side `register_on_chain_tool` aborts with `EFqnAlreadyExists` when the FQN is already claimed, but the CLI surfaces that abort by changing the output to notify the user about the fact that the tool is already registered. -{% hint style="warning" %} -The specific design for onchain tools is still in progress and as a result the implementation is not yet present. When running the command, it will panic. +`--workflow-authorization-cap-first` routes through `register_on_chain_tool_with_workflow_authorization_cap`, which marks the registered tool as cap-gated. Use this when the workflow executor must mint a `ProvenValue` before each call so the runtime can derive a `VertexAuthorizationCheckCap` and hand it to the tool's `execute` function — without the grant, the cap can't be minted and the vertex (i.e. the tool itself) can't run. + +The JSON output includes the transaction `digest` + `tx_checkpoint`, the locally-derived `tool_id` and `tool_gas_id`, the `owner_cap_over_tool_id` and `owner_cap_over_gas_id` returned by the on-chain call, and the fully-decoded post-registration `Tool` record under the `tool` field — the same shape `nexus tool inspect` emits, so scripts only need to learn one Tool contract. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... {% endhint %} --- -**`nexus tool unregister --tool-fqn --owner-cap [object_id]`** +**`nexus tool inspect --tool-fqn `** + +Derives the `Tool` and `ToolGas` object IDs from the configured `ToolRegistry`/`GasService` and the supplied FQN, probes both objects on-chain, and emits a stable JSON summary so callers do not need to BCS-decode the `Tool` object themselves. Works for both HTTP and Sui tools — the variant lives inside the decoded `Tool` record. + +The JSON includes `tool_id`, `tool_gas_id`, `exists` (true when both objects are present), and the fully-decoded on-chain `Tool` record under the `tool` field (or `null` when `exists` is false). When the tool is HTTP, `tool.ref` is the `Http { url }` variant; when it is on-chain Sui, `tool.ref` is the `Sui { package_address, module_name, tool_witness_id }` variant. The stored `description`, `input_schema`, `output_schema`, `workflow_authorization_cap_first`, `registered_at_ms`, and `unregistered_at_ms` all live under `tool` too. When the tool does not exist yet, the derived IDs are still returned so the caller can pre-compute them. + +--- + +**`nexus tool unregister --tool-fqn [--owner-cap ] [--yes]`** -Command that sends a TX to our Tool Registry and unregisters a Tool with the provided ``. This command requires confirmation as unregistering a Tool will render all DAGs using it unusable. +Command that sends a TX to the Tool Registry and unregisters a Tool with the provided ``. By default the command prompts for confirmation as unregistering a Tool will render all DAGs using it unusable; pass `--yes` (or `-y`) to skip the confirmation prompt, which is useful for CI pipelines. If the OwnerCap object ID is not passed, the CLI will attempt to use the one saved in the configuration file. @@ -143,19 +159,26 @@ Generates a new Ed25519 Tool message-signing keypair. --- -**`nexus tool auth register-key --tool-fqn --signing-key [--owner-cap ] [--description ] ...gas`** +**`nexus tool auth register-key --tool-fqn --signing-key [--owner-cap ] [--description ] [--skip-if-active] ...gas`** Registers (or rotates) the Tool’s message-signing key in the on-chain Network Auth registry. - Requires an `OwnerCap` (the tool ownership cap) to prove Tool identity. - Requires a proof-of-possession signature so the chain can verify the registrant controls the private key. - Returns the registered `tool_kid` (key id) which must match the Tool runtime config. +- `--skip-if-active` makes the command idempotent: if the supplied public key is already the active key for this tool, registration is skipped. Useful in CI to avoid re-registering an unchanged key. If `--owner-cap` is omitted, the CLI will try to use the OwnerCap saved in the CLI config for that Tool. --- -**`nexus tool auth export-allowed-leaders (--all | --leader
...) --out `** +**`nexus tool auth list-keys --tool-fqn `** + +Lists every message-signing key currently registered for the given tool in the on-chain Network Auth registry. Useful for confirming a `register-key` rotation landed and for auditing which keys can sign on the tool's behalf. + +--- + +**`nexus tool auth export-allowed-leaders (--all | --leader ...) --out `** Exports a local allowlist file (JSON) of permitted Leader nodes and their active signing keys. @@ -232,11 +255,11 @@ This command requires that a wallet is connected to the CLI... --- -**`nexus dag execute --dag-id --input-json --entry-group [group] --remote [field1,field2,...] [--priority-fee-per-gas-unit ] [--inspect]`** +**`nexus dag execute --dag-id --input-json [--entry-group ] [--remote vertex.port,...] [--inspect] [--priority-fee-per-gas-unit ] [--payment-coin ] [--payment-budget ]`** -Execute a DAG with the provided ``. This command also accepts an entry `` of vertices to be invoked. Find out more about entry groups in [[Package: Workflow]]. Entry `` defaults to a starndardized `_default_group` string. +Execute a DAG with the provided ``. This command also accepts an entry `` of vertices to be invoked. Find out more about entry groups in [[Package: Workflow]]. Entry group defaults to a standardized `_default_group` string. -The input `` is a JSON string with the following structure: +The input `` is a JSON string with the following structure: - The top-level object keys refer to the _entry vertex names_ - Each top-level value is an object and its keys refer to the _input port names_ of each vertex (this object can be empty if the vertex has no input ports) @@ -250,21 +273,26 @@ Supported remote storage providers are: - Walrus +Talus agent execution payment is supplied via two optional flags: + +- `--payment-coin ` — SUI coin to lock as the execution payment. When omitted, the execution is recorded with no Talus agent payment context. +- `--payment-budget ` — optional cap on the payment budget. Defaults to the full balance of `--payment-coin` when omitted. + {% hint style="info" %} This command requires that a wallet is connected to the CLI... {% endhint %} --- -**`nexus dag inspect-execution --dag-execution-id --execution-digest `** +**`nexus dag inspect-execution --dag-execution-id `** -Inspects a DAG execution process based on the provided `DAGExecution` object ID and the transaction digest from submitting the execution transaction. +Inspects a DAG execution process from its `DAGExecution` object ID. The SDK derives the starting checkpoint by chasing `Owner::Shared(initial_shared_version)` → time-pinned `previous_transaction` → that transaction's `checkpoint`, so callers no longer have to track which checkpoint the execution was committed in. The command subscribes to the on-chain event stream starting at that checkpoint and emits each walk advance, end-state, terminal `_err_eval` record, and the final execution-finished event in human-readable form or as a JSON trace when `--json` is set. --- -**`nexus dag execution-cost --dag-execution-id `** +**`nexus dag execution-cost --dag-execution-id `** -Checks the cost of a DAG execution based on the provided `DAGExecution` object ID. This cost is broken down per transaction digest and includes the execution cost and the priority fee. +Shows the Talus agent execution payment consumed by a DAG execution. Decodes `DAGExecution.standard_tap_context` to find the linked `TapExecutionPayment` object and emits its `payment_id`, `max_budget`, `locked_budget`, `consumed`, `outstanding_locks`, `accomplished`, and `refunded` fields as stable JSON. Pair with `nexus tap payments wait --payment-id ` to drive settlement to a terminal state. --- @@ -286,7 +314,7 @@ Manage scheduler tasks, occurrences, and periodic schedules. --- -**`nexus scheduler task create --dag-id [--entry-group ] [--input-json ] [--remote vertex.port,...] [--metadata key=value ...] [--execution-priority-fee-per-gas-unit ] [--schedule-start-ms | --schedule-start-offset-ms ] [--schedule-deadline-offset-ms ] [--schedule-priority-fee-per-gas-unit ] [--generator queue|periodic]`** +**`nexus scheduler task create --dag-id [--entry-group ] [--input-json ] [--remote vertex.port,...] [--metadata key=value ...] [--execution-priority-fee-per-gas-unit ] [--schedule-start-ms | --schedule-start-offset-ms ] [--schedule-deadline-offset-ms ] [--schedule-priority-fee-per-gas-unit ] [--generator queue|periodic] [--agent-id --skill-id ]`** Creates a new scheduler task tied to the specified DAG. Key options: @@ -297,6 +325,7 @@ Creates a new scheduler task tied to the specified DAG. Key options: - `--schedule-start-ms` supplies an absolute first-occurrence timestamp (milliseconds since epoch) while `--schedule-start-offset-ms` uses the current Sui clock as the base; the two switches are mutually exclusive. - `--schedule-deadline-offset-ms` sets the completion window relative to whichever start time was selected, and `--schedule-priority-fee-per-gas-unit` sets the priority fee for that initial occurrence. - `--generator` chooses the generator responsible for future occurrences (`queue` by default, `periodic` to enable recurring schedules). +- `--agent-id` and `--skill-id` (must be supplied together, or both omitted) scope the task to a registered TAP agent skill. When set, the workflow dispatches walks under the agent-bound execution policy (`AdvanceForAgentExecution`) instead of the default DAG-execution policy. Use `nexus tap schedule-task` when task creation and TAP funding should happen in one transaction. Initial schedule arguments (`--schedule-*`) are only valid for queue-based tasks. Selecting `--generator periodic` prepares the task for periodic execution, but you must configure the recurring schedule separately via `nexus scheduler periodic set`. @@ -364,31 +393,15 @@ This command requires that a wallet is connected to the CLI and holds sufficient ### `nexus gas` -Set of commands to manage Nexus gas budgets and tickets. - ---- - -**`nexus gas add-budget --coin `** - -Upload the coin object to the Nexus gas service as budget in the "invoker address" scope. That means that if a DAG execution is started from the address that the coin was uploaded from, the coin can be used to pay for the gas. +Set of commands to manage Nexus gas ticket extensions (expiry tickets and limited-invocations tickets) for off-chain tools. {% hint style="info" %} -This command requires that a wallet is connected to the CLI... +Talus agent execution payments are managed through `nexus dag execute --payment-coin`, `nexus tap execute --payment-*` flags, `nexus dag execution-cost`, and `nexus tap payments`. The commands below are for the tool-side gas ticket extensions that off-chain tool owners can enable for their tools. {% endhint %} --- -**`nexus gas balance`** - -Check the balance of the invoker's gas funds. This command reads all the funds that the invoker has uploaded as gas budget and prints them per usage scope. - -{% hint style="info" %} -This command requires that a wallet is connected to the CLI... -{% endhint %} - ---- - -**`nexus gas expiry enable --tool-fqn --owner-cap [object_id] --cost-per-minute `** +**`nexus gas expiry enable --tool-fqn --cost-per-minute [--owner-cap ]`** The tool owners can enable the expiry gas extension for their tools specified by the FQN. This allows users to buy expiry gas tickets that can be used to pay for the tool usage for a limited amount of time. @@ -468,17 +481,162 @@ This command requires that a wallet is connected to the CLI... --- -### `nexus network` +### `nexus tap` + +Commands for authoring, publishing, registering, executing, scheduling, and inspecting custom TAP packages and Talus agent skills. The TAP package surface covers the full lifecycle from scaffolding a new skill locally through publishing it on-chain, binding it to an agent, updating the current skill revision, and inspecting registry/payment/scheduled-task state. + +A typical lifecycle looks like: + +1. `tap scaffold` — generate a TAP package + DAG + skill config skeleton. +1. `tap validate-skill` / `tap dry-run` — verify the local artifacts and report the validated skill name plus interface revision. +1. `tap publish-skill` — publish the Move package, publish the DAG, derive the current skill artifact, and write a portable publish artifact. +1. `tap create-skill-artifact` — build the same portable skill artifact locally when the DAG and TAP package were published by another flow. +1. `tap create-agent` (or `tap bind` to do create+register in one PTB) — get an on-chain agent identity. +1. `tap register-skill` and `tap update-skill` — bind the skill to the agent and move future executions to a new current skill revision when the DAG or policies change. +1. `tap execute` / `tap schedule` — run the skill once or schedule recurring/queued executions. +1. `tap registry show`, `tap default-agent show`, `tap requirements`, `tap payments show`/`wait`, `tap vault balance`, and `tap payments list` — inspect on-chain state and drive settlement. + +All commands accept `--json` for stable machine-readable output. + +#### Authoring (local-only) + +--- + +**`nexus tap scaffold --name [--target ]`** + +Generates a TAP package skeleton in `//`, containing a `tap/` Move package, a `dag.json` DAG, and a `skill.tap.json` skill config that points at both. The package name is snake-cased from the supplied ``, and the module name matches the package name. The JSON output contains the resolved path to the generated directory. `--target` defaults to the current directory. + +--- + +**`nexus tap validate-skill --config `** + +Statically validates a TAP skill config JSON and the local TAP package it references — package manifest, named-address aliases, module declarations, and the bundled DAG JSON. The TAP package is resolved from the config's `tap_package_path` (interpreted relative to the config file's directory). No network is required. + +--- + +**`nexus tap dry-run --config `** + +Runs `validate-skill` and checks the local TAP package, DAG, and simplified skill requirements before any chain write. The JSON output reports `valid`, the skill name, and the requested interface revision. + +#### Publishing (on-chain authoring) + +--- + +**`nexus tap publish-skill --config [--out ]`** + +Publishes the TAP Move package, publishes the DAG, and constructs a `TapPublishArtifact` carrying the `dag_id`, requested `interface_revision`, and simplified requirements needed to bind or update a skill. The JSON output includes the TAP `package_id`, the `dag_id`, the per-step transaction digests and checkpoints, and the full `artifact`. When `--out` is supplied, the artifact is also written to disk as JSON for `register-skill`, `bind`, or `update-skill`. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +**`nexus tap create-skill-artifact --skill-name --dag-id --interface-revision --payment-mode [--agent-funded-max-budget ] [--recurrence-kind ] [--min-interval-ms ] [--max-occurrences ] [--allow-recursive] [--fixed-tool ] --out `** + +Creates a skill `TapPublishArtifact` file from explicit skill inputs and a read-only fetch of the published DAG. Use it when a script has already published or otherwise knows the DAG id, but still wants the canonical skill artifact consumed by `tap register-skill`, `tap bind`, and `tap update-skill`. The command derives `requirements.input_schema_commitment` from the fetched DAG input-port data and aborts without writing if the DAG cannot be fetched or decoded. The artifact file and `--json` output contain only the active TAP artifact fields: `skill_name`, `dag_id`, `interface_revision`, and `requirements`. + +`--payment-mode agent-funded` requires a positive `--agent-funded-max-budget`; `--payment-mode user-funded` rejects that budget flag. `--fixed-tool` is repeatable and maps directly to `requirements.fixed_tools[]` as `=`. + +#### Agent setup + +--- + +**`nexus tap create-agent`** + +Creates a Talus agent through the configured Agent Registry and shares the agent object. Mutable custody of the `Agent` object is the lifecycle authorization handle. JSON output includes the new `agent_id` and the transaction digest/checkpoint. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +**`nexus tap bind --artifact `** + +Composes `tap::create_agent` and `tap::register_skill` into a single PTB, returning the new agent and skill bound together in one transaction. Use this when an agent has not been created yet and the operator wants the "create + register first skill" flow in one round-trip. + +The artifact JSON is the one produced by `nexus tap publish-skill` — it carries DAG id, TAP package id, interface revision, and simplified requirements. + +The JSON output exposes the transaction digest and checkpoint, the new `agent_id` and `skill_id`, the agent object ref, and structured skill evidence for external bookkeeping. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +**`nexus tap agent save --name --agent-id `** + +Saves a Talus agent object ID under a local alias in the CLI configuration. Commands that accept `--alias` (e.g. `tap vault balance`, `tap payments list`) use this mapping to resolve agent ids without re-typing them. + +--- + +**`nexus tap agent list`** + +Lists locally saved Talus agent aliases. + +--- + +**`nexus tap agent remove --name `** + +Removes a locally saved Talus agent alias. + +#### Skill Registration and Current Revisions + +--- + +**`nexus tap register-skill --artifact --agent-id `** + +Registers a TAP skill against an existing agent using the publish artifact. The artifact supplies the DAG id, TAP package id, interface revision, and simplified requirements. JSON output includes the new `skill_id`, the `agent_id`, the DAG and TAP package ids, and the transaction digest/checkpoint. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +**`nexus tap update-skill --artifact --agent-id --skill-id `** + +Updates an existing skill from a publish artifact. The current CLI path refreshes the skill DAG/policy contract and reports the resulting `current_interface_revision`; there is no endpoint-revision table or separate announce step in the active TAP model. JSON output includes the `agent_id`, `skill_id`, artifact evidence, `current_interface_revision`, and transaction digest/checkpoint. -Set of commands for managing Nexus networks. +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +#### Registry and default-agent inspection + +--- + +**`nexus tap registry show`** + +Reads the configured Agent Registry and prints its full contents as JSON: a `standard_tap` flag, the registry `id`, the configured `default_executor`, all agent records, and each skill's active flag, DAG binding, current interface revision, requirements, and scheduled-task count. This replaces ad-hoc `sui client object --json` walks of the registry's dynamic fields. + +--- + +**`nexus tap default-agent show`** + +Resolves the configured default agent through the registry and prints a flat JSON containing a `standard_tap` flag, the default `agent_id` and `skill_id`, the DAG binding, active interface revision, and published skill requirements. Useful for scripts that want to drive the network's default agent without hard-coding ids. --- -**`nexus network create --addresses [addresses] --count-leader-caps [count-leader-caps]`** +**`nexus tap requirements --agent-id --skill-id `** -Create a new Nexus network and assign `count-leader-caps` (default: 5) leader caps to the TX sender and the addresses listed in `addresses` (default: []). +Fetches the live skill requirements from the TAP registry for a given agent/skill pair: the active skill revision key `(agent_id, skill_id, current_interface_revision)` plus the registered requirements (`input_schema_commitment`, payment policy, schedule policy, and fixed tools). Use this before `tap execute` or `tap schedule` to confirm the active revision and verify the runtime inputs match the on-chain commitments. + +#### Vaults and payments + +--- -The network object ID is returned. +**`nexus tap vault balance [--alias | --agent-id ]`** + +Reads the Talus agent payment vault (a dynamic-object child of the agent object) and reports its current SUI balance. The agent can be supplied either as a saved alias or as an explicit object id; the two flags are mutually exclusive. + +--- + +**`nexus tap vault deposit --amount [--alias | --agent-id ]`** + +Deposits MIST into a Talus agent payment vault by splitting `--amount` MIST from the signer's gas coin and submitting `tap::deposit_agent_payment_vault`. The agent can be supplied either as a saved alias or as an explicit object id; the two flags are mutually exclusive. JSON output includes the agent id, deposited amount, transaction digest, and tx checkpoint. {% hint style="info" %} This command requires that a wallet is connected to the CLI... @@ -486,7 +644,115 @@ This command requires that a wallet is connected to the CLI... --- +**`nexus tap payments show --payment-id `** + +Reads a `TapExecutionPayment` object and emits a flat JSON of its fields: payment/execution/agent/skill ids, interface revision, payer, mode/source kind/source identity, locked budget, consumed amount, `accomplished`/`refunded` booleans, raw `final_state`, computed `terminal` flag, and the list of currently-locked vertices. Replaces shell-side BCS decoding of payment object internals. + +--- + +**`nexus tap payments wait --payment-id [--timeout-secs ] [--poll-secs ]`** + +Polls the same `TapExecutionPayment` object on a fixed interval until `accomplished`, `refunded`, or any non-`Pending` `final_state` is observed, or until the timeout elapses. Emits the same JSON shape as `payments show` plus `elapsed_ms` and `timed_out` fields. Defaults to a 120-second total timeout and a 2-second poll interval; both are configurable. + +Use this in CI pipelines or demos to drive payment settlement instead of hand-rolled retry loops over raw Sui object reads. + +--- + +**`nexus tap payments list [--alias | --agent-id ] [--completed | --pending | --all]`** + +Lists wallet-owned `ExecutionPaymentReceipt` objects and, when an agent is supplied (by alias or id), the agent-vault payment-receipt history. Filter to completed-only, pending-only, or both. JSON output includes the owner, optional agent id, wallet receipts, vault receipts, and the unresolved/resolved execution-id lists. + +--- + +**`nexus tap payments resolve --execution-id [--alias | --agent-id ]`** + +Settles the Talus agent payment linked to a shared `DAGExecution` so it moves to its `Accomplished` final state. Useful when the off-chain leader has not (yet) submitted the settlement transaction itself but the execution has reached a state that the on-chain assertions accept (`assert_execution_can_accomplish_tap_payment` + `assert_matches_tap_payment`). + +Two on-chain entrypoints are wrapped depending on the funding source: + +- Without `--alias`/`--agent-id`, the SDK builds a one-call PTB targeting `nexus_workflow::execution::accomplish_tap_execution_payment` — the invoker-funded path that settles out of the `TapExecutionPayment` object. +- With `--alias` (resolved against the local agent alias map) or `--agent-id`, the SDK additionally fetches the agent's shared object and routes through `nexus_workflow::execution::accomplish_tap_execution_payment_from_agent_vault` so the payment settles out of the agent's payment vault. + +JSON output includes a `function` marker (`accomplish_tap_execution_payment` or `accomplish_tap_execution_payment_from_agent_vault`), the resolved `execution_id`, the resolved `agent_id` (or `null` on the invoker-funded path), and the transaction `digest`/`tx_checkpoint`. Pair with `nexus tap payments show` or `nexus tap payments wait` to confirm the linked `TapExecutionPayment` flipped to `accomplished: true`. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +#### Execution and scheduling + +--- + +**`nexus tap execute --agent-id --skill-id --input-json [--entry-group ] [--remote vertex.port,...] [--priority-fee-per-gas-unit ] [--payment-source-hex ] [--payment-max-budget ] [--authorization-plan-hash-hex ]`** + +Executes a Talus agent skill through its current registry skill revision and DAG binding. Input JSON follows the same `{vertex: {port: data}}` shape as `nexus dag execute`. `--remote` forces named ports to be uploaded to the configured remote storage instead of being inlined on-chain. Payment options select the payment source for the Talus agent execution payment: + +- `--payment-source-hex` provides typed payment-source bytes (invoker-funded vs agent-vault-funded). Empty defaults to the invoker. +- `--payment-max-budget` caps the Talus agent execution payment. +- `--authorization-plan-hash-hex` optionally supplies an authorization-plan commitment for cap-gated tools. + +JSON output includes the new `DAGExecution` object id, the agent and skill ids, the active skill revision key, the submitted authorization plan, and the transaction digest/checkpoint. Pair with `nexus dag inspect-execution`, `nexus tap payments wait`, and (where relevant) `nexus dag execution-cost`. + +Cap-gated skills (tools registered with `--workflow-authorization-cap-first`) need a `ProvenValue` minted and recorded in the tap package's shared state before the leader dispatches the walk. The CLI does **not** drive that wiring — its shape is skill-specific. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +**`nexus tap schedule --agent-id --skill-id --long-term-gas-coin-id [--refill-policy-hex ] [--schedule-entries-commitment-hex ] [--recurrence-kind ] [--min-interval-ms ] [--max-occurrences ] [--allow-recursive] [--first-after-ms ]`** + +Schedules a Talus agent skill execution by attaching a durable, long-term gas coin to the configured Agent Registry scheduler. The `--recurrence-kind` (default `once`), `--min-interval-ms`, `--max-occurrences` (default `1`), and `--first-after-ms` parameters define the schedule shape; `--refill-policy-hex` and `--schedule-entries-commitment-hex` supply the on-chain policy commitments. JSON output includes the `scheduled_task_id`, agent and skill ids, and the transaction digest/checkpoint. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +**`nexus tap schedule-task --agent-id --skill-id --payment-source --prepay-amount --occurrence-budget [--input-json ] [--entry-group ] [--remote ] [--metadata ] [--refund-recipient
] [--schedule-start-ms |--schedule-start-offset-ms ] [--schedule-deadline-offset-ms ] [--schedule-priority-fee-per-gas-unit ] [--generator ]`** + +Creates a scheduler task for a registered TAP agent skill and attaches TAP payment components in the same transaction. Use `--payment-source address-funded` to split `--prepay-amount` from the signer gas coin, or `--payment-source agent-vault` after funding the agent vault. JSON output includes one `task_id` plus a `tap_payment` block with agent id, skill id, prepay amount, and occurrence budget. + +{% hint style="info" %} +This command requires that a wallet is connected to the CLI... +{% endhint %} + +--- + +### `nexus conf` + +Manage the Nexus CLI configuration stored at `~/.nexus/conf.toml`. The CLI reads the configured Sui RPC URL, the Sui private key, the Nexus deployment objects (package IDs and shared registry/service/gas-service/leader-registry refs), and optional data-storage settings from this file. + +--- + +**`nexus conf get`** + +Print the current Nexus CLI configuration. JSON mode emits the full configuration as a JSON document; otherwise a human-readable summary is printed. + +--- + +**`nexus conf set [--sui.pk ] [--sui.rpc-url ] [--nexus.objects ] [--data-storage.walrus-aggregator-url ] [--data-storage.walrus-publisher-url ] [--data-storage.walrus-save-for-epochs ] [--data-storage.preferred-remote-storage ] [--data-storage.testnet]`** + +Update the Nexus CLI configuration. Each flag updates the corresponding setting in `~/.nexus/conf.toml`; only the flags supplied are modified. + +- `--sui.pk` sets the Sui private key as base64-encoded bytes (matches the `base64WithFlag` format from `sui keytool convert`). +- `--sui.rpc-url` sets the Sui node RPC URL the CLI talks to. +- `--nexus.objects ` loads the Nexus package ids and shared object refs from a TOML file (as produced by `publish.sh`). This replaces the `[nexus.*]` sections wholesale. +- `--data-storage.walrus-aggregator-url` / `--data-storage.walrus-publisher-url` configure the Walrus endpoints used for remote DAG input storage. +- `--data-storage.walrus-save-for-epochs` sets how many epochs uploaded data is preserved for. +- `--data-storage.preferred-remote-storage` chooses the default remote storage backend (currently `walrus`). +- `--data-storage.testnet` is a preset that fills in the data-storage block for Sui testnet defaults and overrides any conflicting flags. + +--- + ### `nexus completion` -Provides completion for some well-known shells. +**`nexus completion `** + +Prints shell completion scripts to stdout. Supported shells: `bash`, `elvish`, `fish`, `powershell`, `zsh`. Source the output into your shell's completion directory or `eval` it directly. + + +[nexus-cli-repo]: https://github.com/Talus-Network/nexus-sdk/tree/main/cli diff --git a/nexus-sdk/client.md b/nexus-sdk/client.md index 689dca5..c6b9396 100644 --- a/nexus-sdk/client.md +++ b/nexus-sdk/client.md @@ -77,6 +77,8 @@ The `Signer` struct accepts a [`sui::crypto::Ed25519PrivateKey`] and is responsi Nexus gas budget is managed through the [`GasActions`] struct. +Talus agent-funded execution uses agent payment vaults in the `nexus_interface::tap` Move interface. Every Talus agent has a vault object, and SDK callers can fetch that object, deposit or withdraw funds through agent payment builders, and create typed `AgentVault` payment sources for skill execution. Agent-scoped workflow gas budget helpers are also available when execution settlement should resolve `Execution -> Agent -> Invoker`. + ### Add Budget ```rust @@ -97,6 +99,8 @@ println!("Gas budget added in tx: {:?}", result.tx_digest); **Returns:** +[`AddBudgetResult`]: includes the transaction digest. + --- ## ⚡ Workflow Actions @@ -122,6 +126,9 @@ println!("Published DAG ID: {:?}", publish_result.dag_object_id); **Returns:** +[`PublishResult`]: includes the transaction digest and DAG object ID. + +--- ### 2. Execute a Workflow @@ -157,8 +164,10 @@ println!("Execution object ID: {:?}", execute_result.execution_object_id); **Returns:** +[`ExecuteResult`]: includes the transaction digest and execution object ID. --- + ### 3. Inspect Workflow Execution ```rust @@ -168,7 +177,6 @@ let inspect = nexus_client .workflow() .inspect_execution( execute_result.execution_object_id, - execute_result.tx_digest, Some(Duration::from_secs(180)), // timeout ) .await?; @@ -193,9 +201,12 @@ println!("✅ Execution finished successfully!"); **Returns:** +[`InspectExecutionResult`]: includes an event stream and a poller handle. --- +## ⏱️ Scheduler Actions + The [`SchedulerActions`] API allows you to create and manage **on-chain scheduler tasks**. A scheduler task is split into: @@ -362,12 +373,10 @@ nexus_client ## 🧭 Error Handling -All methods return a `Result`. -The `NexusError` enum categorizes issues from configuration errors to RPC and transaction issues. +All methods return a `Result`. The `NexusError` enum categorizes issues from configuration errors to RPC and transaction issues. --- ## 🪶 Summary The [`NexusClient`] aims to make building, publishing, and executing Nexus workflows _simple, safe, and async-ready_. It abstracts away Sui transaction signing and gas management while providing a clean modular interface. - diff --git a/nexus-sdk/guides/1-tap-development.md b/nexus-sdk/guides/1-tap-development.md new file mode 100644 index 0000000..d6d64e7 --- /dev/null +++ b/nexus-sdk/guides/1-tap-development.md @@ -0,0 +1,81 @@ +# Custom TAP Package Development + +This series teaches how to build, register, and operate a **custom TAP package skill** end-to-end. Each page is short and self-contained; together they take you from an empty directory to a working agent that calls an on-chain Move tool which transfers SUI to a recipient address. + +> **Prereqs.** You should already be comfortable with the [Setup guide](setup.md) (CLI install, Sui wallet, `nexus conf set`) and have read the [Onchain Tool Development guide](onchain-tool-development.md) for Move tool fundamentals (witness types, `TaggedOutput`, registration mechanics). + +## What a TAP package skill is + +A custom TAP package skill combines up to three things behind one registry identity: + +1. A **TAP Move package** — your custom Move code: shared state objects, the witness type that ties a vertex tool to your package, and any business-logic helpers the tool needs (e.g. coin custody). At the protocol level this is optional: `register_skill` itself doesn't take a package id, so a skill whose DAG uses only off-chain HTTP tools and no on-chain state doesn't need one. This tutorial's skill uses an on-chain transfer tool, so the package contents below are required. +1. A **DAG** — the workflow definition the leader executes when the skill runs. For this tutorial the DAG has a single vertex that calls one on-chain Move tool. +1. A **skill config** (`skill.tap.json`) — declares the DAG, the TAP package path, and the skill's input, payment, schedule, and fixed-tool requirements. + +A skill lives under an **agent** (also on-chain). Mutable custody of the `Agent` object is the lifecycle authorization handle, and the registry stores the agent's active flag plus skill records. Each skill record carries the DAG binding, simplified requirements, and a `current_interface_revision` that fresh executions and scheduled-task creation use. `nexus tap bind` / `nexus tap register-skill` create revision `1` with the skill record, and `nexus tap update-skill` moves the current skill contract to a new revision for future starts. + +The current skill contract has these important parts: + +- **DAG binding** points to the published DAG that workflow execution should run. The concrete shared objects a skill needs, such as this tutorial's `TutorialState`, are supplied as execution inputs rather than stored in a separate endpoint-revision table. +- **`requirements.input_schema_commitment`** is an opaque byte vector that identifies the expected input shape for tooling and dry-run checks. +- **`requirements.payment_policy`** is either `UserFunded` or `AgentFunded { max_budget }`; user-funded execution supplies the payment coin at call time, while agent-funded execution draws from the agent's payment vault. +- **`requirements.schedule_policy`** declares whether scheduled execution is one-shot or recursive, including `allow_recursive` and recurrence bounds. +- **`requirements.fixed_tools`** is the canonical set of registry-verified tools that must remain present in the bound DAG. It is a preservation requirement, not the old authorized-tool or vertex-authorization schema. + +## What we'll build + +The tutorial's skill exposes a single vertex tool that does one job: **drain a SUI treasury sitting in the TAP package's shared state into a recipient address** passed as a workflow input. The state is funded out-of-band (we'll add a `fund_treasury` helper), and each skill execution moves the treasury balance to the recipient. The workflow dispatches the walk, the leader runs the Move tool, the recipient receives SUI. + +{% hint style="warning" %} +**This tutorial is intentionally minimal.** The on-chain transfer tool is registered through the plain `register_on_chain_tool` entry point and the skill config carries an empty `fixed_tools` list, so any workflow execution against this skill can drain the treasury — there is no per-call authorization check. The end of the last page covers what that means in practice and points at the follow-up guide for cap-gated authorization (`VertexAuthorizationCheckCap`, `WorkflowVertexAuthorizationGrant`, and `fixed_tools`), which is the production-ready way to wrap the same transfer logic. +{% endhint %} + +## End-to-end flow + +```text +nexus tap scaffold → empty TAP package skeleton + skill.tap.json + │ + ▼ +edit Move source → add state object + on-chain transfer tool + │ + ▼ +nexus tap validate-skill → local-only checks (no chain) + │ + ▼ +nexus tap publish-skill → publishes Move package + DAG, writes artifact.json + │ + ▼ +nexus tool register → registers the on-chain transfer tool in ToolRegistry + onchain + │ + ▼ +nexus tap bind → creates an agent + registers the skill atomically + │ + ▼ +fund the treasury → one-shot Move call that deposits SUI into state + │ + ▼ +nexus tap execute → submits the agent skill execution (payment, DAG inputs) + │ + ▼ +verify recipient balance → the treasury arrived in the destination wallet +``` + +Each arrow is one `nexus` command and one short stop on the way. The next five pages walk through them. + +## Pages + +1. [Scaffold the TAP package](2-tap-scaffold-and-package.md) — `nexus tap scaffold`, plus the Move state module the scaffold doesn't write for you. +1. [Write the on-chain transfer tool](3-tap-transfer-tool.md) — the `transfer_vertex` Move module that the workflow invokes. +1. [DAG and skill config](4-tap-dag-and-skill-config.md) — wire the on-chain tool's FQN into `dag.json` and adjust `skill.tap.json`. +1. [Publish, register, bind](5-tap-publish-and-register.md) — `tap publish-skill`, `tool register onchain`, `tap bind`, and the on-chain confirmations. +1. [Execute and verify the transfer](6-tap-execute-and-settle.md) — fund the treasury, run `tap execute`, watch the recipient balance go up. + +## What this guide does **not** cover + +The TAP package CLI surface is broader than what one tutorial can show. After you finish the series, the [CLI reference](../cli.md) covers: + +- Vault funding and vault-funded scheduling (`nexus tap vault deposit`, `nexus tap schedule-task --payment-source agent-vault`). +- Address-funded scheduling (`nexus tap schedule-task --payment-source address-funded`). +- Current skill updates for already-bound skills (`nexus tap update-skill`). +- Inspecting payment receipts and execution costs (`nexus tap payments list`, `nexus dag execution-cost`). diff --git a/nexus-sdk/guides/2-tap-scaffold-and-package.md b/nexus-sdk/guides/2-tap-scaffold-and-package.md new file mode 100644 index 0000000..f0e50f4 --- /dev/null +++ b/nexus-sdk/guides/2-tap-scaffold-and-package.md @@ -0,0 +1,170 @@ +# Scaffold the TAP package + +This page generates the on-disk shape of a TAP skill and replaces the scaffolded Move stub with a real state module that holds a SUI treasury and the per-vertex witness object the on-chain tool will be registered against. + +## 1. Generate the scaffold + +Pick a working directory and run: + +```bash +nexus tap scaffold --name "tutorial transfer" --target . +cd tutorial-transfer +``` + +The scaffold writes four files under `tutorial-transfer/`: + +```text +tutorial-transfer/ +├── dag.json # workflow definition (we'll edit later) +├── skill.tap.json # skill config (we'll edit later) +└── tap/ + ├── Move.toml # the TAP package manifest + └── sources/ + └── tutorial_transfer.move +``` + +Each generated file is a stub. The scaffolded `tutorial_transfer.move` is a single drop witness with an `init_for_test` helper — enough to compile, but nothing the workflow can actually call. + +## 2. Trim the scaffolded `tap/Move.toml` and stage `nexus_primitives` + +The scaffold ships with four `[dependencies]` entries (`nexus_primitives`, `nexus_interface`, `nexus_registry`, `nexus_workflow`) so authors who reach for the full standard-TAP surface don't have to add deps mid-build. The minimal vertex tool we're about to write only touches `nexus_primitives` — `data`, `proof_of_uid`, and `tagged_output`. Drop the other three entries so the build resolves the smallest possible dep tree: + +```toml +[dependencies] +nexus_primitives = { local = "deps/primitives" } +``` + +Then stage the `nexus_primitives` package under `tap/deps/primitives/`. It lives in `nexus-next/sui/primitives/`; either copy the directory in or point the `local` path at wherever your installation keeps it. The staged dependency needs its own `Move.toml` with an `[environments]` table and a `Published.toml` carrying the deployed package address. + +The scaffold writes an `[environments]` table pre-filled with the public-testnet chain id, which is what this guide targets: + +```toml +[environments] +testnet = "4c78adac" +``` + +Leave that as-is unless you're publishing to a different network. If you are, replace the row with ` = ""` for your target network (the alias must match a name in `sui client envs`, and the chain id is what `sui client chain-identifier` prints while that env is active). + +The end result looks like: + +```toml +[package] +name = "tutorial_transfer" +version = "1.0.0" +edition = "2024" + +[dependencies] +nexus_primitives = { local = "deps/primitives" } + +[environments] +testnet = "4c78adac" +``` + +{% hint style="info" %} +`nexus tap validate-skill` enforces the new-style 2024 layout: the manifest must have `[package].version`, `edition = "2024"` (no `.beta`), an `[environments]` table, and **no** `[addresses]` section. Old-style packages can't resolve their dependency graph against the new-style published Nexus packages, so the validator rejects them up front with a pointer at the field that needs fixing. +{% endhint %} + +## 3. Replace the scaffold's Move source + +The interesting work is in `tap/sources/tutorial_transfer.move`. Replace its contents with the module below. The state object holds a SUI treasury that the vertex tool will drain on each execution, plus the per-vertex witness whose UID feeds `nexus tool register onchain --tool-witness-id` and the worksheet stamp at runtime. + +```move +module tutorial_transfer::tutorial_transfer; + +use std::ascii::String as AsciiString; +use sui::coin::{Self, Coin}; +use sui::sui::SUI; +use sui::transfer::public_share_object; + +/// One-time witness — guarantees `init` runs exactly once at publish. +public struct TUTORIAL_TRANSFER has drop {} + +/// Per-vertex witness. Its UID becomes the on-chain tool's `tool_witness_id` +/// (passed to `nexus tool register onchain`) and the seed the vertex stamps +/// onto the workflow worksheet at runtime. +public struct TransferVertexWitness has key, store { + id: UID, +} + +/// Shared state for the tutorial skill. Holds the SUI treasury that the +/// transfer vertex drains on each execution plus the per-vertex witness +/// the on-chain tool registers against. +public struct TutorialState has key, store { + id: UID, + transfer_vertex_witness: TransferVertexWitness, + treasury: option::Option>, +} + +fun init(_otw: TUTORIAL_TRANSFER, ctx: &mut TxContext) { + public_share_object(TutorialState { + id: object::new(ctx), + transfer_vertex_witness: TransferVertexWitness { id: object::new(ctx) }, + treasury: option::none(), + }); +} + +/// Canonical FQN for the on-chain transfer vertex tool. The DAG references +/// this FQN, the tool registration uses this FQN, and the vertex module +/// returns this FQN from its own `fqn()` helper. +public fun transfer_vertex_fqn(): AsciiString { + b"tutorial.local.transfer_vertex@1".to_ascii_string() +} + +/// The id passed to `nexus tool register onchain --tool-witness-id`. +public fun transfer_vertex_tool_witness_id(state: &TutorialState): ID { + object::uid_to_inner(&state.transfer_vertex_witness.id) +} + +/// The witness UID the vertex stamps onto its worksheet at runtime. +public(package) fun transfer_vertex_witness_uid(state: &TutorialState): &UID { + &state.transfer_vertex_witness.id +} + +/// Top up the treasury that future skill executions will drain. +public fun fund_treasury(state: &mut TutorialState, coin: Coin) { + if (state.treasury.is_some()) { + let mut existing = option::extract(&mut state.treasury); + coin::join(&mut existing, coin); + option::fill(&mut state.treasury, existing); + } else { + option::fill(&mut state.treasury, coin); + } +} + +/// Drain the treasury. `public(package)` keeps the function callable only +/// from sibling modules in `tutorial_transfer` (i.e. `transfer_vertex`), so +/// nothing outside this package can pull funds out directly. +public(package) fun take_treasury(state: &mut TutorialState): Coin { + option::extract(&mut state.treasury) +} +``` + +Key things to notice: + +- `TutorialState` is shared (`public_share_object`) so the workflow and the treasury funder can both reach it. +- `TransferVertexWitness` is stored inside `TutorialState` so its `UID` is stable for the package's lifetime — the on-chain tool registers against it once. +- `take_treasury` is `public(package)`. The sibling `transfer_vertex` module (next page) is the only caller; nothing outside the `tutorial_transfer` package can extract the coin directly. + +## 4. Validate locally + +Run the local validator before going anywhere near the chain: + +```bash +nexus tap validate-skill --config skill.tap.json +``` + +The validator resolves `tap_package_path` and `dag_path` relative to `--config`, so you do not need to point at the Move package separately. You should see: + +```text +[✓] Validating TAP skill config... +``` + +If the Move package fails to compile, the error surfaces here — fix the source and re-run. `validate-skill` doesn't touch the network, so iterations are fast. + +## What you have now + +- A `tap/Move.toml` and `tap/sources/tutorial_transfer.move` that compile against the published Nexus deps for your network. +- A `TutorialState` shared object with a SUI-coin treasury, a witness object, and a `fund_treasury` entry function. +- A `skill.tap.json` and `dag.json` still in their scaffold-default shapes — we'll edit those two pages from now. + +Next: [Write the on-chain transfer tool](3-tap-transfer-tool.md). diff --git a/nexus-sdk/guides/3-tap-transfer-tool.md b/nexus-sdk/guides/3-tap-transfer-tool.md new file mode 100644 index 0000000..d6cdbc7 --- /dev/null +++ b/nexus-sdk/guides/3-tap-transfer-tool.md @@ -0,0 +1,95 @@ +# Write the on-chain transfer tool + +The previous page set up `TutorialState` and the `take_treasury` helper. This page adds the actual on-chain Move tool — a sibling module named `transfer_vertex` whose `execute` function is what the workflow invokes per skill execution. + +The general mechanics of on-chain Move tools (`TaggedOutput`, witness types, the registration round-trip) are covered in detail in the [Onchain Tool Development guide](onchain-tool-development.md). This page only walks through what's _new_ for our TAP-bound transfer tool. + +## 1. Why a second Move module + +The on-chain tool the workflow calls is identified by `(package_id, module_name, function_name)`. The `module_name` ends up as a registry key, so each on-chain tool gets its own Move module. Our package will end up with two modules: + +```text +tutorial_transfer::tutorial_transfer // state + witness + helpers +tutorial_transfer::transfer_vertex // the on-chain vertex tool +``` + +`transfer_vertex` is what gets registered. The leader looks up `transfer_vertex::execute` by module + function name when it picks the walk up. + +## 2. Add `tap/sources/transfer_vertex.move` + +Drop the file alongside `tutorial_transfer.move`: + +```move +module tutorial_transfer::transfer_vertex; + +use nexus_primitives::data; +use nexus_primitives::proof_of_uid::ProofOfUID; +use nexus_primitives::tagged_output::{Self as tagged_output, TaggedOutput}; +use std::ascii::String as AsciiString; +use sui::transfer::public_transfer; +use tutorial_transfer::tutorial_transfer::{Self, TutorialState}; + +public struct TRANSFER_VERTEX has drop {} + +public enum Output { + Transferred { + amount: u64, + recipient: address, + }, +} + +public fun fqn(): AsciiString { + tutorial_transfer::transfer_vertex_fqn() +} + +/// On-chain transfer. +/// +/// Inputs (the workflow passes these via the DAG entry ports): +/// worksheet — workflow-supplied `ProofOfUID` for stamping. +/// port 0 — `state: &mut TutorialState` (shared) +/// port 1 — `recipient: address` +/// +/// The body drains the treasury, fires `public_transfer`, stamps the +/// worksheet, and returns a tagged output the workflow records on chain. +public fun execute( + worksheet: &mut ProofOfUID, + state: &mut TutorialState, + recipient: address, +): TaggedOutput { + let coin = tutorial_transfer::take_treasury(state); + let amount = coin.value(); + public_transfer(coin, recipient); + worksheet.stamp_with_data( + tutorial_transfer::transfer_vertex_witness_uid(state), + b"tutorial_transfer_done", + ); + + tagged_output::new(b"transferred") + .with_named_payload( + b"amount", + data::inline_one(amount.to_string().into_bytes()).as_number(), + ) + .with_named_payload( + b"recipient", + data::inline_one(recipient.to_ascii_string().into_bytes()).as_address(), + ) +} +``` + +## 3. What each line is doing + +- **`worksheet: &mut ProofOfUID`** — supplied by the workflow. Every on-chain vertex tool takes it. Calling `worksheet.stamp_with_data(witness_uid, b"…")` proves to the workflow that _this_ registered tool ran on _this_ walk. Skip the stamp and the workflow rejects the walk. +- **`take_treasury` + `public_transfer`** — the actual SUI move. Once the walk succeeds the recipient owns those funds outright. +- **`TaggedOutput::Transferred { amount, recipient }`** — the structured output the workflow records on chain. Downstream consumers can read it back via `nexus dag inspect-execution`. + +## 4. Re-validate locally + +Re-run the validator to confirm both modules still compile: + +```bash +nexus tap validate-skill --config skill.tap.json +``` + +You should still see `[✓] Validating TAP skill config...` — but now both modules are present and the package gates withdrawal correctly. + +Next: [DAG and skill config](4-tap-dag-and-skill-config.md). diff --git a/nexus-sdk/guides/4-tap-dag-and-skill-config.md b/nexus-sdk/guides/4-tap-dag-and-skill-config.md new file mode 100644 index 0000000..fc0f067 --- /dev/null +++ b/nexus-sdk/guides/4-tap-dag-and-skill-config.md @@ -0,0 +1,94 @@ +# DAG and skill config + +The Move package now compiles and exposes `transfer_vertex::execute`. Before we publish, we need to teach the workflow about it. That happens in two files: + +- `dag.json` — the workflow definition. We tell it about the on-chain vertex, its FQN, and which entry ports we'll feed at execute time. +- `skill.tap.json` — the TAP package skill manifest. We point it at the DAG and the TAP package and keep the rest of the requirements at scaffold defaults. + +Both files were created by `nexus tap scaffold` with off-chain-tool defaults. We're going to overwrite them. + +## 1. Rewrite `dag.json` + +The scaffold writes a one-vertex DAG referencing a placeholder off-chain weather tool. Replace it with our on-chain transfer vertex: + +```json +{ + "vertices": [ + { + "kind": { + "variant": "on_chain", + "tool_fqn": "tutorial.local.transfer_vertex@1" + }, + "name": "transfer_vertex", + "entry_ports": [{ "name": "0" }, { "name": "1" }] + } + ], + "edges": [] +} +``` + +What's going on: + +- **`variant: "on_chain"`** flips the vertex kind. The workflow runtime will expect an on-chain Move tool registered under the FQN below. +- **`tool_fqn: "tutorial.local.transfer_vertex@1"`** is the FQN you set in the Move source and that the registration on the next page will use. The Move source, the DAG, and the on-chain tool registration must all agree on this string. +- **`name: "transfer_vertex"`** is the vertex name inside the DAG. It's what we type when we feed inputs at execute time (`--input-json '{"transfer_vertex": {...}}'`). +- **`entry_ports`** lists the inputs the workflow will collect from the invoker. Port `"0"` is the `state` object and port `"1"` is the recipient address. The workflow prepends `worksheet` to the call automatically, so the Move `execute(worksheet, state, recipient)` lines up. + +You're not declaring types here; the leader reads the registered tool's input schema at runtime and validates the entry-port JSON against it. + +## 2. Rewrite `skill.tap.json` + +```json +{ + "name": "tutorial transfer", + "tap_package_name": "tutorial_transfer", + "dag_path": "dag.json", + "tap_package_path": "tap", + "requirements": { + "input_schema_commitment": [ + 116, 117, 116, 111, 114, 105, 97, 108, 45, 105, 110, 112, 117, 116 + ], + "payment_policy": "UserFunded", + "schedule_policy": { + "recurrence": "Once", + "allow_recursive": false + }, + "fixed_tools": [] + }, + "interface_revision": 1 +} +``` + +Field by field: + +- **`tap_package_name`** must match the Move package name (`tutorial_transfer`) — `publish-skill` uses it as the named-address override when it compiles the package. +- **`dag_path` / `tap_package_path`** are relative to this file. The scaffold wires both for you and we keep them as-is. +- **`requirements.input_schema_commitment`** is an opaque byte vector that identifies the expected input shape. The JSON above encodes the ASCII string `tutorial-input`; anything reproducible works because downstream tooling treats it as an identifier. +- **`payment_policy: "UserFunded"`** means the wallet calling `nexus tap execute` supplies the SUI for the Talus agent execution payment. The alternative shape is `{"AgentFunded": {"max_budget": }}`, which draws from the agent's payment vault and caps the requested budget. +- **`schedule_policy.recurrence = "Once"`** keeps the demo synchronous. Recursive schedules use `{"Recursive": {"min_interval_ms": , "max_occurrences": }}` and must set `allow_recursive: true`. +- **`fixed_tools: []`** means this skill does not preserve any registry-verified fixed tools in its DAG. Fixed tools are a DAG preservation requirement, not an authorization grant list. +- **`interface_revision: 1`** is the current Talus agent skill interface generation; bump it only when the on-chain interface ships a new revision. + +## 3. Dry-run + +Run the local dry-run to confirm the DAG, the on-chain tool reference, and the skill requirements all line up: + +```bash +nexus tap dry-run --config skill.tap.json +``` + +You should see the validation summary again — no chain calls happen yet. If the DAG references an unknown FQN or the entry ports don't match the registered tool's schema, the dry-run is where you'll catch it. + +> Note: `dry-run` checks the DAG's structure and the skill's requirements against the configured Nexus deployment, but it does **not** execute the Move tool. The tool only runs once a leader picks the walk up after `nexus tap execute …`. + +## 4. What changed + +You now have: + +- A `dag.json` whose only vertex is the on-chain transfer tool we wrote. +- A `skill.tap.json` whose `payment_policy` makes the invoker pay for each execution, whose `schedule_policy` keeps everything single-shot, and whose `fixed_tools` requirement is empty. +- A `validate-skill` and `dry-run` that both pass. + +Everything is still local — nothing has touched the chain yet. The next page goes on chain three times: publish the Move package + DAG, register the on-chain tool, and bind the agent. + +Next: [Publish, register, bind](5-tap-publish-and-register.md). diff --git a/nexus-sdk/guides/5-tap-publish-and-register.md b/nexus-sdk/guides/5-tap-publish-and-register.md new file mode 100644 index 0000000..b865472 --- /dev/null +++ b/nexus-sdk/guides/5-tap-publish-and-register.md @@ -0,0 +1,153 @@ +# Publish, register, bind + +Three on-chain transactions in this page: + +1. `nexus tap publish-skill` — publishes the TAP Move package, publishes the DAG, and writes a publish artifact JSON. +1. `nexus tool register onchain` — adds the on-chain transfer vertex to the tool registry. +1. `nexus tap bind` — creates a Talus agent and registers the skill against it in one transaction. + +Each step records what the next one needs. Capture the IDs as you go. + +## 1. Publish the Move package and DAG + +```bash +nexus tap publish-skill \ + --config skill.tap.json \ + --out artifact.json \ + --sui-gas-budget 500000000 \ + --json | tee publish-skill.json +``` + +What `publish-skill` does in a single transaction: + +- Builds and publishes `tap/` as a new Move package. +- Publishes the DAG in `dag.json` on chain, getting back a `dag_id`. +- Computes the substituted requirements from `skill.tap.json` (in this guide there is nothing to substitute because `fixed_tools` is empty). +- Builds a `TapPublishArtifact` from the DAG id, interface revision, and simplified requirements. +- Writes a `TapPublishArtifact` JSON to `--out`. Downstream `tap register-skill`, `tap bind`, and `tap update-skill` consume this file. + +The JSON output gives you the two IDs you'll keep referring to: + +```json +{ + "standard_tap": true, + "function": "publish_skill", + "tap_package_id": "0x556e5acd093ff4ba407cd5677abf27a72a7cf7e3023ae862806260d0ccfd54b2", + "dag_id": "0xcf1ce804f37973437354784683895736304727e9e6a19bbe467cd1f2a8fa2267", + ... +} +``` + +(IDs in this guide are illustrative — yours will differ.) + +Capture them as shell variables for the rest of the page: + +```bash +PKG=$(jq -r '.tap_package_id' publish-skill.json) +DAG=$(jq -r '.dag_id' publish-skill.json) +``` + +## 2. Find the freshly-published TutorialState id + +The Move `init` function creates and _shares_ one `TutorialState`. Because it's a shared object it doesn't show up in `sui client objects ` (which only lists owned objects), and `sui client object --json` returns BCS-encoded contents rather than parsed Move fields. We use the Sui JSON-RPC instead, which gives us the parsed `objectChanges` from the publish transaction and the parsed field tree of the shared state: + +```bash +RPC_URL=$(grep -E '^rpc_url' ~/.nexus/conf.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') +ACTIVE=$(sui client active-address) + +STATE=$(curl -s "$RPC_URL" -H 'Content-Type: application/json' \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"suix_queryTransactionBlocks\",\"params\":[{\"filter\":{\"FromAddress\":\"$ACTIVE\"},\"options\":{\"showObjectChanges\":true}},null,3,true]}" | + jq -r --arg pkg "$PKG" \ + '.result.data[].objectChanges[]? + | select(.objectType? // "" | endswith("::tutorial_transfer::TutorialState")) + | select(.objectType | startswith($pkg)) + | .objectId' | head -1) + +WITNESS=$(curl -s "$RPC_URL" -H 'Content-Type: application/json' \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"sui_getObject\",\"params\":[\"$STATE\",{\"showContent\":true}]}" | + jq -r '.result.data.content.fields.transfer_vertex_witness.fields.id.id') + +echo "STATE=$STATE WITNESS=$WITNESS" +``` + +`STATE` is the shared `TutorialState` object id; `WITNESS` is the UID we'll register as the on-chain tool's `tool_witness_id`. The publish transaction is in the wallet's recent history because `nexus tap publish-skill` was the last state-changing call. + +## 3. Register the on-chain transfer tool + +```bash +nexus tool register onchain \ + --package "$PKG" \ + --module transfer_vertex \ + --tool-fqn tutorial.local.transfer_vertex@1 \ + --description "Tutorial transfer vertex" \ + --tool-witness-id "$WITNESS" \ + --sui-gas-budget 500000000 \ + --json +``` + +A few things worth knowing: + +- **`--package` and `--module`** must match the Move package id and module name. The CLI derives the tool's input/output schemas from the on-chain Move ABI, so a mismatch fails fast. +- **`--tool-fqn`** must equal the FQN you set in the Move source and in `dag.json`. All three must agree. +- **`--tool-witness-id`** ties the tool registration to the `TransferVertexWitness` inside `TutorialState`. + +The JSON output includes the derived `tool_id`, `tool_gas_id`, and the decoded schemas. The tool registers through the plain (non-cap-gated) entry point, so the workflow will dispatch walks against it without minting any per-walk authorization cap. + +## 4. Create the agent and register the skill + +`nexus tap bind` does this in a single PTB: it calls `tap::create_agent` and then `tap::register_skill` with the artifact's DAG id, input commitment, payment policy, schedule policy, and empty fixed-tool requirement. + +```bash +nexus tap bind \ + --artifact artifact.json \ + --sui-gas-budget 500000000 \ + --json +``` + +Output: + +```json +{ + "function": "bind_agent_skill", + "agent_id": "0x31984f6acbb08ffa1dc053659c9e4af5327459b1ba2ca723ae04ca72dae98cf3", + "skill_id": 0, + "dag_id": "0xcf1ce804f37973437354784683895736304727e9e6a19bbe467cd1f2a8fa2267", + ... +} +``` + +`tap bind` always creates a _new_ agent every time it's called. Capture the agent id from the first invocation by piping the JSON to a file so a second `tap bind` does not silently provision a second agent on top of the first: + +```bash +nexus tap bind \ + --artifact artifact.json \ + --sui-gas-budget 500000000 \ + --json > bind.json + +AGENT=$(jq -r '.agent_id' bind.json) +``` + +> **Re-running the guide?** If you already have an agent, use `nexus tap register-skill --agent-id --artifact artifact.json` instead of `tap bind`. + +## 5. Confirm in the registry + +```bash +nexus tap registry show --json | jq --arg agent "$AGENT" '{ + agents: [.agents[] | select(.agent_id == $agent)], + skills: [.skills[] | select(.agent_id == $agent)] +}' +``` + +You should see exactly one agent entry with your `agent_id`, and one skill entry with `skill_id: 0`, `current_interface_revision: 1`, and a DAG binding matching the value you captured from `publish-skill`. The skill's stored requirements carry an empty `fixed_tools` list. + +`nexus tap default-agent show` is unaffected — that's the registry-managed default agent, not your new agent. + +## What you have now + +- A published TAP Move package and DAG. Their ids are in `publish-skill.json`; the reusable skill artifact is in `artifact.json`. +- A registered on-chain transfer vertex tool through the plain (non-cap-gated) entry point. +- A new Talus agent with one skill bound to it. The skill's `skill_id` is `0` (skills are numbered per-agent starting at 0). + +The agent is empty so far — the treasury inside `TutorialState` is still `option::none()`. The next page funds it and runs the first execution. + +Next: [Execute and verify the transfer](6-tap-execute-and-settle.md). diff --git a/nexus-sdk/guides/6-tap-execute-and-settle.md b/nexus-sdk/guides/6-tap-execute-and-settle.md new file mode 100644 index 0000000..a156053 --- /dev/null +++ b/nexus-sdk/guides/6-tap-execute-and-settle.md @@ -0,0 +1,188 @@ +# Execute and verify the transfer + +Time to run the skill. From here on you need three values from earlier pages: + +```bash +PKG= +STATE= +AGENT= +``` + +Pick a recipient address — any Sui wallet, including a vanity address you don't actually own. The example below uses `0x000…face`: + +```bash +RECIPIENT=0x000000000000000000000000000000000000000000000000000000000000face +RPC_URL=$(grep -E '^rpc_url' ~/.nexus/conf.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') +``` + +## 1. Fund the treasury + +The skill's `execute` empties whatever coin is sitting in `TutorialState.treasury`. We deposit 0.1 SUI before running the workflow. `fund_treasury` is a plain Move entry function, so we use a small Sui PTB to split a coin off the gas object and pass it in: + +```bash +sui client ptb \ + --split-coins gas '[100000000]' --assign deposit \ + --move-call "$PKG::tutorial_transfer::fund_treasury" "@$STATE" deposit.0 \ + --gas-budget 50000000 \ + --json | jq '.effects.status' +``` + +The `100000000` is the deposit amount in MIST (0.1 SUI). The PTB: + +- Splits a 0.1 SUI coin off the transaction's gas coin. +- Calls `tutorial_transfer::fund_treasury(state, deposit_coin)`. +- Leaves the rest of the gas coin where it was. + +Confirm the treasury balance: + +```bash +curl -s "$RPC_URL" -H 'Content-Type: application/json' \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"sui_getObject\",\"params\":[\"$STATE\",{\"showContent\":true}]}" | + jq -r '.result.data.content.fields.treasury.fields.balance' +``` + +Expected: `100000000`. + +## 2. Pick a payment coin and execute the skill + +`nexus tap execute` submits one transaction that: + +- Locks a Talus agent `ExecutionPayment` (paid out of the wallet's coins). +- Initialises the `DAGExecution` object and shares it. +- Calls the workflow's `request_network_to_execute_walks`, which emits a `RequestWalkExecutionEvent` for the `transfer_vertex` walk. The leader picks the event up, runs `transfer_vertex::execute(worksheet, state, recipient)` on chain, and marks the walk `Successful`. Your wallet sees `consumed` MIST debited from the payment object; the recipient receives whatever was in the treasury. + +Pick any coin that has enough room for the payment max-budget (50 million MIST in the example below — adjust to taste): + +```bash +PAYMENT_COIN=$(sui client gas --json | + jq -r '[.[] | select(.mistBalance > 60000000)][0].gasCoinId') +``` + +Then run the skill: + +```bash +INPUT_JSON=$(jq -cn \ + --arg state "$STATE" \ + --arg recipient "$RECIPIENT" \ + '{transfer_vertex: {"0": $state, "1": $recipient}}') + +EXEC_JSON=$(nexus tap execute \ + --agent-id "$AGENT" \ + --skill-id 0 \ + --input-json "$INPUT_JSON" \ + --payment-max-budget 50000000 \ + --sui-gas-coin "$PAYMENT_COIN" \ + --sui-gas-budget 500000000 \ + --json) + +EXEC=$(printf '%s' "$EXEC_JSON" | jq -r '.execution_id') +echo "Execution: $EXEC" +``` + +The output gives you `execution_id` and `tx_checkpoint`: + +```json +{ + "agent_dag": true, + "agent_id": "0x31984f6acbb08ffa1dc053659c9e4af5327459b1ba2ca723ae04ca72dae98cf3", + "skill_id": 0, + "execution_id": "0x7b582d5fe921f4a35dcdb9897c5fc66e3d2ebae5301e3fd43376ed9576e15ea9", + "digest": "...", + "tx_checkpoint": 117137, + "submit": { /* ... */ } +} +``` + +## 3. Wait for the recipient balance to increase + +The actual transfer happens when the leader executes the on-chain vertex tool. From your CLI's point of view, the easiest check is the recipient's SUI balance: + +```bash +for i in $(seq 1 30); do + BAL=$(curl -s "$RPC_URL" -H 'Content-Type: application/json' \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"suix_getBalance\",\"params\":[\"$RECIPIENT\"]}" | + jq -r '.result.totalBalance') + if [ "$BAL" != "0" ] && [ -n "$BAL" ]; then + echo "Recipient balance: $BAL MIST" + break + fi + sleep 2 +done +``` + +You should see the deposit amount (`100000000` MIST in the example) land within ~15 seconds on a healthy network. + +You can also confirm the treasury has been drained: + +```bash +curl -s "$RPC_URL" -H 'Content-Type: application/json' \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"sui_getObject\",\"params\":[\"$STATE\",{\"showContent\":true}]}" | + jq '.result.data.content.fields.treasury' +``` + +The field should be `null` — the coin moved out of state into the recipient address. + +## 4. Inspect the execution and payment + +`nexus dag inspect-execution` reads the on-chain `DAGExecution` plus its event stream, returning the structured `TaggedOutput` the vertex emitted: + +```bash +nexus dag inspect-execution \ + --dag-execution-id "$EXEC" \ + --json | jq +``` + +Look for the `transferred` tagged variant with `amount` and `recipient` matching what you deposited and the destination wallet you supplied. + +You can also inspect the payment object directly: + +```bash +PAYMENT_ID=$(curl -s "$RPC_URL" -H 'Content-Type: application/json' \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"sui_getObject\",\"params\":[\"$EXEC\",{\"showContent\":true}]}" | + jq -r '.result.data.content.fields.tap_payment_id') + +nexus tap payments show --payment-id "$PAYMENT_ID" --json +``` + +Useful fields in that JSON: + +- **`consumed`** — gas the leader's tool-eval consumed. Should be > 0. +- **`outstanding_locks`** — `0` once the walk is no longer holding the payment. +- **`accomplished` / `refunded` / `terminal` / `final_state`** — the settlement signal. Payment settlement is asynchronous and may lag the walk completion by seconds to minutes depending on leader cadence; the recipient balance arrives first, the payment terminal flag lands shortly after. + +If you want to block until the payment object lands in a terminal state, `nexus tap payments wait --payment-id --timeout-secs 120` polls for you. It's optional — for verification, the recipient balance is the source of truth. + +## 5. Cost summary + +`nexus dag execution-cost` rolls up the Talus agent payment consumption: + +```bash +nexus dag execution-cost --dag-execution-id "$EXEC" --json +``` + +Returns `payment_id`, `max_budget`, `locked_budget`, `consumed`, `outstanding_locks`, plus `accomplished`/`refunded` flags. This is the same data `payments show` returns, scoped to one execution. + +## What you built + +End-to-end, your skill does this on every call: + +1. Invoker submits `nexus tap execute` with a payment coin. Workflow locks the payment, records the `DAGExecution`, shares it, and emits a `RequestWalkExecutionEvent` for the `transfer_vertex` walk. +1. Leader picks the walk up, runs `transfer_vertex::execute(worksheet, state, recipient)` on chain. +1. `execute` drains the treasury, fires `public_transfer` to the recipient, stamps the worksheet, and returns the `Transferred` tagged output. +1. Workflow records the walk as `Successful`; the payment settles asynchronously. +1. You see the recipient balance go up; `inspect-execution` and `payments show` confirm the on-chain trail. + +Re-running just means funding the treasury again and calling `tap execute` again with a fresh recipient (or the same one). + +{% hint style="danger" %} +**This flow is minimal, not production-authorized.** Anyone who can reach a workflow dispatch against `(agent, skill)` will drain the treasury because there is no per-call authorization check on `transfer_vertex::execute`. The only thing keeping the funds in place is the `public(package)` visibility on `take_treasury`, which prevents *direct* Move-side calls from other packages; it does **not** prevent another skill author from publishing their own DAG that lists `tutorial.local.transfer_vertex@1` in its entry vertex and submitting `tap execute` against their own agent. Treat this guide as an introduction to the workflow lifecycle, not as a production pattern. The cap concept (`WorkflowVertexAuthorizationGrant`, `VertexAuthorizationCheckCap`, fixed-tool requirements, and `--workflow-authorization-cap-first`) plus the state-bound grant-id check that closes the multi-`(agent, skill)` attack will land in a follow-up cap-gated TAP guide. +{% endhint %} + +## Next steps + +The CLI surface for the rest of TAP package and Talus agent operation is the natural follow-up reading — start with [CLI reference: `nexus tap`](../cli.md) and look at: + +- **`nexus tap vault deposit`** to pre-fund a payment vault on the agent instead of paying per-call. +- **`nexus tap schedule-task --payment-source agent-vault`** and **`nexus tap schedule-task --payment-source address-funded`** to create and fund scheduled TAP executions. +- **`nexus tap update-skill`** for moving an existing skill to a new current revision. +- **`nexus dag execution-cost`** and **`nexus tap payments list`** for observability on what executions cost the operator across an agent's lifetime. diff --git a/nexus-sdk/guides/dag-construction.md b/nexus-sdk/guides/dag-construction.md index eced845..944b7fa 100644 --- a/nexus-sdk/guides/dag-construction.md +++ b/nexus-sdk/guides/dag-construction.md @@ -2,7 +2,7 @@ This guide explains how to construct DAG (Directed Acyclic Graph) JSON files for the Nexus platform. DAGs define the workflow that an Agent will execute. -For an explanation of the terms and rules used below, refer to [the Nexus workflow documentation](../../nexus-next/packages/workflow.md). +For an explanation of the terms and rules used below, refer to [the Nexus workflow documentation][nexus-next-workflow]. {% hint style="info"%} Note that for all DAG related terms in the configuration JSON file, snake casing is applied. @@ -14,10 +14,14 @@ A DAG JSON file consists of sections defining the graph's components: ```json { - "vertices": [ ... ], // All vertices in the DAG - "edges": [ ... ], // Connections defining data flow - "default_values": [ ... ], // Static inputs for vertices - "entry_groups": [ ... ] // Named starting points (Optional) + "vertices": [ ... ], // All vertices in the DAG + "edges": [ ... ], // Connections defining data flow + "default_values": [ ... ], // Static inputs for vertices (Optional) + "entry_groups": [ ... ], // Named starting points (Optional) + "post_failure_action": "...", // Default failure behavior (Optional) + "leader_verifier": { ... }, // Leader request verification (Optional) + "tool_verifier": { ... }, // Tool response verification (Optional) + "outputs": [ ... ] // DAG return values (Optional) } ``` @@ -89,7 +93,7 @@ Edges define the flow of data between vertices, connecting an output port of a s - **`do_while`** → Repeats execution by looping back as long as a condition is satisfied. - **`break`** → Exits a `do_while` loop when the condition is no longer met. -Read more about looping and flow controls in the [looping documentation](../../nexus-next/flow-controls/looping.md). +Read more about looping and flow controls in the [looping documentation][looping]. ## 4. Default Values @@ -108,8 +112,8 @@ Default values provide static inputs to vertices: **Important Constraints:** -- An _input port_ can receive data either from an _incoming edge_ or a _default value_, but **never both**. ([workflow rules](../../nexus-next/packages/workflow.md) Rule 4) -- Entry ports **cannot** have default values (by definition). Default values are only permitted for input ports that are _not_ entry ports. ([workflow rules](../../nexus-next/packages/workflow.md) Rule 11) +- An _input port_ can receive data either from an _incoming edge_ or a _default value_, but **never both**. ([workflow rules][nexus-next-workflow] Rule 4) +- Entry ports **cannot** have default values (by definition). Default values are only permitted for input ports that are _not_ entry ports. ([workflow rules][nexus-next-workflow] Rule 11) ## 5. Entry Groups (Optional) @@ -137,7 +141,54 @@ Practically speaking, this means that you'll need to add all vertices to the ent - will immediately start execution - need to be provided client input for entry ports -## 6. Outputs (Optional) +## 6. Post-Failure Action (Optional) + +The `post_failure_action` field at the DAG level sets the default behavior when a vertex execution fails. This can be overridden on individual vertices: + +```json +{ + "post_failure_action": "continue" // or "terminate" +} +``` + +- **`continue`** → Continue DAG execution despite the failure (TransientContinue) +- **`terminate`** → Stop DAG execution immediately (Terminate) + +Vertex-level `post_failure_action` values override the DAG-level setting. + +## 7. Verifier Configuration (Optional) + +### Leader Verifier + +Configures how the workflow verifies the leader/tool communication proof for off-chain result submission. Use registered-key verification when the signed HTTP session is the proof material: + +```json +{ + "leader_verifier": { + "mode": "leader_registered_key", // Verification mode + "method": "signed_http_v1" // Verification method + } +} +``` + +### Tool Verifier + +Configures a custom on-chain verifier package for tool output policy: + +```json +{ + "tool_verifier": { + "mode": "tool_verifier_contract", // Verification mode + "method": "demo_verifier_v1" // Verification method + } +} +``` + +Verifier configuration can also be specified at the vertex level to override DAG-level settings. + +`leader_registered_key` with `signed_http_v1` requires the Tool's signed HTTP response key to be registered in Network Auth. See [Tool Communication (HTTPS + Signed HTTP)](tool-communication.md). `tool_verifier_contract` is a separate path for registered verifier packages. + +## 8. Outputs (Optional) Outputs can be defined on vertices that have no outgoing edges. These can be thought of as the return values of a DAG execution. Only ports that are specified here will be part of the `EndStateReachedEvent` emitted by the DAG execution. @@ -163,11 +214,11 @@ Outputs can be defined on vertices that have no outgoing edges. These can be tho - A default entry group can be named `_default_group`. This group is used when no `--entry-group` flag is provided during execution. - If no _entry group_ is specified, all vertices that have _entry ports_ are considered part of the `_default_group`. -## 7. Validation Rules +## 9. Validation Rules -The [Nexus CLI](../cli.md) (`nexus dag validate`) performs static analysis to enforce the critical rules defined in [workflow rules](../../nexus-next/packages/workflow.md). +The [Nexus CLI][nexus-cli] (`nexus dag validate`) performs static analysis to enforce the critical rules defined in [workflow rules][nexus-next-workflow]. -## 8. Best Practices +## 10. Best Practices 1. **Naming Conventions**: - Use descriptive names for vertices. @@ -186,7 +237,7 @@ The [Nexus CLI](../cli.md) (`nexus dag validate`) performs static analysis to en - Document the purpose of each vertex. - Refer to the tool documentation for the expected input/output formats for each vertex. -## 9. Example Workflow +## 11. Example Workflow Here's a step-by-step process to create a DAG: @@ -218,7 +269,7 @@ Here's a step-by-step process to create a DAG: - Verify all connections - Test with sample inputs -## 10. Examples +## 12. Examples For working examples, see the following files in the `cli/src/dag/_dags` directory: @@ -229,5 +280,11 @@ For working examples, see the following files in the `cli/src/dag/_dags` directo - `ig_story_planner_valid.json`: Example of a complex workflow - `entry_groups_valid.json`: Example of using entry groups. -For examples of invalid DAGs and common mistakes to avoid (especially regarding Rule 5 - Race Conditions), see the diagrams in [workflow documentation](../../nexus-next/packages/workflow.md) and the `*_invalid.json` files in the [testing DAG directory](https://github.com/Talus-Network/nexus-sdk/tree/v1.0.0/sdk/src/dag/_dags). +For examples of invalid DAGs and common mistakes to avoid (especially regarding Rule 5 - Race Conditions), see the diagrams in [workflow documentation][nexus-next-workflow] and the `*_invalid.json` files in the [testing DAG directory][example-dags]. + + +[nexus-next-workflow]: ../../nexus-next/packages/workflow.md +[example-dags]: https://github.com/Talus-Network/nexus-sdk/tree/v2.0.0-rc.2/sdk/src/dag/_dags +[nexus-cli]: ../cli.md +[looping]: ../../nexus-next/flow-controls/looping.md diff --git a/nexus-sdk/guides/llm-openai-chat-prep-tool.md b/nexus-sdk/guides/llm-openai-chat-prep-tool.md index e262240..52c9e03 100644 --- a/nexus-sdk/guides/llm-openai-chat-prep-tool.md +++ b/nexus-sdk/guides/llm-openai-chat-prep-tool.md @@ -379,4 +379,3 @@ Consider for what use cases you could use this tool to prepare it to add as an L ## Next Steps This tool provides a simple but essential bridge between mathematical operations and chat completion, enabling the creation of more sophisticated DAGs that combine numerical computation with natural language processing. Follow along with the developer guides to expand the [Math Branching Example DAG with LLM chat completion](math-branching-with-chat.md). - diff --git a/nexus-sdk/guides/math-branching-dag-builder.md b/nexus-sdk/guides/math-branching-dag-builder.md index 479a970..e493441 100644 --- a/nexus-sdk/guides/math-branching-dag-builder.md +++ b/nexus-sdk/guides/math-branching-dag-builder.md @@ -485,4 +485,3 @@ This example showcases how to combine simple tools and DAG structure definitions ## Up Next Want to extend this example? Follow the next part of the guide to see how we can add another entry point to the DAG and manage this through entry groups. - diff --git a/nexus-sdk/guides/math-branching-dag-entry.md b/nexus-sdk/guides/math-branching-dag-entry.md index 1536315..34a1bf5 100644 --- a/nexus-sdk/guides/math-branching-dag-entry.md +++ b/nexus-sdk/guides/math-branching-dag-entry.md @@ -1,6 +1,6 @@ # Extending Your DAG with Entry Groups -This guide builds on the [Build the Quickstart guide](./math-branching-dag-builder.md) by extending the example to support multiple entry points using entry groups. You'll take the original [`math_branching.json`](https://github.com/Talus-Network/nexus-sdk/blob/main/sdk/src/dag/_dags/math_branching.json) DAG and add an alternative entry path that allows users to directly provide two numbers for multiplication instead of adding a constant to the input. +This guide builds on the [Build the Quickstart guide][math-branching-dag-builder-guide] by extending the example to support multiple entry points using entry groups. You'll take the original [`math_branching.json`](https://github.com/Talus-Network/nexus-sdk/blob/main/sdk/src/dag/_dags/math_branching.json) DAG and add an alternative entry path that allows users to directly provide two numbers for multiplication instead of adding a constant to the input. {% hint style="info" %} Prerequisites Follow the [setup guide](setup.md) to get properly setup in case you haven't. @@ -602,5 +602,9 @@ In this guide, we extended our original branching math DAG to support multiple e Entry groups are a powerful feature of Nexus DAGs that enable more flexible and modular workflows while maintaining the safety guarantees of the DAG execution model. They allow a single DAG to support multiple different starting states and input combinations while preventing potential race conditions. -For more advanced usage of entry groups and other DAG features, refer to the [DAG Construction Guide](./dag-construction.md). +For more advanced usage of entry groups and other DAG features, refer to the [DAG Construction Guide][dag-construction]. + + +[dag-construction]: ./dag-construction.md +[math-branching-dag-builder-guide]: ./math-branching-dag-builder.md diff --git a/nexus-sdk/guides/math-branching-quickstart.md b/nexus-sdk/guides/math-branching-quickstart.md index 5a00707..3e17b06 100644 --- a/nexus-sdk/guides/math-branching-quickstart.md +++ b/nexus-sdk/guides/math-branching-quickstart.md @@ -149,4 +149,3 @@ When you execute the DAG via the `nexus dag execute` command, a successful outpu - Read the full [Agent Builder Guide](math-branching-dag-builder.md) to understand how this DAG is constructed - Study the [DAG Construction Guide](dag-construction.md) for more advanced DAG features - Try building your own DAG with different tools and logic flows - diff --git a/nexus-sdk/guides/math-branching-with-chat.md b/nexus-sdk/guides/math-branching-with-chat.md index 4f469e7..1cfe0d6 100644 --- a/nexus-sdk/guides/math-branching-with-chat.md +++ b/nexus-sdk/guides/math-branching-with-chat.md @@ -1,6 +1,6 @@ # Extending the Math Branching DAG with Chat Completion -This guide builds on the [Math Branching DAG with Entry Groups](./math-branching-dag-entry.md) by adding a chat completion tool that explains the mathematical results. You'll learn how to: +This guide builds on the [Math Branching DAG with Entry Groups][math-branching-entry-guide] by adding a chat completion tool that explains the mathematical results. You'll learn how to: 1. Understand the need for a custom tool to bridge between math operations and chat completion 1. Add the chat completion tool to the DAG @@ -15,7 +15,7 @@ Follow the [setup guide](setup.md) to get properly setup in case you haven't. Before you can connect our math operations to the chat completion tool, you need to understand a key challenge: type safety. The [LLM chat completion tool](../../tools/llm-openai-chat-completion/README.md)expects a `Message` struct as input, but the [math tool](../../tools/math/README.md) outputs numbers. You can't directly connect these without proper type conversion. -This is where you need a custom tool to bridge this gap. You'll use the `xyz.taluslabs.llm.openai.chat-prep@1` tool that you developed in the [Build the Missing Tool guide](./llm-openai-chat-prep-tool.md). This tool converts numbers into the proper message format that the chat completion tool expects. +This is where you need a custom tool to bridge this gap. You'll use the `xyz.taluslabs.llm.openai.chat-prep@1` tool that you developed in the [Build the Missing Tool guide][llm-openai-chat-prep-tool]. This tool converts numbers into the proper message format that the chat completion tool expects. ## Step 1: Adding the Required Tools @@ -662,3 +662,7 @@ This extended DAG demonstrates how to combine mathematical computation with natu This extended DAG demonstrates how to combine mathematical computation with natural language processing, creating a more interactive and engaging experience for users. + + +[math-branching-entry-guide]: ./math-branching-dag-entry.md +[llm-openai-chat-prep-tool]: ./llm-openai-chat-prep-tool.md diff --git a/nexus-sdk/guides/onchain-tool-development.md b/nexus-sdk/guides/onchain-tool-development.md index 1578c3b..49f12fe 100644 --- a/nexus-sdk/guides/onchain-tool-development.md +++ b/nexus-sdk/guides/onchain-tool-development.md @@ -83,7 +83,7 @@ use std::ascii::String as AsciiString; /// One-time witness for package initialization. public struct MY_ONCHAIN_TOOL has drop {} -/// Witness object used to identify this tool. +/// Witness object used as the worksheet stamp locator for this tool. public struct MyToolWitness has key, store { id: UID, } @@ -91,7 +91,6 @@ public struct MyToolWitness has key, store { /// Your tool's state object (customize as needed). public struct MyToolState has key { id: UID, - /// Store the witness object that identifies this tool. witness: Bag, // Add your application-specific fields here // Example: value: u64, @@ -151,7 +150,7 @@ This is the core of your tool, the function that performs the actual execution: /// 1. First parameter: worksheet: &mut ProofOfUID /// 2. Last parameter: ctx: &mut TxContext /// 3. Return type: TaggedOutput -/// 4. Must stamp worksheet with witness ID +/// 4. Must stamp worksheet with tool witness ID public fun execute( worksheet: &mut ProofOfUID, state: &mut MyToolState, @@ -160,11 +159,8 @@ public fun execute( clock: &Clock, ctx: &mut TxContext, ): TaggedOutput { - // Get the witness for stamping. - let witness = state.witness(); - - // REQUIRED: Stamp the worksheet to prove execution - worksheet.stamp_with_data(&witness.id, b"my_tool_executed"); + // REQUIRED: Stamp the worksheet with the tool witness ID to prove execution + worksheet.stamp_with_data(&state.witness().id, b"my_tool_executed"); // Implement your tool logic here if (input_value == 0) { @@ -221,10 +217,10 @@ fun witness(self: &MyToolState): &MyToolWitness { self.witness.borrow(b"witness") } -/// Get the witness ID for external reference. +/// Get the tool witness ID for external reference. /// Useful for registering the tool onchain. -public fun witness_id(self: &MyToolState): ID { - self.witness().id.to_inner() +public fun tool_witness_id(self: &MyToolState): ID { + object::uid_to_inner(&self.witness().id) } // Add getters for your custom fields @@ -260,16 +256,15 @@ export PACKAGE_ID="0x..." After publishing, you'll need: 1. **Module Path**: Combination of package address and module name (e.g., "0xPACKAGE_ID::my_tool") -1. **Witness ID**: Object ID of your witness object -1. **\*ToolState**: The shared object necessary as argument for the execute function. _This ID is not required for tool registration._ +1. **Tool witness ID**: Object ID of the witness object stored under your shared tool state. This is used as the inert execution stamp locator during registration. +1. **\*ToolState**: The shared object necessary as argument for the execute function. This is often the object that stores the witness, but it is not the value passed as `--tool-witness-id`. -You can find the witness ID in the explorer by looking up the Witness object in the dynamic field ID that is given -to you in the publish output. This object has type: `0x2::dynamic_field::Field, PACKAGE_ID::my_onchain_tool::MyToolWitness>` +You can find the tool witness ID in the explorer by looking up the shared state object created by your package initialization and reading its `witness` dynamic field, or by exposing and calling a `tool_witness_id` getter. -Alternatively, you can find the witness ID by using the CLI: +Alternatively, you can inspect the state object by using the Sui CLI: ```bash -sui client object +sui client object ``` ### Step 3: Register with Nexus @@ -281,7 +276,7 @@ nexus tool register onchain \ --module-path "$PACKAGE_ID::my_onchain_tool" \ --tool-fqn "xyz.mydomain.my_onchain_tool@1" \ --description "My custom onchain tool that processes values" \ - --witness-id "0x..." + --tool-witness-id "0x..." ``` The CLI will: @@ -379,4 +374,3 @@ This workflow only executes the onchain tool twice if the output variant is Succ - **Examples**: Study the [onchain tool example modules](../../nexus-next/sui/examples/) and [corresponding json dag workflows](../../sdk/src/dag/_dags/) Remember that onchain tools are powerful building blocks in the Nexus ecosystem. Well-designed tools can be composed with others to create sophisticated autonomous agents and workflows. - diff --git a/nexus-sdk/guides/setup.md b/nexus-sdk/guides/setup.md index 5042331..f3a99ff 100644 --- a/nexus-sdk/guides/setup.md +++ b/nexus-sdk/guides/setup.md @@ -38,7 +38,7 @@ To install directly from the source using `cargo`, run: ```bash cargo install nexus-cli \ --git https://github.com/talus-network/nexus-sdk \ - --tag v1.0.0 \ + --tag v2.0.0-rc.2 \ --locked ``` @@ -54,7 +54,7 @@ nexus --version {% tab title="Testnet" %} ```bash -wget -O ~/.nexus/objects.testnet.toml https://storage.googleapis.com/production-talus-sui-objects/v1.0.0/objects.testnet.toml +wget -O ~/.nexus/objects.testnet.toml https://storage.googleapis.com/production-talus-sui-objects/v2.0.0-rc.2/objects.testnet.toml ``` {% endtab %} @@ -62,7 +62,7 @@ wget -O ~/.nexus/objects.testnet.toml https://storage.googleapis.com/production- {% tab title="Mainnet" %} ```bash -wget -O ~/.nexus/objects.mainnet.toml https://storage.googleapis.com/production-talus-sui-objects/v1.0.0/objects.mainnet.toml +wget -O ~/.nexus/objects.mainnet.toml https://storage.googleapis.com/production-talus-sui-objects/v1.0.1/objects.mainnet.toml ``` {% endtab %} @@ -185,4 +185,3 @@ Note that this coin can only be used to pay for Nexus and tool invocation fees o --- After completing these steps, you are ready to build and execute workflows using the Nexus SDK. To build your first workflow, check the [Dev Quickstart guide](math-branching-quickstart.md). - diff --git a/nexus-sdk/guides/tool-communication.md b/nexus-sdk/guides/tool-communication.md index eb61bc8..a3e6678 100644 --- a/nexus-sdk/guides/tool-communication.md +++ b/nexus-sdk/guides/tool-communication.md @@ -19,6 +19,7 @@ It is written for: - Leader node → Tool requests carry `X-Nexus-Sig-*` headers that authenticate the calling Leader node, bind the request metadata, and bind the request body bytes. - Tool → Leader node responses also carry `X-Nexus-Sig-*` headers so the Leader node can verify provenance and bind the response to the exact request. 1. **Tools should not do on-chain reads at runtime** to validate Leader nodes. Instead, the Tool operator exports a local allowlist file of permitted Leader nodes and deploys it next to the Tool. +1. **DAGs that require on-chain registered-key verification** set `leader_verifier.mode = "leader_registered_key"` and `method = "signed_http_v1"`. In that mode, the leader builds workflow proof from the signed HTTP transcript, so the Tool must have an active registered key and must sign the exact `/invoke` response body. {% hint style="info" %} Terminology: a **Leader node** is the Nexus node calling the Tool. In signed HTTP claims, `leader_id` identifies the Leader node (a Sui like `address`) that signed the request. @@ -168,6 +169,33 @@ Each identity has: Registration uses a **proof-of-possession** (PoP) signature so the chain can verify the registrant actually controls the private key corresponding to the public key being registered. +## On-chain registered-key verification + +Signed HTTP is the transport/session contract. The DAG can require that same signed session to be proven on chain by using registered-key verifier policy: + +```json +{ + "leader_verifier": { + "mode": "leader_registered_key", + "method": "signed_http_v1" + } +} +``` + +This policy is configured as a `leader_verifier`, not a `tool_verifier`. A `tool_verifier` with `mode = "tool_verifier_contract"` is for a custom verifier package registered in the verifier registry. + +When `leader_registered_key` is active for a vertex, the leader submits a verifier-aware workflow transaction with proof derived from the signed HTTP request and response. Missing or invalid proof is handled as a verifier failure and routed through `_err_eval`; the no-verifier route is only valid when the effective policy is `None`. + +For the Tool, this means: + +- register the Tool message-signing public key on chain with `nexus tool auth register-key`; +- configure the runtime with the returned `tool_kid` and matching private signing key; +- keep `allowed_leaders.json` synced so the Tool verifies incoming Leader requests locally; +- ensure the reverse proxy preserves all `X-Nexus-Sig-*` headers and does not rewrite bodies; +- sign the exact response body sent to the Leader, including `_err_eval` bodies. + +If you implement a custom runtime instead of using `nexus-toolkit`, use the body-aware signed HTTP response signer. Status-only response signing is deprecated because a 2xx HTTP response can still carry an `_err_eval` outcome in the body. + --- ## How to deploy a Tool (end-to-end checklist) @@ -264,6 +292,8 @@ Notes: This creates (or updates) the Tool’s key binding in `network_auth` and returns the `tool_kid` you must configure in the Tool runtime. +If an Agent developer configures `leader_verifier.mode = "leader_registered_key"` with method `signed_http_v1`, this registered key is also the key used by the workflow proof path. A stale `tool_kid`, inactive key, body-rewriting proxy, or unsigned response will prevent the leader from producing valid registered-key proof. + ### 6) Export `allowed_leaders.json` for Tool-side verification Tools should not RPC to Sui on every request. Instead, generate a local allowlist file of permitted Leader nodes: @@ -321,6 +351,21 @@ export NEXUS_TOOLKIT_CONFIG_PATH=./toolkit.json If you run multiple tools on the same server, add each tool id under `signed_http.tools` with its own signing key and `tool_kid`. {% endhint %} +### 8) Configure DAG verification when you want on-chain proof + +Add the registered-key leader verifier to the DAG or to the specific vertex that requires proof: + +```json +{ + "leader_verifier": { + "mode": "leader_registered_key", + "method": "signed_http_v1" + } +} +``` + +Use DAG-level configuration when every off-chain vertex should require the same proof policy. Use vertex-level configuration when only selected tool calls need the registered-key requirement. + --- ## Optional: additional Tool-side authorization @@ -353,6 +398,15 @@ Common causes: - Tool key is not registered (or not the active key) on-chain. - Tool response body is being modified by middleware. +### Registered-key verifier proof fails + +Common causes: + +- DAG or vertex uses `leader_verifier.mode = "leader_registered_key"` but the Tool response is unsigned. +- The Tool signed with a stale `tool_kid` or a key that is not active in Network Auth. +- Middleware changed the response body after signing. +- Custom runtime used status-only response signing instead of body-aware response signing. + ### TLS / certificate errors from Leader nodes Common causes: @@ -360,4 +414,3 @@ Common causes: - Certificate is self-signed or missing intermediate chain. - Certificate hostname does not match the Tool URL. - Leader node environment does not include the required root CA (custom CA deployments). - diff --git a/nexus-sdk/guides/tool-firewall.md b/nexus-sdk/guides/tool-firewall.md index c80b5f6..a4c0b53 100644 --- a/nexus-sdk/guides/tool-firewall.md +++ b/nexus-sdk/guides/tool-firewall.md @@ -83,4 +83,3 @@ You should see entries indicating that connections from the specified IP address --- By following this guide, your Tool will be configured to accept connections only from the specified Leader nodes, enhancing security as defense-in-depth. - diff --git a/nexus-sdk/index.md b/nexus-sdk/index.md index f21f28b..3bbf973 100644 --- a/nexus-sdk/index.md +++ b/nexus-sdk/index.md @@ -29,6 +29,7 @@ Docs: - [Nexus CLI](cli.md) - [DAG Construction Guide](guides/dag-construction.md) +- [TAP Development Guide](guides/1-tap-development.md) - [Nexus Client (Rust)](client.md) ## Toolkit @@ -42,4 +43,3 @@ Docs: - [Tool Development Guidelines](tool-development.md) - [Nexus Toolkit Rust](toolkit-rust.md) - [Tool Communication (HTTPS + Signed HTTP)](guides/tool-communication.md) - diff --git a/nexus-sdk/tool-development.md b/nexus-sdk/tool-development.md index 8899f98..b49b0ab 100644 --- a/nexus-sdk/tool-development.md +++ b/nexus-sdk/tool-development.md @@ -95,4 +95,3 @@ Tool developers should design with these constraints in mind: For a detailed guide (TLS termination options, key registration, runtime config, and troubleshooting), see: - [Tool Communication (HTTPS + Signed HTTP)](guides/tool-communication.md) - diff --git a/nexus-sdk/toolkit-rust.md b/nexus-sdk/toolkit-rust.md index bd9d840..6178e27 100644 --- a/nexus-sdk/toolkit-rust.md +++ b/nexus-sdk/toolkit-rust.md @@ -1,6 +1,6 @@ # Nexus Toolkit for Rust -> concerns [`nexus-toolkit-rust` repo](https://github.com/Talus-Network/nexus-sdk/tree/main/toolkit-rust) +> concerns [`nexus-toolkit-rust` repo][nexus-toolkit-rust-repo] This library exports useful functionality to streamline the development of Nexus Tools in Rust. It is mainly used by **Tool developers** to bootstrap their efforts to extend the Nexus ecosystem. @@ -8,14 +8,14 @@ This documentation will go over the main features of the library and how to use ## Installation -Using the [CLI](./cli.md) run the `$ nexus tool new --help` command to see the available options. This command creates a fresh Rust project with the necessary dependencies to get started. +Using the [CLI][nexus-cli-docs] run the `$ nexus tool new --help` command to see the available options. This command creates a fresh Rust project with the necessary dependencies to get started. Alternatively, you can add the following to your `Cargo.toml` file: ```toml [dependencies.nexus-toolkit] git = "https://github.com/Talus-Network/nexus-sdk" -tag = "v1.0.0" +tag = "v2.0.0-rc.2" package = "nexus-toolkit" ``` @@ -83,7 +83,7 @@ This associated type defines the output that the Tool produces. This type must d The Tool's output schema is then derived from this type via the `schemars::schema_for!` macro. -To comply with [Nexus Workflow output variants](../nexus-next/packages/workflow.md), the output schema **must include a top-level `oneOf`**. This is also enforced by the Tool's runtime and achievable in Rust simply by using an `enum`. +To comply with [Nexus Workflow output variants][nexus-next-workflow-docs], the output schema **must include a top-level `oneOf`**. This is also enforced by the Tool's runtime and achievable in Rust simply by using an `enum`. ```rs use nexus_toolkit::*; @@ -106,7 +106,7 @@ impl NexusTool for HttpStatus { #### `NexusTool::fqn` -Defines the Tool's fully qualified name. This is used to uniquely identify the Tool in the Nexus ecosystem. Read more about FQNs in the [Nexus Tool documentation](../nexus-next/tool.md). +Defines the Tool's fully qualified name. This is used to uniquely identify the Tool in the Nexus ecosystem. Read more about FQNs in the [Nexus Tool documentation][nexus-next-tool-docs]. ```rs use nexus_toolkit::*; @@ -204,7 +204,7 @@ If signed HTTP is disabled, `authorize` is not invoked. ### `nexus_toolkit::bootstrap!` The `bootstrap!` macro hides away the boilerplate code needed to create the -underlying HTTP server that adheres to the [Nexus Tool interface](../nexus-next/tool.md). +underlying HTTP server that adheres to the [Nexus Tool interface][nexus-next-tool-docs]. It has a flexible interface that accepts an `Into` value and a struct that `impl NexusTool`. @@ -280,3 +280,9 @@ For a full end-to-end setup guide (TLS termination options + key registration + - [Tool Communication (HTTPS + Signed HTTP)](guides/tool-communication.md) + + +[nexus-toolkit-rust-repo]: https://github.com/Talus-Network/nexus-sdk/tree/main/toolkit-rust +[nexus-next-tool-docs]: ../nexus-next/tool.md +[nexus-next-workflow-docs]: ../nexus-next/packages/workflow.md +[nexus-cli-docs]: ./cli.md From b6ca693bac116a76a621524477e3a6e0483253e3 Mon Sep 17 00:00:00 2001 From: devops-talus Date: Wed, 24 Jun 2026 11:23:31 +0000 Subject: [PATCH 2/2] Update SUMMARY.md with new files under 'Looking for a home' --- SUMMARY.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SUMMARY.md b/SUMMARY.md index 8ddb564..54e78a9 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -113,3 +113,9 @@ ## Looking for a home * [vision/talus-vision/explorer.md](vision/talus-vision/explorer.md) +* [nexus-sdk/guides/1-tap-development.md](nexus-sdk/guides/1-tap-development.md) +* [nexus-sdk/guides/2-tap-scaffold-and-package.md](nexus-sdk/guides/2-tap-scaffold-and-package.md) +* [nexus-sdk/guides/3-tap-transfer-tool.md](nexus-sdk/guides/3-tap-transfer-tool.md) +* [nexus-sdk/guides/4-tap-dag-and-skill-config.md](nexus-sdk/guides/4-tap-dag-and-skill-config.md) +* [nexus-sdk/guides/5-tap-publish-and-register.md](nexus-sdk/guides/5-tap-publish-and-register.md) +* [nexus-sdk/guides/6-tap-execute-and-settle.md](nexus-sdk/guides/6-tap-execute-and-settle.md)