Tools: Command Execution (exec)

The exec tool is one of the most versatile tools in Lectic. It allows the LLM to execute commands and scripts, enabling it to interact directly with your system, run code, and interface with other command‑line applications.

Configuration

The snippets below show only the tool definition. They assume you have an interlocutor with a valid prompt and model configuration. See Getting Started for a full header example.

You configure an exec tool by providing the command to be executed. You can also provide a custom name for the LLM to use, a usage guide, and optional parameters for security and execution control.

Simple command

This configuration allows the LLM to run the python3 interpreter.

tools:
  - exec: python3
    name: python
    usage: >
      Use this to execute Python code. The code to be executed should be
      written inside the tool call block.

Inline script

You can also provide a multi‑line script in the YAML. The first line of the script must be a shebang (for example, #!/usr/bin/env bash) to choose the interpreter.

tools:
  - name: line_counter
    usage: "Counts the number of lines in a file. Takes one argument: path."
    exec: |
      #!/usr/bin/env bash
      # A simple script to count the lines in a file
      wc -l "$1"

Configuration parameters

  • exec: (Required) The command or inline script to execute.
  • name: An optional name for the tool.
  • usage: A string with instructions for the LLM. It also accepts file: and exec: sources. See External Prompts for semantics.
  • sandbox: A path to a sandboxing script. See safety below.
  • timeoutSeconds: Seconds to wait before aborting a long‑running call.
  • env: Environment variables to set for the subprocess.
  • schema: A map of parameter name → description. When present, the tool takes named string parameters (exposed as env vars). When absent, the tool instead takes a required arguments array of strings.

Execution details

  • No shell is involved when executing single line commands. The command is executed directly. Shell features like globbing or command substitution will not work unless you invoke a shell yourself.
  • Single‑line exec values have environment variables expanded before execution using the tool’s env plus standard Lectic variables.
  • Single‑line commands are split into argv using simple shell‑like rules: single ‘…’ and double “…” quotes are supported; no globbing or substitution. If you need shell features, invoke a shell explicitly, e.g., bash -lc '...'.
  • Multi‑line exec values must start with a shebang. Lectic writes the script to a temporary file and executes it with that interpreter.

Working directory and files

The current working directory for exec is:

  • If you run with -f or -i: the directory containing the .lec file.
  • Otherwise: the directory from which you invoked the lectic command.

This means relative paths in your commands and scripts resolve relative to that directory. Temporary scripts are written into the same working directory.

Stdout, stderr, and exit codes

Lectic captures stdout and stderr separately and returns both to the model. It also includes the numeric exit code when it is non‑zero. You will see these serialized inside the tool call results as XML tags like , , and .

If a timeout occurs, Lectic kills the subprocess and throws an error that includes any partial stdout and stderr collected so far.

Named parameters with schema

You might want to control what arguments your LLM can pass to a command or script, or offer a template for correct usage. If your configuration includes a schema, the LLM will be guided to provide specific parameters when calling the script or command. Each parameter is a string and Lectic exposes it to the subprocess via an environment variable with the same name.

This applies to both commands and scripts:

  • For scripts, parameters are available as $PARAM_NAME inside the script.
  • For commands, parameters are available in the subprocess environment and also expanded in the command.

Example:

# YAML configuration
tools:
  - name: greeter
    exec: |
      #!/usr/bin/env bash
      echo "Hello, ${NAME}! Today is ${DAY}."
    schema:
      NAME: The name to greet.
      DAY: The day string to include.

or equivalently

# YAML configuration
tools:
  - name: greeter
    exec: echo "Hello, ${NAME}! Today is ${DAY}."
    schema:
      NAME: The name to greet.
      DAY: The day string to include.

If the LLM provides { NAME: "Ada", DAY: "Friday" } Lectic will fill in the results:

<tool-call with="greeter">
<arguments>
<NAME>
┆Ada
</NAME>
<DAY>
┆Friday
</DAY>
</arguments>
<results>
<result type="text">
┆Hello, Ada! Today is Friday.
┆
</result>
</results>
</tool-call>

Execution environment

When Lectic runs your command or script, it sets a few helpful environment variables. In particular, LECTIC_INTERLOCUTOR is set to the name of the interlocutor who invoked the tool. This makes it easy to maintain per‑interlocutor state (for example, separate scratch directories or memory stores) in your scripts or sandbox wrappers.

Safety and trust

Warning

Granting an LLM the ability to execute commands can be dangerous. Treat every exec tool as a capability you are delegating. Combine human‑in‑the‑ loop confirmation and sandboxing to minimize risk. Do not expose sensitive files or networks unless you fully trust the tool and its usage.

Lectic provides two mechanisms to help you keep exec tools safe: hooks and sandboxing.

Confirmation via hooks

You can use the tool_use_pre hook to implement confirmation dialogs or logic. See Hooks for examples.

Sandboxing (sandbox)

When a sandbox script is configured, a command call will actually execute the sandbox script, which will receive the command and the LLM provided parameters as arguments. The wrapper is responsible for creating a controlled environment to run the command.

For example, extra/sandbox/bwrap-sandbox.sh uses Bubblewrap to create a minimal, isolated environment with a temporary home directory.