When a user writes ${env.SOME_VAR} inside an agent's instruction: field, docker-agent ships the literal placeholder text to the LLM as part of the system prompt without expansion, evaluation, or warning. The user has no signal that their template was not honored — the agent just behaves as if the placeholder were a literal string in the system prompt, which the model then tries to reason about.
Reproduction
agents:
root:
model: claude-sonnet-4-6
description: Demo
instruction: |
You are an automated reviewer for ${env.TARGET_REPO}. Operate only on this repository.
toolsets: []
Set TARGET_REPO=acme/foo in the runtime's environment. Run the agent. Inspect the system prompt agent sends to the model - it contains the literal text ${env.TARGET_REPO}, not acme/foo.
The same behavior applies to toolsets[*].instruction. Seems the overall behavior is quite inconsistent:
| Field |
Expanded? |
agents.<name>.description |
✅ |
agents.<name>.welcome_message |
✅ |
agents.<name>.commands |
✅ |
agents.<name>.instruction |
❌ |
toolsets[*].env |
✅ |
toolsets[*].instruction |
❌ |
I think the current approach (silently passing ${env.X} through to the model as content) - is the worst of the available options. Could we:
-
Fail loud at agent load. Detect ${...} patterns in instruction: and toolsets[*].instruction: at load time and either error or log a WARN clearly identifying the offending field and pattern. This signals "you wrote what looks like a template literal in a field that doesn't support templating."
-
Expand instruction: too. The current non-expansion is plausibly intentional - instruction: is typically multi-line user-authored prose that may contain literal ${...} for legitimate reasons (shell examples, regex snippets, the model's own format spec). Expanding by default would introduce a different footgun. Yet, being able to refer to environment variables in the prompt (even if it's somehow opt-in), would be quite useful.
When a user writes
${env.SOME_VAR}inside an agent'sinstruction:field, docker-agent ships the literal placeholder text to the LLM as part of the system prompt without expansion, evaluation, or warning. The user has no signal that their template was not honored — the agent just behaves as if the placeholder were a literal string in the system prompt, which the model then tries to reason about.Reproduction
Set
TARGET_REPO=acme/fooin the runtime's environment. Run the agent. Inspect the system prompt agent sends to the model - it contains the literal text${env.TARGET_REPO}, notacme/foo.The same behavior applies to
toolsets[*].instruction. Seems the overall behavior is quite inconsistent:agents.<name>.descriptionagents.<name>.welcome_messageagents.<name>.commandsagents.<name>.instructiontoolsets[*].envtoolsets[*].instructionI think the current approach (silently passing
${env.X}through to the model as content) - is the worst of the available options. Could we:Fail loud at agent load. Detect
${...}patterns ininstruction:andtoolsets[*].instruction:at load time and either error or log a WARN clearly identifying the offending field and pattern. This signals "you wrote what looks like a template literal in a field that doesn't support templating."Expand
instruction:too. The current non-expansion is plausibly intentional -instruction:is typically multi-line user-authored prose that may contain literal${...}for legitimate reasons (shell examples, regex snippets, the model's own format spec). Expanding by default would introduce a different footgun. Yet, being able to refer to environment variables in the prompt (even if it's somehow opt-in), would be quite useful.