We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Narrow Tool Interfaces

Limiting which tools a model can call still isn't enough. You should also narrow the interface of each tool.

This is a more nuanced concept, but to be clear, here's the opposite of what I mean:

func executeShellCommand(ctx context.Context, command string) (string, error) {
  output, err := exec.CommandContext(ctx, "sh", "-c", command).Output()
  return string(output), err
}

An arbitrary command-execution tool is just about the most insecure thing you can hand to a user-facing LLM. However, a dedicated searchBooks tool is a lot better:

func searchBooks(ctx context.Context, query string) ([]Book, error) {
  return bookCatalog.Search(ctx, query, 5)
}

All the model can do here is specify the query string and receive up to five results at a time, a limit it can't change. It also gives us the control to validate the query string in deterministic code and reject anything that doesn't match our expected patterns.

Assignment

Bearly Secure's status tool lets the model supply both an order ID and a user ID, so a prompt can steer it toward another customer's order. Bind status lookups to the authenticated user.

With Bearly Secure still running, run and submit the CLI tests from the project root.