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:

async function executeShellCommand(command: string): Promise<string> {
  const { stdout } = await exec(command);
  return stdout;
}

An arbitrary exec 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:

async function searchBooks(query: string): Promise<string> {
  return await bookCatalogApi({ query, limit: 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 orderId and userId, so a prompt can steer it toward another customer's orders. Bind status lookups to the authenticated user.

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