--- title: "Agent tools" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Agent tools} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` hal connects to a coding agent with built-in tools for reading code, editing files, searching your codebase, and running commands. You can also register your own R functions as tools. ## Built-in tools Always available — no registration needed: | Tool | What it does | |---|---| | view / Read | Read file contents | | grep / Grep | Search file contents | | glob / Glob | Find files by pattern | | edit / Edit | Edit an existing file | | create / Write | Create a new file | | bash / Bash | Run shell commands | The agent decides when to use them — you just describe what you want: ```r hal("Find all functions that call the database and list them") hal("Add error handling to the process_data function") hal("Run the tests and fix any failures") ``` ## eval_r — the R bridge hal registers `eval_r` in every session so the agent can run R code in your live session, not a subprocess copy: ```r df <- mtcars hal("Which rows in df have mpg above the median?", use_env = TRUE) ``` `use_env = TRUE` injects names + types from your environment into the prompt; the agent reads actual values via `eval_r`. The default (`use_env = NULL`) auto-detects when prompt tokens match env objects. ## Plot vision When `eval_r` code draws a plot, hal captures it as a PNG and attaches it to the tool result as an image — the model sees the rendered chart, not just the code that made it: ```r df <- mtcars hal("Plot mpg vs wt and tell me what stands out") #> i hal: plot captured for the model. ``` | Backend | Plot vision | |---|---| | vscode | Yes (bundled hal-bridge >= 0.1.4; if the selected model rejects images, the bridge falls back to text automatically) | | claude | Yes (MCP image content blocks) | | copilot | No — text-only until the CLI's image forwarding is verified | Details worth knowing: - Returned `ggplot`/`lattice` objects are printed to your device first, so they appear in your plots pane as usual — and a ggplot that fails to render reports the error to the model instead of failing silently. - One image per eval: the final page (a `par(mfrow = ...)` grid is one page and is captured whole). - Plots written to file devices your code opens itself (`png()`, `pdf()`) are not echoed. - Disable globally with `hal_configure(plot_vision = FALSE)`. ## Register your own tools Turn any R function into a tool: ```r hal_register_tool( fun = function(city) paste("Sunny, 72F in", city), name = "get_weather", description = "Get current weather for a city", types = list(city = "string") ) hal("What's the weather in Austin?") ``` Register tools **before** the first `hal()` / `$chat()` call — they're passed to the CLI at startup. Bulk registration: ```r hal_register_package_tools("dplyr") hal_register_tool_specs(winston::timelog_tool_specs()) ``` ellmer `ToolDef` objects are accepted directly: ```r chat <- hal_chat() chat$register_tool(my_ellmer_tool) ``` ## Permissions, in brief Read tools auto-allow. Writes and shell commands trigger a permission request. The default policy auto-allows everything; switch to auto-deny for read-only behavior: ```r hal_configure(permission_policy = "auto-deny") ``` For custom logic (logging, interactive approval, selective allow), pass a function. See `?hal_configure` for the full reference. ## Next - `?hal_register_tool` — full tool builder reference - `?hal_configure` — governance settings (policies, denylist, timeout)