diff --git a/docs/snippets/go-hash-tool-readme.md.mdx b/docs/snippets/go-hash-tool-readme.md.mdx
index 2331c674f..82162c710 100644
--- a/docs/snippets/go-hash-tool-readme.md.mdx
+++ b/docs/snippets/go-hash-tool-readme.md.mdx
@@ -10,9 +10,9 @@ To clone this repo and follow along, run the following command:
git clone git@github.com:otto8-ai/go-hash-tool
```
----
+
-### Tool Repo Structure
+## Tool Repo Structure
The directory tree below highlights the files required to implement `Hash` in Go and package it for `Otto8`.
@@ -25,11 +25,12 @@ go-hash-tool
└── hash.go
```
-**Note:** Most Tools implemented in Go will also have a `go.sum` file that is also required when present. It is not present in the reference implementation because it has no external dependencies and relies solely on the Go standard library.
+> **Note:** Most Tools implemented in Go will also have a `go.sum` file that is also required when present.
+> It is not present in the reference implementation because it has no external dependencies and relies solely on the Go standard library.
----
+
-### Defining the `Hash` Tool
+## Defining the `Hash` Tool
The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that can be used by Agents in `Otto8`.
Every Tool repository must have a `tool.gpt` file in its root directory.
@@ -41,7 +42,7 @@ We call the section of a Tool definition that contains this info a `Preamble`.
We want the `Hash` Tool to return the hash of some given `data`. It would also be nice to support a few different algorithms for the Agent to choose from.
Let's take a look at the `Preamble` for `Hash` to see how that's achieved:
-```text
+```yaml
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
Param: data: The data to hash
@@ -55,9 +56,11 @@ Breaking this down a bit:
- In this case, the description of the `algo` parameter outlines the valid options (`sha256` or `md5`) and defines a default value (`sha256`)
- The `Description` explains what `Hash` returns with respect to the given arguments; the hash of `data` using the algorithm selected with `algo`.
+
+
Immediately below the `Preamble` is the `Tool Body`, which tells `Otto8` how to execute the Tool:
-```text
+```bash
#!{GPTSCRIPT_TOOL_DIR}/bin/gptscript-go-tool hash
```
@@ -71,9 +74,11 @@ To oversimplify, when an Agent calls the `Hash` Tool, `Otto8` reads this line an
4. Projects the call arguments onto environment variables (`DATA` and `ALGO`)
5. Runs `gptscript-go-tool hash`.
+
+
Putting it all together, here's the complete definition of the `Hash` Tool:
-```text
+```yaml
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
Param: data: The data to hash
@@ -82,16 +87,20 @@ Param: algo: The algorithm to generate a hash with. Default is "sha256". Support
#!{GPTSCRIPT_TOOL_DIR}/bin/gptscript-go-tool hash
```
-### Tool Metadata
+
+
+## Tool Metadata
The `tool.gpt` file also provides the following metadata for use in `Otto8`:
- `!metadata:*:category` which tags Tools with the `Crypto` category to promote organization and discovery
- `!metadata:*:icon` which assigns `https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg` as the Tool icon
-Where `*` is a wild card pattern that applies the metadata to all Tools in a `tool.gpt`.
+
+
+> **Note:** `*` is a wild card pattern that applies the metadata to all Tools in the `tool.gpt` file.
-```text
+```yaml
---
!metadata:*:category
Crypto
@@ -101,17 +110,25 @@ Crypto
https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
-**Note:** Metadata can be applied to a specific Tool by either specifying the exact name (e.g. `!metadata:Hash:category`) or by adding the metadata directly to a Tool's `Preamble`:
+
+
+ Note: Metadata can be applied to a specific Tool by either specifying the exact name (e.g. !metadata:Hash:category
) or by adding the metadata directly to a Tool's Preamble
+
-```text
+```yaml
Name: Hash
Metadata: category: Crypto
Metadata: icon: https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
-### Complete `tool.gpt`
+
+
+
+
+
+ Complete tool.gpt
-```text
+```yaml
---
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
@@ -129,45 +146,52 @@ Crypto
https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
----
+
+
+
-### Implementing Business Logic
+## Implementing Business Logic
The `main.go` file is the entry point of the `gptscript-go-tool` binary that is executed by `Otto8` when the `Hash` Tool is called.
Let's walk through the the code to understand what happens at runtime:
```go
- // ...
- switch cmd := os.Args[1]; cmd {
- case "hash":
- res, err = commands.Hash(os.Getenv("DATA"), os.Getenv("ALGO"))
- default:
- err = fmt.Errorf("Unsupported command: %s", cmd)
- }
+// ...
+switch cmd := os.Args[0]; cmd {
+case "hash":
+ res, err = commands.Hash(os.Getenv("DATA"), os.Getenv("ALGO"))
+default:
+ err = fmt.Errorf("Unsupported command: %s", cmd)
+}
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
+if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+}
- if res != "" {
- fmt.Println(res)
- }
+if res != "" {
+ fmt.Println(res)
+}
```
This code implements a simple CLI responsible for dispatching the `commands.Hash` function on request -- when `hash` is passed in as an argument -- after extracting the Tool arguments, `data` and `algo`, from the respective environment variables.
It also ensures that the return value and errors of the call to `commands.Hash` are written to stdout. This is crucial because only stdout is returned to the Agent, while stderr is discarded.
-The simple CLI pattern showcased above is also easily extensible; adding business logic for new tools becomes a matter of adding a new case to the `switch` statement.
+
+
+ Note: The simple CLI pattern showcased above is also easily extensible; adding business logic for new tools becomes a matter of adding a new case to the switch
statement.
+
+
+
For example, to add business logic for a new Tool to verify a hash, we just have to tack on `verify` case:
```go
// ...
case "verify":
- res, err = commands.Verify(os.Getenv("HASH"), os.Getenv("DATA"), os.Getenv("ALGO"))
+ res, err = commands.Verify(os.Getenv("HASH"), os.Getenv("DATA"), os.Getenv("ALGO"))
case "hash":
// ...
default:
@@ -176,47 +200,51 @@ default:
The Body of the `Verify` Tool definition would then simply pass `verify` to `gptscript-go-tool` instead of `hash`:
-```text
+```yaml
Name: Verify
# ...
#!{GPTSCRIPT_TOOL_DIR}/bin/gptscript-go-tool verify
```
-Getting back to the business logic for the `Hash` Tool, `commands.Hash` is does the bulk of the heavy lifting.
+
+
+
+
+The `commands.Hash` function implements the bulk of the `Hash` Tool's business logic.
+
+It starts off by validating the `data` and `algo` arguments.
+
```go
func Hash(data, algo string) (string, error) {
- if data == "" {
- return "", fmt.Errorf("A non-empty data argument must be provided")
- }
+ if data == "" {
+ return "", fmt.Errorf("A non-empty data argument must be provided")
+ }
- if algo == "" {
- algo = "sha256"
- }
+ if algo == "" {
+ algo = "sha256"
+ }
- // ...
-}
+ sum, ok := hashFunctions[algo]
+ if !ok {
+ return "", fmt.Errorf("Unsupported hash algorithm: %s not in [%s]", algo, hashFunctions)
+ }
+ // ...
```
-It starts off by validating the `data` and `algo` arguments.
-When an argument is invalid, the function throws an exception that describes the validation issue in detail.
+When an argument is invalid, the function returns an error that describes the validation issue in detail.
The goal is to provide useful information that an Agent can use to construct valid arguments for future calls.
For example, when an invalid `algo` argument is provided, the code returns an error that contains the complete list of valid algorithms.
+
+
Once it determines that all of the arguments are valid, it then calculates the hash and writes a JSON object to stdout.
This object contains both the hash and the algorithm used to generate it.
```go
-func Hash(data, algo string) (string, error) {
// ...
-
- sum, ok := hashFunctions[algo]
- if !ok {
- return "", fmt.Errorf("Unsupported hash algorithm: %s not in [%s]", algo, hashFunctions)
- }
-
- hash, err := json.Marshal(hashResult{
+ hash, err := json.Marshal(hashResult{
Algo: algo,
Hash: hex.EncodeToString(sum([]byte(data))),
})
@@ -228,10 +256,11 @@ func Hash(data, algo string) (string, error) {
}
```
-Producing structured data with extra contextual info (e.g. the algorithm) is considered good form.
-It's a pattern that improves the Agent's ability to correctly use the Tool's result over time.
+> **Note:** Producing structured data with extra contextual info (e.g. the algorithm) is considered good form.
+> It's a pattern that improves the Agent's ability to correctly use the Tool's result over time.
-### Complete `main.go` and `commands/hash.go`
+
+ Complete main.go
and hash.go
```go
// main.go
@@ -241,7 +270,7 @@ import (
"fmt"
"os"
- "github.com/njhale/go-hash-tool/commands"
+ "github.com/otto8-ai/go-hash-tool/commands"
)
func main() {
@@ -277,8 +306,8 @@ func main() {
package commands
import (
- "hash/md5"
- "hash/sha256"
+ "crypto/md5"
+ "crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
@@ -336,10 +365,13 @@ func keys[V any](m map[string]V) []string {
sort.Strings(set)
return set
}
+```
----
+
-### Testing `main.go` Locally
+
+
+## Testing `main.go` Locally
Before adding a Tool to `Otto8`, verify that the Go business logic works on your machine.
@@ -353,43 +385,77 @@ To do this, run through the following steps in the root of your local fork:
2. Run the Tool with some test arguments:
- | **Command** |**Output** |
- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
- | `DATA='foo' bin/gptscript-go-tool hash` | `{ "algo": "sha256", "hash": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" }` |
- | `DATA='' bin/gptscript-go-tool hash` | `Error: A data argument must be provided` |
- | `DATA='foo' ALGO='md5' bin/gptscript-go-tool hash` | `{ "algo": "md5", "hash": "acbd18db4cc2f85cedef654fccc4a4d8" }` |
+ | **Command** | **Output** |
+ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
+ | `DATA='foo' bin/gptscript-go-tool hash` | `{ "algo": "sha256", "hash": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" }` |
+ | `DATA='' bin/gptscript-go-tool hash` | `Error: A data argument must be provided` |
+ | `DATA='foo' ALGO='md5' bin/gptscript-go-tool hash` | `{ "algo": "md5", "hash": "acbd18db4cc2f85cedef654fccc4a4d8" }` |
| `DATA='foo' ALGO='whirlpool' bin/gptscript-go-tool hash` | `Error: Unsupported hash algorithm: whirlpool not in ['sha256', 'md5']` |
----
+
-### Adding The `Hash` Tool to `Otto8`
+## Adding The `Hash` Tool to `Otto8`
Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto8` by performing the steps below:
-1. Navigate to the `Otto8` admin UI in a browser and open the Tools page by clicking the "Tools" button in the left drawer
- ![Open The Tools Page](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/add-tools-step-0.png "Open The Tools Page")
-
-2. Click the "Register New Tool" button on the right
- ![Click The Register New Tool Button](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/add-tools-step-1.png "Click The Register New Tool Button")
-
-3. Type the Tool repo reference into the modal's input box -- in this example `github.com/otto8-ai/go-hash-tool` -- and click "Register Tool"
- ![Enter Tool Repo Reference](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/add-tools-step-2.png "Enter Tool Repo Reference")
-
-Afterwords, the Tool will be available for use in `Otto8`.
-
-You can search for the Tool by category or name on the Tools page to verify:
-
-![Search For Newly Added Tools](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/add-tools-step-3.png "Search For Newly Added Tools")
-
-### Using The `Hash` Tool in an Agent
+1.
+ Navigate to the Otto8
admin UI in a browser and open the Tools page by clicking the Tools button in the left drawer
+
+
+
+
+
+2.
+ Click the Register New Tool button on the right
+
+
+
+
+
+3.
+ Type the Tool repo reference into the modal's input box and click Register Tool
+
+
+
+
+
+
+
+
+ Once the tool has been added, you can search for it by category or name on the Tools page to verify
+
+
+
+
+
+## Using The `Hash` Tool in an Agent
To use the `Hash` Tool in an Agent, open the Agent's Edit page, then:
-1. Click the "Add Tool" button under either the "Agent Tools" or "User Tools" sections
- ![Click The Add Tool Button](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/use-tools-step-0.png "Click The Add Tool Button")
-
-2. Search for "Hash" or "Crypto" in the Tool search pop-out and select the `Hash` Tool
- ![Add Hash Tool To Agent](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/use-tools-step-1.png "Add Hash Tool To Agent")
-
-3. Ask the Agent to generate a hash
- ![Ask The Agent To Generate a Hash](https://raw.githubusercontent.com/otto8-ai/go-hash-tool/refs/heads/main/docs/use-tools-step-2.png "Ask The Agent To Generate a Hash")
+1.
+ Click the Add Tool button under either the Agent Tools or User Tools sections
+
+
+
+
+
+2.
+ Search for "Hash" or "Crypto" in the Tool search pop-out and select the Hash
Tool
+
+
+
+
+
+3.
+ Ask the Agent to generate a hash
+
+
+
+
diff --git a/docs/snippets/node-hash-tool-readme.md.mdx b/docs/snippets/node-hash-tool-readme.md.mdx
index a7fa8615c..67edceadf 100644
--- a/docs/snippets/node-hash-tool-readme.md.mdx
+++ b/docs/snippets/node-hash-tool-readme.md.mdx
@@ -9,10 +9,9 @@ To clone this repo and follow along, run the following command:
```bash
git clone git@github.com:otto8-ai/node-hash-tool
```
+
----
-
-### Tool Repo Structure
+## Tool Repo Structure
The directory tree below highlights the files required to implement `Hash` in Typescript and package it for `Otto8`.
@@ -27,11 +26,12 @@ node-hash-tool
└── tools.ts
```
-**Note:** The `tsconfig.json` file is only required for tools written in Typescript. It is not necessary for tools written in JavaScript.
+> **Note:** The `tsconfig.json` file is only required for tools written in Typescript.
+> It is not necessary for tools written in JavaScript.
----
+
-### Defining the `Hash` Tool
+## Defining the `Hash` Tool
The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that can be used by Agents in `Otto8`.
Every Tool repository must have a `tool.gpt` file in its root directory.
@@ -43,7 +43,7 @@ We call the section of a Tool definition that contains this info a `Preamble`.
We want the `Hash` Tool to return the hash of some given `data`. It would also be nice to support a few different algorithms for the Agent to choose from.
Let's take a look at the `Preamble` for `Hash` to see how that's achieved:
-```text
+```yaml
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
Param: data: The data to hash
@@ -57,9 +57,11 @@ Breaking this down a bit:
- In this case, the description of the `algo` parameter outlines the valid options (`sha256` or `md5`) and defines a default value (`sha256`)
- The `Description` explains what `Hash` returns with respect to the given arguments; the hash of `data` using the algorithm selected with `algo`.
+
+
Immediately below the `Preamble` is the `Tool Body`, which tells `Otto8` how to execute the Tool:
-```text
+```bash
#!/usr/bin/env npm --silent --prefix ${GPTSCRIPT_TOOL_DIR} run tool -- hash
```
@@ -73,9 +75,11 @@ To oversimplify, when an Agent calls the `Hash` Tool, `Otto8` reads this line an
4. Projects the call arguments onto environment variables (`DATA` and `ALGO`)
5. Runs `npm --silent --prefix ${GPTSCRIPT_TOOL_DIR} run tool -- hash`.
+
+
Putting it all together, here's the complete definition of the `Hash` Tool.
-```text
+```yaml
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
Param: data: The data to hash
@@ -84,16 +88,20 @@ Param: algo: The algorithm to generate a hash with. Default is "sha256". Support
#!/usr/bin/env npm --silent --prefix ${GPTSCRIPT_TOOL_DIR} run tool -- hash
```
-### Tool Metadata
+
+
+## Tool Metadata
The `tool.gpt` file also provides the following metadata for use in `Otto8`:
- `!metadata:*:category` which tags Tools with the `Crypto` category to promote organization and discovery
- `!metadata:*:icon` which assigns `https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg` as the Tool icon
-Where `*` is a wild card pattern that applies the metadata to all Tools in a `tool.gpt`.
+
-```text
+> **Note:** `*` is a wild card pattern that applies the metadata to all Tools in the `tool.gpt` file.
+
+```yaml
---
!metadata:*:category
Crypto
@@ -103,17 +111,25 @@ Crypto
https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
-**Note:** Metadata can be applied to a specific Tool by either specifying the exact name (e.g. `!metadata:Hash:category`) or by adding the metadata directly to a Tool's `Preamble`:
+
+
+ Note: Metadata can be applied to a specific Tool by either specifying the exact name (e.g. !metadata:Hash:category
) or by adding the metadata directly to a Tool's Preamble
+
-```text
+```yaml
Name: Hash
Metadata: category: Crypto
Metadata: icon: https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
-### Complete `tool.gpt`
+
+
+
+
+
+ Complete tool.gpt
-```text
+```yaml
---
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
@@ -131,9 +147,11 @@ Crypto
https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
----
+
+
+
-### Implementing Business Logic
+## Implementing Business Logic
As we saw earlier, the `npm` command invoked by the `Tool Body` passes `hash` as an argument to the `tool` script.
@@ -141,7 +159,7 @@ As we saw earlier, the `npm` command invoked by the `Tool Body` passes `hash` as
npm --silent --prefix ${GPTSCRIPT_TOOL_DIR} run tool -- hash
```
-To figure out what this resolves to, let's inspect the `tool` script defined by `package.json`:
+To figure out what this resolves to, let's inspect the `tool` script defined in `package.json`:
```json
"scripts": {
@@ -155,7 +173,7 @@ This means that when the `Tool Body` is executed, the effective command that run
node --no-warnings --loader ts-node/esm src/tools.ts hash
```
-**Note:** The `--loader ts-node/esm` option, in conjunction with the contents of `tsconfig.json`, is the "special sauce" that lets us run Typescript code directly without transpiling it to JavaScript first.
+> **Note:** The `--loader ts-node/esm` option, in conjunction with the contents of `tsconfig.json`, is the "special sauce" that lets us run Typescript code directly without transpiling it to JavaScript first.
To summarize, when the `Hash` Tool is called by an Agent, `src/tools.ts` gets run with `hash` as an argument.
@@ -181,10 +199,14 @@ try {
}
```
-This code implements a simple CLI that wraps business logic -- e.g. the `hash` function from `src/hash.ts` -- in a try/catch block and forwards any exceptions to stdout.
-Writing errors to stdout instead of stderr is crucial because only stdout is returned to the Agent, while sdterr is discarded.
+This code implements a simple CLI that wraps business logic in a try/catch block and forwards any exceptions to stdout. Writing errors to stdout instead of stderr is crucial because only stdout is returned to the Agent, while sdterr is discarded.
+
+
+
+ Note: The simple CLI pattern showcased above is also easily extensible; adding business logic for new tools becomes a matter of adding a new case to the switch
statement.
+
-The simple CLI pattern showcased above is also easily extensible; adding business logic for new tools becomes a matter of adding a new case to the `switch` statement.
+
For example, if we wanted to add a new Tool to verify a given hash, we'd add a `verify` case:
@@ -202,16 +224,20 @@ switch (cmd) {
And the Body of the `Verify` Tool would pass `verify` to the `tool` script instead of `hash`:
-```text
+```yaml
Name: Verify
# ...
#!/usr/bin/env npm --silent --prefix ${GPTSCRIPT_TOOL_DIR} run tool -- verify
```
-Getting back to the `Hash` Tool, when invoked, the code calls the `hash` function with `data` and `algo` arguments extracted from the respective environment variables.
+
-The `hash` function is where the bulk of the `Hash` Tool's business logic is implemented.
+
+
+When `"hash"` is passed as an argument, the code extracts the `data` and `algo` Tool arguments from the respective environment variables, then passes them to the `hash` function.
+
+The `hash` function is where the bulk of the business logic is implemented.
```typescript
import { createHash } from 'node:hash';
@@ -250,10 +276,13 @@ This object contains the hash and the algorithm used to generate it.
});
```
-Producing structured data with extra contextual info (e.g. the algorithm) is considered good form.
-It's a pattern that improves the Agent's ability to correctly use the Tool's result over time.
+> **Note:** Producing structured data with extra contextual info (e.g. the algorithm) is considered good form.
+> It's a pattern that improves the Agent's ability to correctly use the Tool's result over time.
-### Complete `package.json`, `src/tools.ts`, and `src/hash.ts`
+
+
+ Complete package.json
, src/tools.ts
, and src/hash.ts
+
```json
{
@@ -318,10 +347,11 @@ export function hash(data: string = '', algo = 'sha256'): string {
});
}
```
+
----
+
-### Testing `src/tools.ts` and `src/hash.ts` Locally
+## Testing `src/tools.ts` and `src/hash.ts` Locally
Before adding a Tool to `Otto8`, verify that the Typescript business logic works on your machine.
@@ -342,36 +372,70 @@ To do this, run through the following steps in the root of your local fork:
| `DATA='foo' ALGO='md5' npm run tool hash` | `{ "algo": "md5", "hash": "acbd18db4cc2f85cedef654fccc4a4d8" }` |
| `DATA='foo' ALGO='whirlpool' npm run tool hash` | `Error: Unsupported hash algorithm: whirlpool not in ['sha256', 'md5']` |
----
+
-### Adding The `Hash` Tool to `Otto8`
+## Adding The `Hash` Tool to `Otto8`
Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto8` by performing the steps below:
-1. Navigate to the `Otto8` admin UI in a browser and open the Tools page by clicking the "Tools" button in the left drawer
- ![Open The Tools Page](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/add-tools-step-0.png "Open The Tools Page")
-
-2. Click the "Register New Tool" button on the right
- ![Click The Register New Tool Button](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/add-tools-step-1.png "Click The Register New Tool Button")
-
-3. Type the Tool repo reference into the modal's input box -- in this example `github.com/otto8-ai/node-hash-tool` -- and click "Register Tool"
- ![Enter Tool Repo Reference](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/add-tools-step-2.png "Enter Tool Repo Reference")
-
-Afterwords, the Tool will be available for use in `Otto8`.
-
-You can search for the Tool by category or name on the Tools page to verify:
-
-![Search For Newly Added Tools](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/add-tools-step-3.png "Search For Newly Added Tools")
-
-### Using The `Hash` Tool in an Agent
+1.
+ Navigate to the Otto8
admin UI in a browser and open the Tools page by clicking the Tools button in the left drawer
+
+
+
+
+
+2.
+ Click the Register New Tool button on the right
+
+
+
+
+
+3.
+ Type the Tool repo reference into the modal's input box and click Register Tool
+
+
+
+
+
+
+
+
+ Once the tool has been added, you can search for it by category or name on the Tools page to verify
+
+
+
+
+
+## Using The `Hash` Tool in an Agent
To use the `Hash` Tool in an Agent, open the Agent's Edit page, then:
-1. Click the "Add Tool" button under either the "Agent Tools" or "User Tools" sections
- ![Click The Add Tool Button](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/use-tools-step-0.png "Click The Add Tool Button")
-
-2. Search for "Hash" or "Crypto" in the Tool search pop-out and select the `Hash` Tool
- ![Add Hash Tool To Agent](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/use-tools-step-1.png "Add Hash Tool To Agent")
-
-3. Ask the Agent to generate a hash
- ![Ask The Agent To Generate a Hash](https://raw.githubusercontent.com/otto8-ai/node-hash-tool/refs/heads/main/docs/use-tools-step-2.png "Ask The Agent To Generate a Hash")
+1.
+ Click the Add Tool button under either the Agent Tools or User Tools sections
+
+
+
+
+
+2.
+ Search for "Hash" or "Crypto" in the Tool search pop-out and select the Hash
Tool
+
+
+
+
+
+3.
+ Ask the Agent to generate a hash
+
+
+
+
diff --git a/docs/snippets/python-hash-tool-readme.md.mdx b/docs/snippets/python-hash-tool-readme.md.mdx
index b950a112d..53b2b979b 100644
--- a/docs/snippets/python-hash-tool-readme.md.mdx
+++ b/docs/snippets/python-hash-tool-readme.md.mdx
@@ -10,9 +10,9 @@ To clone this repo and follow along, run the following command:
git clone git@github.com:otto8-ai/python-hash-tool
```
----
+
-### Tool Repo Structure
+## Tool Repo Structure
The directory tree below highlights the files required to implement `Hash` in Python and package it for `Otto8`.
@@ -22,22 +22,21 @@ python-hash-tool
├── requirements.txt
└── tool.gpt
```
+
----
-
-### Defining the `Hash` Tool
+## Defining the `Hash` Tool
-The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that
-can be used by Agents in `Otto8`.
+The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that can be used by Agents in `Otto8`.
Every Tool repository must have a `tool.gpt` file in its root directory.
The Tools defined in this file must have a descriptive `Name` and `Description` that will help Agents understand what the Tool does, what it returns (if anything), and all the `Parameters` it takes.
Agents use these details to figure out when and how to use the Tool. We call the section of a Tool definition that contains this info a `Preamble`.
We want the `Hash` Tool to return the hash of some given `data`. It would also be nice to support a few different algorithms for the Agent to choose from.
+
Let's take a look at the `Preamble` for `Hash` to see how that's achieved:
-```text
+```yaml
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
Param: data: The data to hash
@@ -51,12 +50,15 @@ Breaking this down a bit:
- In this case, the description of the `algo` parameter outlines the valid options (`sha256` or `md5`) and defines a default value (`sha256`)
- The `Description` explains what `Hash` returns with respect to the given arguments; the hash of `data` using the algorithm selected with `algo`.
+
+
Immediately below the `Preamble` is the `Tool Body`, which tells `Otto8` how to execute the Tool:
-```text
+```bash
#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/hash.py
```
+
This is where the magic happens.
To oversimplify, when an Agent calls the `Hash` Tool, `Otto8` reads this line and then:
@@ -67,9 +69,11 @@ To oversimplify, when an Agent calls the `Hash` Tool, `Otto8` reads this line an
4. Projects the call arguments onto environment variables (`DATA` and `ALGO`)
5. Runs `python3 ${GPTSCRIPT_TOOL_DIR}/hash.py`.
+
+
Putting it all together, here's the complete definition of the `Hash` Tool.
-```text
+```yaml
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
Param: data: The data to hash
@@ -78,16 +82,20 @@ Param: algo: The algorithm to generate a hash with. Default is "sha256". Support
#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/hash.py
```
-### Tool Metadata
+
+
+## Tool Metadata
The `tool.gpt` file also provides the following metadata for use in `Otto8`:
- `!metadata:*:category` which tags Tools with the `Crypto` category to promote organization and discovery
- `!metadata:*:icon` which assigns `https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg` as the Tool icon
-Where `*` is a wild card pattern that applies the metadata to all Tools in a `tool.gpt`.
+
-```text
+> **Note:** `*` is a wild card pattern that applies the metadata to all Tools in a `tool.gpt`.
+
+```yaml
---
!metadata:*:category
Crypto
@@ -97,17 +105,24 @@ Crypto
https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
-**Note:** Metadata can be applied to a specific Tool by either specifying the exact name (e.g. `!metadata:Hash:category`) or by adding the metadata directly to a Tool's `Preamble`:
+
+
+ Note: Metadata can be applied to a specific Tool by either specifying the exact name (e.g. !metadata:Hash:category
) or by adding the metadata directly to a Tool's Preamble
+
-```text
+```yaml
Name: Hash
Metadata: category: Crypto
Metadata: icon: https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
+
+
+
-### Complete `tool.gpt`
+
+ Complete tool.gpt
-```text
+```yaml
---
Name: Hash
Description: Generate a hash of data using the given algorithm and return the result as a hexadecimal string
@@ -125,9 +140,11 @@ Crypto
https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-duotone.svg
```
----
+
-### Implementing Business Logic
+
+
+## Implementing Business Logic
The `hash.py` file executed by the `Tool Body` is the concrete implementation of the Tool's business logic.
@@ -190,10 +207,11 @@ This object contains the hash and the algorithm used to generate it.
}))
```
-Producing structured data with extra contextual info (e.g. the algorithm) is considered good form.
-It's a pattern that improves the Agent's ability to correctly use the Tool's result over time.
+> **Note:** Producing structured data with extra contextual info (e.g. the algorithm) is considered good form.
+> It's a pattern that improves the Agent's ability to correctly use the Tool's result over time.
-### Complete `hash.py`
+
+ Complete hash.py
```python
import hashlib
@@ -239,9 +257,11 @@ if __name__ == '__main__':
sys.exit(1)
```
----
+
+
+
-### Testing `hash.py` Locally
+## Testing `hash.py` Locally
Before adding a Tool to `Otto8`, verify that the Python business logic works on your machine.
@@ -276,36 +296,70 @@ To do this, run through the following steps in the root of your local fork:
| `DATA='foo' ALGO='md5' python3 hash.py` | `{ "algo": "md5", "hash": "acbd18db4cc2f85cedef654fccc4a4d8" }` |
| `DATA='foo' ALGO='whirlpool' python3 hash.py` | `Error: Unsupported hash algorithm: whirlpool not in ['sha256', 'md5']` |
----
+
-### Adding The `Hash` Tool to `Otto8`
+## Adding The `Hash` Tool to `Otto8`
Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto8` by performing the steps below:
-1. Navigate to the `Otto8` admin UI in a browser and open the Tools page by clicking the "Tools" button in the left drawer
- ![Open The Tools Page](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/add-tools-step-0.png "Open The Tools Page")
-
-2. Click the "Register New Tool" button on the right
- ![Click The Register New Tool Button](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/add-tools-step-1.png "Click The Register New Tool Button")
-
-3. Type the Tool repo reference into the modal's input box -- in this example `github.com/otto8-ai/python-hash-tool` -- and click "Register Tool"
- ![Enter Tool Repo Reference](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/add-tools-step-2.png "Enter Tool Repo Reference")
-
-Afterwords, the Tool will be available for use in `Otto8`.
-
-You can search for the Tool by category or name on the Tools page to verify:
-
-![Search For Newly Added Tools](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/add-tools-step-3.png "Search For Newly Added Tools")
-
-### Using The `Hash` Tool in an Agent
+1.
+ Navigate to the Otto8
admin UI in a browser and open the Tools page by clicking the Tools button in the left drawer
+
+
+
+
+
+2.
+ Click the Register New Tool button on the right
+
+
+
+
+
+3.
+ Type the Tool repo reference into the modal's input box and click Register Tool
+
+
+
+
+
+
+
+
+ Once the tool has been added, you can search for it by category or name on the Tools page to verify
+
+
+
+
+
+## Using The `Hash` Tool in an Agent
To use the `Hash` Tool in an Agent, open the Agent's Edit page, then:
-1. Click the "Add Tool" button under either the "Agent Tools" or "User Tools" sections
- ![Click The Add Tool Button](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/use-tools-step-0.png "Click The Add Tool Button")
-
-2. Search for "Hash" or "Crypto" in the Tool search pop-out and select the `Hash` Tool
- ![Add Hash Tool To Agent](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/use-tools-step-1.png "Add Hash Tool To Agent")
-
-3. Ask the Agent to generate a hash
- ![Ask The Agent To Generate a Hash](https://raw.githubusercontent.com/otto8-ai/python-hash-tool/refs/heads/main/docs/use-tools-step-2.png "Ask The Agent To Generate a Hash")
+1.
+ Click the Add Tool button under either the Agent Tools or User Tools sections
+
+
+
+
+
+2.
+ Search for "Hash" or "Crypto" in the Tool search pop-out and select the Hash
Tool
+
+
+
+
+
+3.
+ Ask the Agent to generate a hash
+
+
+
+