What it is
Tools are callable functions the LLM can request during an agent run. They are the primary way an agent interacts with the outside world: reading/writing files, executing commands, talking to services, or asking a human for confirmation.
Phero tools are just function tools from llm, registered on an agent.
Built-in tool packages
Phero includes a few ready-to-use tools under tool/. These are designed to be easy to attach to an agent.
Exact behavior can be customized with llm.Tool.Use(...) middleware.
- File tools (
tool/file):view,create_file,str_replace - Bash tool (
tool/bash): run bash commands with optional guardrails (blocklist, allowlist, timeout, safe mode) - Human tool (
tool/human): ask the user for input/approval mid-run
Tip: for anything with side effects (writes or shell commands), add an approval middleware.
Bash tool guardrails
The bash tool ships with several security options to restrict what the agent can run.
import (
"time"
"github.com/henomis/phero/tool/bash"
)
// Safe mode: applies a built-in blocklist of dangerous patterns
// and sets a 30-second timeout.
bashTool, err := bash.New(bash.WithSafeMode())
// Fine-grained control:
bashTool, err := bash.New(
bash.WithWorkingDirectory("/tmp/sandbox"),
bash.WithTimeout(10*time.Second),
bash.WithBlocklist("curl", "wget"), // blocked substrings
bash.WithAllowlist("ls", "cat", "echo"), // only these are allowed
)
WithSafeMode(): enables a built-in blocklist (rm -rf /,dd if=, fork bombs, …) and a 30 s timeoutWithTimeout(d): maximum execution time per command; context deadline takes precedence when shorterWithBlocklist(patterns...): any command containing a pattern (case-insensitive) returnsErrCommandBlockedWithAllowlist(patterns...): when set, the command must match at least one pattern orErrCommandNotAllowedis returnedWithWorkingDirectory(dir): directory in which commands run
File tool: prevent overwriting
By default CreateFileTool silently overwrites existing files.
Pass WithNoOverwrite() to return ErrFileExists instead.
import "github.com/henomis/phero/tool/file"
createTool, err := file.NewCreateFileTool(
file.WithWorkingDirectory("/workspace"),
file.WithNoOverwrite(),
)
if err != nil {
panic(err)
}
The examples/skills program combines skills with a file-writing tool that asks the user to approve writes before the underlying tool handler runs.
// From examples/skills (edited for brevity)
createFileTool, err := file.NewCreateFileTool()
if err != nil {
panic(err)
}
tools = append(tools, createFileTool.Tool().Use(func(_ *llm.Tool, next llm.ToolHandler) llm.ToolHandler {
return func(ctx context.Context, arguments string) (any, error) {
var input *file.CreateFileInput
if err := json.Unmarshal([]byte(arguments), &input); err != nil {
return nil, &llm.ToolArgumentParseError{Err: err}
}
if err := writeValidationFunc(ctx, input); err != nil {
return nil, err
}
return next(ctx, arguments)
}
}))
for _, tool := range tools {
if err := a.AddTool(tool); err != nil {
panic(err)
}
}
// From examples/skills (edited for brevity)
func writeValidationFunc(_ context.Context, input *file.WriteInput) error {
fmt.Printf("Do you want to write to the file '%s'? (y/N): ", input.Path)
var permission string
_, scanErr := fmt.Scanln(&permission)
if scanErr != nil {
return fmt.Errorf("failed to read user input: %w", scanErr)
}
if strings.EqualFold(permission, "y") {
return nil
}
return fmt.Errorf("user permission denied")
}
This pattern keeps the agent powerful while still giving the user control.
Default tools inside skills
When you convert a skill into a tool, Phero automatically gives the skill-agent a small local toolbox rooted at the skill directory:
view, create_file, str_replace, and bash.
That makes skill execution self-contained: the skill can inspect files, make targeted edits, or run commands without needing separate tool wiring in the caller.
Run an example
These are good starting points to see tools in action (provider setup is described in each example README):
# Skills + built-in file/bash tools (run from example dir)
cd ./examples/skills
go run .
# Multi-agent workflow (uses a custom restricted command tool)
cd -
go run ./examples/multi-agent-workflow