Tools¶
Tools let the AI do more than just respond with a message.
Shell tool !sh
¶
!sh <prompt>
- Ask the AI to execute shell commands directly.
The shell tool prompts the AI to generate a shell script to be executed on your machine. Both the code and the output is added to the conversation history.
[0]: !sh list my home dir
↓↓↓
ls -lh ~
⚙ ⚙ ⚙
Desktop
Documents
...
Require confirmation !?
¶
If you're worried about destructive side effects, you can require your final
confirmation with !?sh
.
[0]: !?sh delete evidence.txt
↓↓↓
rm evidence.txt
⚙ ⚙ ⚙
[QUESTION] Execute? y/[n]:
Make tool optional ?
¶
To let the AI to decide whether to use your suggested tool, add a "?" as a suffix to the tool’s name.
[0]: !sh? how old is the earth?
The Earth is approximately 4.54 billion years old.
Note that the answer was given without invoking the shell tool.
Repeat !
¶
Sometimes simply asking the AI the same prompt over again helps it work through
errors it may have encountered in script or code writing. A lone !
in the
REPL is a shortcut to do this. Note that the previous invocation and error is
now in the conversation history which guides the AI to improve its answer.
[0]: !sh what's the weather in santa clara, ca
↓↓↓
curl -s 'wttr.in/Santa+Clara,CA?format=%C+%t'
⚙ ⚙ ⚙
Unknown location; please try ~37.2333253,-121.6846349
[3]: !
↓↓↓
curl -s 'wttr.in/Santa+Clara?format=%C+%t'
⚙ ⚙ ⚙
Partly cloudy +51°F
Same tool, different prompt ! <prompt>
¶
If you need to change your prompt while using the same tool, use ! <prompt>
(note that sh
is omitted). Following from the above weather example:
[6]: ! how about tokyo?
↓↓↓
curl -s 'wttr.in/Tokyo?format=%C+%t'
⚙ ⚙ ⚙
Clear +59°F
Tool mode¶
If you find yourself using the same tool over-and-over, you can enter tool-mode
by specifying a tool without a prompt (e.g. !sh
).
[0]: !sh
Entering tool mode; All messages are treated as prompts for !sh.
To exit tool mode, use !exit
or Ctrl + D
.
Tool mode in tasks
When publishing tasks, you can place users directly into tool-mode by
making it the final command in your task's list of steps. This approach is
helpful when your task relies on a tool to respond to user requests. If
your task requires tool use and regular text responses, consider using the
optional suffix for the tool mode (e.g. !sh?
).
Python Tool !py
!pyuv
¶
!py
prompts the AI to write a Python script and execute it with your system
Python or virtual env (.venv
) if available in the current working directory.
It may use dependencies that you do not have installed: you can either install
them, try repeat !
to see if the AI can work around it, or use
!pyuv
described below.
!pyuv
prompts the AI to write Python with
script dependencies
so that dependencies can be automatically installed. It requires
uv
.
Here's an example of it in action:
[0]: !pyuv distance from sf to nyc
↓↓↓
# /// script
# dependencies = ["geopy"]
# ///
from geopy.distance import geodesic
# Coordinates: (lat, lon)
sf = (37.7749, -122.4194)
nyc = (40.7128, -74.0060)
distance_km = geodesic(sf, nyc).kilometers
distance_miles = geodesic(sf, nyc).miles
print(f"Distance from San Francisco to New York City: {distance_km:.2f} km ({distance_miles:.2f} miles)")
⚙ ⚙ ⚙
Distance from San Francisco to New York City: 4139.15 km (2571.95 miles)
Custom program tool !'<cmd>'
¶
You can prompt the AI to generate the stdin
to any program. For example, to
use psql
:
[0]: !'psql -U postgres -d my_db' what db users are there?
↓↓↓
SELECT usename FROM pg_user;
⚙ ⚙ ⚙
usename
---------
postgres
...
A {file}
placeholder can be used to prompt the AI to generate an input file
rather than stdin
. The below example demonstrates the difference using uv
.
# Uses stdin (-)
[0]: !'uv run --with geopy -' distance from sf to nyc
OR
# Uses temporary file
[0]: !'uv run --with geopy {file.py}' distance from sf to nyc
↓↓↓
from geopy.distance import geodesic
sf_coords = (37.7749, -122.4194) # San Francisco coordinates
nyc_coords = (40.7128, -74.0060) # New York City coordinates
distance = geodesic(sf_coords, nyc_coords).miles
print(distance)
⚙ ⚙ ⚙
2571.9457567914133
Note that a file extension was specified (e.g. {file.<ext>}
) to force the
temporary file to have a particular extension and enable syntax highlighting.
This is helpful for programs that require input to have a specific extension
(uv
happens to be one of them, requiring .py
).
Tip
Note that uv
is used for demonstrative purposes only and !pyuv
would
be the recommended tool for using uv
.
HTML tool !html
¶
Even a terminal jockey needs to touch grass every now and then.
To prompt the AI to help you visualize output, you can ask for HTML output that
will be opened by your configured system-default browser. Asking for iterations
using the !html
tool will trigger reloads automatically.
Clipboard tool !clip
¶
Are you a caveman reaching over to your mouse to copy-and-paste from the
terminal? Use !clip
to ask the AI to copy-and-paste whatever your need.
For example:
!clip option #3
hai tool !hai
¶
The LLM knows how to use the REPL.
[7]: !hai load silk road wiki. who was the founder?
↓↓↓
- /load-url https://en.wikipedia.org/wiki/Silk_Road_(marketplace)
- /prompt Who was the founder of the Silk Road marketplace?
⚙ ⚙ ⚙
Pushed 2 command(s) into queue
!hai-tool[0]: /load-url https://en.wikipedia.org/wiki/Silk_Road_(marketplace)
Loaded (markdown): Silk Road (marketplace) (32,696 tokens)
!hai-tool[1]: /prompt Who was the founder of the Silk Road marketplace?
↓↓↓
The founder of the Silk Road marketplace was **Ross Ulbricht**, who operated under the pseudonym "Dread Pirate Roberts."
The AI is capable enough to know what URL to load and then ask itself a question about the contents.
!hai recursion¶
Some LLMs (sonnet-3.7
is most reliable) are able to work out whether they
need to re-prompt themselves to act on intermediate information.
In this example, only the first command is prompted by the user. The rest,
prefixed by hai-tool[ ]:
, are prompted by the AI. For brevity, user
confirmations are omitted.
[0]: !hai get a random number. if it is even, ask the AI how large the sun is. if it is odd, delete `file1.txt`.
↓↓↓
- !py Generate a random number and determine if it's even or odd
- !hai Based on the random number generated, if it's even, ask how large the sun is. If it's odd, delete file1.txt
⚙ ⚙ ⚙
Pushed 2 command(s) into queue
hai-tool[3]: !py Generate a random number and determine if it's even or odd
↓↓↓
import random
# Generate a random number between 1 and 100
random_number = random.randint(1, 100)
# Check if the number is even or odd
if random_number % 2 == 0:
result = "even"
else:
result = "odd"
print(f"The random number is: {random_number}")
print(f"The number is {result}")
⚙ ⚙ ⚙
The random number is: 86
The number is even
hai-tool[6]: !hai Based on the random number generated, if it's even, ask how large the sun is. If it's odd, delete file1.txt
↓↓↓
- /prompt How large is the sun? Please provide information about its diameter, volume, and mass compared to Earth.
⚙ ⚙ ⚙
Pushed 1 command(s) into queue
hai-tool[9]: /prompt How large is the sun? Please provide information about its diameter, volume, and mass compared to Earth.
↓↓↓
# The Size of the Sun
The Sun is enormously large compared to Earth. Here are the key measurements:
- Sun's diameter: approximately 1.39 million kilometers (864,000 miles)
- Sun's volume: approximately 1.41 × 10^18 cubic kilometers
- Sun's mass: approximately 1.989 × 10^30 kilograms
Function tool !fn-*
¶
A drawback of !py
and !sh
is that there's no ability to re-use the code
that was written. The LLM writes code every time the tool is invoked, which can
consume a lot of output tokens and the time it takes to generate them.
For example, computing the square root of pi:
[0] !py sqrt pi
↓↓↓
import math
print(math.sqrt(math.pi))
⚙ ⚙ ⚙
1.7724538509055159
A second request to compute the square root of e requires the code to be rewritten:
[3] !py sqrt e
↓↓↓
import math
print(math.sqrt(math.e))
⚙ ⚙ ⚙
1.6487212707001282
The solution is to use !fn-py <prompt>
which instructs the AI to generate a
Python function that takes an argument and prints the result to add it to the
conversation.
[0]: !fn-py find the sqrt, print the result
↓↓↓
def f(arg):
import math
result = math.sqrt(arg)
print(result)
⚙ ⚙ ⚙
Stored as command: /f0
The new function can be invoked like a command: /f0 <arg>
without prompting
the LLM. For example:
[3]: /f0 64
8.0
The LLM can invoke /f0
when you use the !hai
tool:
[5]: !hai what's the sqrt of pi
↓↓↓
- /f0 3.141592653589793
⚙ ⚙ ⚙
Pushed 1 command(s) into queue
!hai-tool[0]: /f0 3.141592653589793
1.7724538509055159
For a reusable shell function, use !fn-sh
. For a resuable Python function
that can declare script dependencies, use !fn-pyuv
.
Use native expressions as function args¶
For !fn-py
and !fn-pyuv
, the arg can be any Python expression.
[0]: !fn-py distance from san francisco. input is tuple of geo coordinates. print result.
↓↓↓
def f(arg):
# arg is a tuple of (latitude, longitude)
from math import radians, sin, cos, sqrt, atan2
# San Francisco coordinates
sf_lat, sf_lon = 37.7749, -122.4194
lat1, lon1 = sf_lat, sf_lon
lat2, lon2 = arg
# Radius of the Earth in kilometers
R = 6371.0
# Convert degrees to radians
dlat = radians(lat2 - lat1)
dlon = radians(lon2 - lon1)
a = sin(dlat / 2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = R * c
print(f"Distance from San Francisco, CA to {arg}: {distance:.2f} km")
⚙ ⚙ ⚙
Stored as command: /f0
Using a Python tuple as the arg:
[3]: /f0 (0.0, 78.5)
Distance from San Francisco, CA to (0.0, 78.5): 15299.16 km
Similarly, !fn-sh
accepts a shell expression.
Named functions¶
Use the name
option to give a function a proper name:
[0] !fn-py(name="sqrt") find the sqrt
↓↓↓
def f(arg):
import math
return math.sqrt(arg)
⚙ ⚙ ⚙
Stored as command: /f_sqrt
Show all functions¶
To see all functions declared in the current conversation, use:
/fns