Skip to content

Tools

A tool is a function with a checked capability boundary. One declaration yields a CLI, --help, a machine-readable contract, and a --plan dry run — and the compiler proves the body cannot exceed the declaration (E0077 at the offending call site if it tries; E0078 if it overclaims).

The three-command sequence an agent follows:

$ onion Snapshot.on --contract
[{"tool":"snapshot","params":[{"name":"src","type":"String","role":"positional"},
  {"name":"dst","type":"String","role":"positional"},
  {"name":"tag","type":"String","role":"flag","default":"latest"}],
  "returns":"Int","capabilities":["read(src)","write(dst)","console"]}]

$ onion Snapshot.on notes.txt backup.txt --plan
plan: `snapshot` would
  read    src = notes.txt
  write   dst = backup.txt
  console
(nothing was executed)

$ onion Snapshot.on notes.txt backup.txt --tag nightly
snapshot [nightly]: 1 file copied

Snapshot.on

tool snapshot(src: String, dst: String, tag: String = "latest"): Int
  requires { read(src), write(dst), console }
{
  val data = Files::readText(src)
  Files::writeText(dst, data)
  IO::println("snapshot [" + tag + "]: 1 file copied")
  return 0
}

Required parameters become positionals; defaulted parameters become --name flags; a Boolean default becomes a switch. An absent flag's default is evaluated as the original expression, in the language.

The full demo — a log-digesting tool that combines a shape boundary for the messy input with a capability boundary for the effects — is run/ToolDemo.on in the repository, and the guide chapter walks through every piece: Tools and Capabilities.