llm icon indicating copy to clipboard operation
llm copied to clipboard

Tools in templates, and maybe in fragments too

Open simonw opened this issue 7 months ago • 1 comments

I think templates are the natural place to define collections of tools that can be referenced together.

Maybe fragments as well? Fragments have the advantage that you can apply more than one to the same prompt.

simonw avatar May 12 '25 19:05 simonw

I want templates to be able to include raw Python code - the python_tools: string of code YAML string described in:

  • #1008

I am nervous about the intersection of templates that can execute arbitrary Python code with mechanisms that can load a template from the internet - like passing a URL to a template or plugins such as https://github.com/simonw/llm-templates-github

One option could be to introduce the concept of an untrusted template, which requires users to pass --unsafe on the CLI in order to use it.

simonw avatar May 12 '25 19:05 simonw

Decisions:

  1. Templates can have a tools: [list of tools] list with plugin specs (llm_version, Datasette("...") etc to use with that template
  2. Running llm -T llm_version --save X will save those templates
  3. functions: can also be stored in the template
  4. Some kind of mechanism to discourage or prevent templates from arbitrary sources including executable code

I'm likely over-thinking this: any time people run llm install llm-... from PyPI they are exposing themselves to attacks (which I don't like but that's the nature of Python these days.)

An early idea I head:

For 4, I'm going to add a functions_trusted: true/false YAML key. When you run llm --functions '...' --save X locally it will set that to true for you. Existing plugins won't know about this mechanism so they'll be treated as unsafe.

What should that do?

  • It could throw a hard error - if you try to execute a template with --functions but no functions_trusted you could get a hard error
  • Or maybe a warning or an optional "enable this code" thing?

But then I remembered this feature exists:

llm -t https://url-to-template

I don't want people executing URLs to templates that contain functions and have functions_trusted: true in them. So I need something a bit more baked in.

Maybe it's OK to execute functions from those URLs if the user is presented them first and gets to approve them. Obfuscated code attacks could trip people up so it's a little risky.

Some potential rules then:

  • Templates on disk get to define functions: with no approval needed to run them, they are assumed trusted.
  • Templates from a URL cannot do that. They are either treated as needing approval or maybe they aren't executed under any circumstances. That would be easiest to implement and simplest to explain, I can always add an "opt in to executing from URLs" mechanism in the future. The workaround is so easy: wget https://.... && llm -t downloaded.yaml ...
  • How about templates loaded by template loader plugins? I'm on the fence on this one. Easiest thing would be to say they can't define functions either, but that feels like a wasted opportunity to build some really cool plugins. But... those plugins can be built another way: the plugin can use the register_tools() hook to register some named functions/classes and then the template it returns can reference those names in the --tools: list.

So, decision: functions: in templates only works for templates loaded from disk, either with -t path/to/template.yml or -t saved-template-name.

simonw avatar May 30 '25 20:05 simonw

It's a bit weird that the YAML prototype has --functions as a list of strings of Python code, as opposed to just one big block of code.

I built it that way because it turns out --functions ... can be called multiple times in a single prompt. That's so you can do this:

llm --functions one.py --functions two.py 'prompt goes here'

But for a template there's no value in having multiple functions: lines, they could all be just one.

So I think I'll have functions: in the template as a single string, then when you run --save X I'll concatenate together multiple --functions strings with a pair of newlines.

simonw avatar May 30 '25 20:05 simonw

How about a third option which could be enabled in a config file: send functions in templates from URLs to an LLM with a prompt to check it for security vulnerabilities before use, OR more have a more general config option which says how to handle functions from URL's matching a pattern/regexp.

vapniks avatar Aug 09 '25 10:08 vapniks