Creating Instructions for Actions

Letting a language model directly change data, call APIs or touch production systems can be powerful, but it is also risky and hard to reason about. A simple pattern to make this safer and more transparent is to separate “deciding what to do” from “actually doing it”. Instead of letting the model perform actions directly, you first let it generate explicit instructions for actions, and only then interpret those instructions and execute them.

In this pattern, the model never performs actions itself. Its responsibility is to describe the actions that should be taken. It receives a user request and responds with a set of instructions in a structured, predictable format. There are no direct API calls, no hidden side effects, only a clear description of intent.

To make these instructions reliable and machine-friendly, you use a domain specific language (DSL) for instructions and actions. The DSL defines how actions are represented: which actions exist, what parameters they take, which resources they operate on, and what constraints apply. For example, an instruction might look like a JSON object such as:

{
"action": "update_user",
"params": {
"user_id": "123",
"fields": {
"email": "new@example.com"
}
}
}

The important point is that the model outputs this DSL, not raw API calls or free-form text describing side effects.

After the model has generated instructions in the DSL, a separate component is responsible for interpreting and executing them. This interpreter reads the DSL, validates it, and then maps each instruction to real actions in your system. For example, it might translate update_user into a call to a user service, or send_email into a call to your email provider. The interpreter also enforces rules: checking required fields, rejecting unsafe actions, enforcing permissions, and deciding what happens on errors.

This creates a clear two-step process. First, the model generates instructions for actions in a domain specific language. Second, the system interprets those instructions and executes the corresponding actions. The model does not perform anything directly. All side effects go through the interpreter and runtime.

Using this pattern has several practical benefits. It increases safety, because you can review or validate instructions before executing them. It improves observability, because you can log and inspect the exact instructions that were generated. It helps with debugging and testing, because you can replay instructions or run them in a dry-run mode without touching real systems. And it makes your setup more flexible, because you can change how actions are executed without changing how the model describes them.

In summary, instead of letting a language model act directly, let it generate instructions in a domain specific language, and then interpret and execute those instructions in a controlled way. This keeps the original idea from the notes: let agents generate instructions for actions, do not perform directly, then interpret the instructions and execute the actions, using a domain specific language for both instructions and actions.

Leave a comment