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 acceptsfile:andexec: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 requiredargumentsarray 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
execvalues have environment variables expanded before execution using the tool’senvplus 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
execvalues 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
-for-i: the directory containing the.lecfile. - Otherwise: the directory from which you invoked the
lecticcommand.
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
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_NAMEinside 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
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.