> For the complete documentation index, see [llms.txt](https://docs.talus.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.talus.network/talus-docs-v2.1.0/guides/tap-development/publish-register-bind.md).

# Publish, Register, Bind

{% hint style="info" %}
**Audience:** Nexus adopters and integrators.

**Goal:** Publish a Talus Agent Package (TAP), register its durable Tool and skill artifacts, and verify the Agent binding before execution.
{% endhint %}

Five on-chain boundaries make up this page:

1. `sui client publish` publishes the Talus Agent Package (TAP) Move package and creates `TutorialState`.
2. `nexus tool register onchain` adds the transfer Tool to `ToolRegistry`.
3. `nexus dag publish` publishes the DAG after its Tool FQN can be resolved.
4. `nexus tap create-skill-artifact` derives the input commitment and writes `artifact.json`.
5. `nexus tap bind` creates a Talus Agent and registers its first skill atomically.

Each step records what the next one needs. Capture the IDs as you go. A fresh on-chain Tool cannot use the one-command `nexus tap publish-skill` path because Tool registration needs the package ID while DAG publication needs the registered Tool; the explicit sequence below breaks that dependency cycle.

### 1. Publish the Move package

Build and test once more, then publish from the directory that contains `Move.toml`:

```bash
export SUI_BUILD_ENV="testnet"
(
  set -e
  cd tap
  sui move build --build-env "$SUI_BUILD_ENV"
  nexus tap test --path ../move-tests-published --build-env "$SUI_BUILD_ENV"
  sui client publish . --build-env "$SUI_BUILD_ENV" --json > ../publish-package.json
)
```

The released published-bytecode test runs before `sui client publish` in the same fail-fast block. It exercises the selected public Nexus bytecode in a read-only local VM and does not publish or register anything. Keep its output with the package-owned Move tests; the explicit test packages and their plain-Move boundary are described in [Build the TAP Move package](/talus-docs-v2.1.0/guides/tap-development/build-tap-move-package.md). A green result does not replace the publication, Tool registration, DAG publication, skill binding, or later Testnet execution checks.

The publication transaction creates the immutable package and runs its `init` function, which shares one `TutorialState`. Save both IDs from `objectChanges`; the exact values are network-specific:

```bash
PKG=$(jq -r '[.objectChanges[]? | select(.type == "published") | .packageId] | unique | .[0]' publish-package.json)
STATE=$(jq -r --arg pkg "$PKG" '
  [.objectChanges[]?
   | select(.type == "created")
   | select((.objectType? // "") | startswith($pkg + "::tutorial_transfer::TutorialState"))
   | .objectId][0]
' publish-package.json)

echo "PKG=$PKG STATE=$STATE"
```

Require both values to be nonempty before continuing. Keep `publish-package.json`; it is the durable link between the package, state, and transaction.

#### 2. Find the freshly published `TutorialState` and witness IDs

`TutorialState` is shared, so inspect it by ID rather than looking only at address-owned objects:

```bash
sui client object "$STATE" --json > tutorial-state.json
jq '.content' tutorial-state.json
```

The decoded content includes the `transfer_vertex_witness` created by `init`. Its nested UID is the Tool requirement identity, not the shared `TutorialState` ID. A parent-object read is useful context, but the public CLI does not provide a generic package-specific proof of that nested UID.

```bash
export WITNESS_DECODER="./operator-supplied/decode-tutorial-transfer-witness"
export WITNESS_DECODER_SOURCE="<reviewed source URL or commit>"
export WITNESS_DECODER_SHA256="<64-hex SHA-256 for the reviewed artifact>"
test -x "$WITNESS_DECODER"
test -n "$WITNESS_DECODER_SOURCE"
test "${#WITNESS_DECODER_SHA256}" = 64
printf '%s  %s\n' "$WITNESS_DECODER_SHA256" "$WITNESS_DECODER" | sha256sum -c -
"$WITNESS_DECODER" "$STATE" > witness-proof.json
jq -e --arg state "$STATE" --arg type "${PKG}::tutorial_transfer::TransferVertexWitness" '
  .state_id == $state
  and .field_key == "transfer_vertex_witness"
  and .witness_type == $type
  and .witness_uid_field == "id"
  and (.witness_id | type == "string" and test("^0x[0-9a-fA-F]+$"))
  and .proof == "TutorialState field UID"
' witness-proof.json
export WITNESS="$(jq -er '.witness_id' witness-proof.json)"
echo "STATE=$STATE WITNESS=$WITNESS"
```

The named `operator-supplied/decode-tutorial-transfer-witness` artifact must read the published `TutorialState`, prove the exact `${PKG}::tutorial_transfer::TransferVertexWitness` type and its `id: UID` field, and emit the checked JSON fields above. Record the source/checksum with the deployment evidence. Stop if the artifact or exact type/UID proof is unavailable; never substitute `STATE` for `WITNESS`.

#### 3. Register the on-chain transfer Tool

The SUI faucet funds owned `Coin<SUI>` objects, not the signer's SUI address balance. Select an owned gas coin from `sui client gas` with at least 500,000,000 MIST for the transaction budget below, then set `NEXUS_GAS_COIN` to its object ID. Recheck its remaining balance before each later Nexus transaction and select another funded coin if necessary. Registration, DAG publication, and Agent binding below explicitly use this coin; omitting `--sui-gas-coin` would require a separately funded address balance.

```bash
sui client gas
export NEXUS_GAS_COIN="<owned-sui-coin-object-id>"
```

```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-coin "$NEXUS_GAS_COIN" --sui-gas-budget 500000000 \
  --json > tool-register.json
```

A few things worth knowing:

* **`--package` and `--module`** must identify the published module that contains `public fun execute`. The CLI derives the input mode/schema from `execute` and the output schema from `Output`.
* **`--tool-fqn`** must equal the FQN in the Move helper and `dag.json`. Nexus CLI FQNs use dotted `domain.name@version` syntax.
* **`--tool-witness-id`** ties the Tool record to `TransferVertexWitness`; runtime execution satisfies that exact witness through `UIDRequirements`.
* **Owner and cashier capabilities** are returned in the JSON and saved to local Tool configuration unless `--no-save` is used. Preserve their custody; they authorize later Tool administration and ToolCashier operations.

Confirm the live record before publishing the DAG:

```bash
nexus tool inspect --tool-fqn tutorial.local.transfer_vertex@1 --json > tool-inspect.json
jq '{tool_id, tool_cashier_id, reference: .tool.reference, meta_schema: .tool.meta_schema}' tool-inspect.json
```

This tutorial uses the standard on-chain mode: `execute` starts with `UIDRequirements` and `OnchainToolResult` and has no package-specific external caller check. That is why the guide uses disposable assets.

#### 4. Publish the DAG, create the artifact, and bind the Agent

Now that the FQN resolves to a registered Tool and immutable schema, publish the DAG:

```bash
nexus dag publish --path dag.json --sui-gas-coin "$NEXUS_GAS_COIN" --sui-gas-budget 500000000 --json > dag-publish.json
DAG=$(jq -r '.dag_id' dag-publish.json)
nexus dag inspect --dag-id "$DAG" --json
```

Create the skill artifact from the published DAG. The CLI fetches the DAG's actual entry ports and derives `requirements.input_commitment`; it does not trust the placeholder in the local scaffold config:

```bash
nexus tap create-skill-artifact \
  --skill-name "tutorial transfer" \
  --dag-id "$DAG" \
  --interface-revision 1 \
  --payment-mode user-funded \
  --recurrence-kind once \
  --out artifact.json \
  --json
```

`nexus tap bind` creates a new Agent and registers its first skill in one transaction:

```bash
nexus tap bind \
  --artifact artifact.json \
  --sui-gas-coin "$NEXUS_GAS_COIN" --sui-gas-budget 500000000 \
  --json > bind.json

AGENT=$(jq -r '.agent_id' bind.json)
SKILL=$(jq -r '.skill_id' bind.json)
echo "AGENT=$AGENT SKILL=$SKILL DAG=$DAG"
```

`tap bind` always creates a new Agent. If you already have an Agent, use `nexus tap register-skill --agent-id <existing> --artifact artifact.json` instead. Later DAG or requirement changes use a new artifact plus `nexus tap update-skill`; a compatible package-pointer migration alone does not require a new skill revision when the DAG and requirements stay unchanged.

#### 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)]
}'

nexus tap requirements --agent-id "$AGENT" --skill-id "$SKILL" --json
```

You should see one Agent entry and one skill entry with interface revision `1`, a pinned DAG binding matching `$DAG`, `UserFunded` payment, `Once` scheduling, and an empty fixed-Tool list. `nexus tap default-agent show` is unaffected; that is the registry-managed default Agent, not the object created here.

#### What you have now

* A published TAP Move package and shared `TutorialState`, recorded in `publish-package.json`.
* A registered on-chain Tool with stable Tool/owner/ToolCashier identities and an immutable schema.
* A published one-vertex DAG and reusable `artifact.json` derived from its entry inputs.
* A new Agent with one skill pinned to that DAG.

The treasury inside `TutorialState` is still empty. The next page funds it, creates a Task, follows its Occurrence and Execution, and settles the result.

Next: [Execute and verify the transfer](/talus-docs-v2.1.0/guides/tap-development/execute-and-verify-transfer.md).


---

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

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

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

```
GET https://docs.talus.network/talus-docs-v2.1.0/guides/tap-development/publish-register-bind.md?ask=<question>&goal=<user_goal>
```

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

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

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