6  Tools and Toolsets

Tactus supports multiple tool sources. The quick rule is:

6.1 Standard Library Tools

local done = require("tactus.tools.done")

6.2 Lua Function Tools (In-File)

slugify = Tool {
  description = "Convert text to a slug",
  input = { text = field.string{required = true} },
  function(args) return string.lower(args.text):gsub("%s+", "-") end
}

worker = Agent { model = "openai/gpt-4o-mini", tools = {slugify, done} }

6.3 Lua Toolsets (Toolset { type = "lua" })

math = Toolset {
  type = "lua",
  tools = {
    {
      name = "add",
      description = "Add numbers",
      parameters = {a = {type = "number"}, b = {type = "number"}},
      handler = function(args) return tostring(args.a + args.b) end
    }
  }
}

calculator = Agent { model = "openai/gpt-4o-mini", tools = {math, done} }

6.4 Python Plugin Tools (tool_paths)

Configure search paths in .tactus/config.yml (or a {procedure}.tac.yml sidecar):

tool_paths:
  - "./tools"
  - "./plugins"

6.5 MCP Tools (mcp_servers)

Configure MCP servers:

mcp_servers:
  filesystem:
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]

Then reference the MCP server’s toolset by its server name:

worker = Agent {
  model = "openai/gpt-4o-mini",
  tools = {"filesystem", done}
}

If you prefer, you can alias an MCP server toolset explicitly:

Toolset "filesystem_tools" {
  use = "mcp.filesystem"
}

worker = Agent { model = "openai/gpt-4o-mini", tools = {"filesystem_tools", done} }

If you want to restrict an agent to a subset of tools, use an include filter:

worker = Agent {
  model = "openai/gpt-4o-mini",
  tools = {
    {name = "filesystem", include = {"filesystem_read_file", "filesystem_write_file"}},
    done
  }
}

For deterministic calls to external tools, fetch a handle by name:

local read_file = Tool.get("filesystem_read_file")
local contents = read_file({path = "README.md"})

6.6 Brokered Host Tools

Host tools run in the broker trust zone (useful for secrets) and are invoked from the runtime:

local result = Host.call("host.ping", {value = 1})

host_ping = Tool { use = "broker.host.ping" }
local r2 = host_ping({value = 1})