The contents for section are being revised. Thank you for your patience.
In the previous chapters, we used the chores package to develop helpers—pre-written prompts—for repetitive tasks such as creating roxygen2 documentation and updating testthat tests.1 In the gander chapter, we used the addin to send code and environment context to the LLM.2
chores and gander assist us in automating or enhancing the prompts we submit to the LLM. The addins and shortcuts streamline our interactions with the model, allowing for a more intuitive and efficient experience that resembles a browser interface (like ChatGPT).
Access the applications in this chapter
I’ve created the shinypak R package in an effort to make each section accessible and easy to follow. Install shinypak using pak (or remotes):
In this chapter we’ll focus on the btw package, which is fundamentally different than chores and gander because it,
“provides a default set of tools to to peruse the documentation of packages you have installed, check out the objects in your global environment, and retrieve metadata about your session and platform.”3
I’ll cover using btw to add documentation and improve the contents of the downloadable report in our sap application.
30.1 Configuration
We can place the btw configuration options in the .Rprofile (similar to other ellmer configurations).4 Recall that the .Rprofile file can exist at the user and/or the project-level.
For example, I’ve added a project-level .Rprofile file this branch of the sap package and included a system_prompt and model:
if (interactive()) {require(ellmer, quietly =TRUE)}if (interactive()) {require(btw, quietly =TRUE)}options(btw.client = ellmer::chat_anthropic(system_prompt ="You are an expert R/Python programmer who loves explaining complex topics to non-technical audiences. - When writing R code, use base R functions, but follow the tidyverse style guide. - Avoid using `for` loops and prefer functional programming patterns like `apply()` or `purrr`. - When creating graphs/plots, use `ggplot2`. - If writing R Shiny code, use `bslib` for all layout functions (unless explicitly instructed otherwise). - If writing Python Shiny code, use shiny core (not express) to build apps and include explanations in comments. ",model ="claude-sonnet-4-5-20250929" ))
btw comes with a set of pre-defined tools for examining package documentation, environments, directories and files, git and GitHub, our development environment, CRAN packages, R sessions, and general web searches.5
We can use btw to work interactively in the Positron (or RStudio ) console by creating a btw-enhanced chat client and passing messages directly.6
chat <-btw_client()
We can view the btw enhancements by examining the chat object in the console:
chat
btw has added ‘System and Session Context’ and ‘Tools’ sections to the chat client.
# System and Session ContextPlease account for the following R session and system settings in all responses.<system_info>R_VERSION: R version 4.5.1 (2025-06-13)OS: macOS Tahoe 26.0.1SYSTEM: x86_64, darwin20UI: Positron (a VS Code equivalent)LANGUAGE: (EN)LOCALE: en_US.UTF-8ENCODING: en_US.UTF-8TIMEZONE: America/PhoenixDATE: Tuesday, October 28, 2025 (2025-10-28)</system_info># ToolsYou have access to tools that help you interact with the user's R session andworkspace. Use these tools when they are helpful and appropriate to complete the user's request. These tools are available to augment your ability to helpthe user, but you are smart and capable and can answer many things on your own. It is okay to answer the user without relying on these tools.
We can see the model will have some additional instructions/methods at it’s disposal (beyond what we’ve provided in the system_prompt argument of ellmer::chat_anthropic()).
30.3 Project context
As we learned in the ellmer chapter, project prompts should be stored in inst/prompts/. btw also provides the use_btw_md() function, which creates a project ‘context file.’
use_btw_md(scope ="project")
The btw.md file comes with some default content for project context:
“Use btw.md to inform the LLM of your preferred code style, to provide domain-specific terminology or definitions, to establish project documentation, goals and constraints, to include reference materials such or technical specifications, or more. Storing this kind of information in btw.md may help you avoid repeating yourself and can be used to maintain coherence across many chat sessions.”
client
The YAML header in our newly created btw.md is where can specify the client (along with the provider and model).
---client: claude/claude-4-5-sonnet-latest---
The default values in btw.md will automatically use the latest Claude model from Anthropic. The YAML values above are similar to using ellmer’s chat_* functions.7
tools
The tools section of the YAML header contains a list of the groups from btw_tools(). Each of these groups contains a collection of functions “that allow the chat to interface with your computational environment.”
LLMs can’t execute R code, but if we’ve registered tools (i.e., R functions) with the model, they can be used to help provide additional information.
As mentioned above, btw has a collection of tools at our disposal, so when we start the interactive chat, the model informs us it will be examining the sap package contents for more information.
>>>"Let's get started."
I'll help you create a comprehensive project summary. Let me start by exploring your project structure to understand what we're working with.
30.5.1 Registered tools
When a tool is registered with the LLM, we include the name of the function, a description of what the function does, a list of function arguments and their type (boolean, integer, number, string, etc.). 8
We can view all the tools registered with the LLM using:
chat$get_tools()
Note
The btw_tools() function lists all the tools we could register, but chat$get_tools() returns the tools that are registered with the model.
30.5.2 Tool descriptions
The output from chat$get_tools() is rather lengthy, but we can use Ctrl/Cmd + F to locate btw_tool_files_list_files(), the first tool called by the LLM.
Recall the model was going to start by ‘exploring your project structure’, and we can see this aligns with the’ @description:
List files or directories in the project.WHEN TO USE:* Use this tool to discover the file structure of a project.* When you want to understand the project structure, use `type = "directory"` to list all directories.* When you want to find a specific file, use `type = "file"` and `regexp` to filter files by name or extension.CAUTION: Do not list all files in a project, instead prefer listing files in a specific directory with a `regexp` tofilter to files of interest.
30.5.3 Tool calls
The tool calls and a preview of their results are printed in the console. Below is the first call to btw_tool_files_list_files():
The table output is sent to the LLM, which them provides a summary of the contents:
Perfect! I can see this is an **R package** with a Shiny application. The structure shows:- `DESCRIPTION` and `NAMESPACE` files (R package essentials)- Extensive `R/` directory with many Shiny modules (`mod_*.R` files)- `app.R` file (Shiny app entry point)- `data/` directory with datasets- `tests/testthat/` (comprehensive testing)- `vignettes/` (package documentation)- `renv.lock` (dependency management)
The prompt directory is where chores stores the helpers used in the addin.↩︎
The _intent argument is “An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool.”↩︎
I’ve cleaned up the formatting on this markdown table so it’s easier to read.↩︎