Sandcastle gives you two ways to supply a prompt to an agent: an inline string you construct in JavaScript, or a prompt template file that Sandcastle processes before handing it to the agent. Understanding the difference — and when to use each — is the starting point for building reliable agent workflows.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mattpocock/sandcastle/llms.txt
Use this file to discover all available pages before exploring further.
Two ways to provide a prompt
You must provide exactly one ofprompt or promptFile on every run() call. Providing both is an error; omitting both is also an error.
sandcastle init scaffolds .sandcastle/prompt.md and all built-in templates reference it via promptFile: ".sandcastle/prompt.md". This is a convention, not an automatic fallback — Sandcastle does not read .sandcastle/prompt.md unless you pass it as promptFile.Inline prompts
When you useprompt: "...", the string is passed to the agent exactly as you wrote it. There is no {{KEY}} substitution, no !`command` shell expansion, and no built-in argument injection. The string goes directly to the agent, unchanged.
If you need to embed a dynamic value in an inline prompt, construct the string in JavaScript:
promptArgs alongside an inline prompt is an error. The substitution system only works with prompt templates. If you find yourself needing promptArgs, switch to promptFile.
Prompt templates
When you usepromptFile, Sandcastle reads the file and processes it through two stages before sending it to the agent:
- Prompt argument substitution — replaces
{{KEY}}placeholders with values frompromptArgs(runs on the host) - Prompt expansion — evaluates
!`command`shell expressions (runs inside the sandbox)
Prompt argument substitution
Put{{KEY}} placeholders in your prompt file, then pass the values via promptArgs:
.sandcastle/prompt.md:
promptArgs accepts string, number, or boolean values. Substitution runs on the host before the sandbox starts.
Error and warning behavior:
- A
{{KEY}}placeholder with no matching entry inpromptArgsis an error — the run fails before the sandbox is created. - A
promptArgskey that is not referenced anywhere in the prompt produces a warning, but the run continues.
Built-in prompt arguments
Sandcastle automatically injects two arguments into every prompt template. You do not need to pass these inpromptArgs:
| Placeholder | Value |
|---|---|
{{SOURCE_BRANCH}} | The branch the agent works on (determined by the branch strategy) |
{{TARGET_BRANCH}} | The host’s active branch at run() time |
SOURCE_BRANCH or TARGET_BRANCH in promptArgs is an error — built-in prompt arguments cannot be overridden.
Shell expressions
Use!`command` in your prompt file to pull in dynamic context from inside the sandbox. Each expression is replaced with the command’s stdout before the prompt reaches the agent:
sandbox.onSandboxReady hooks complete, so they see the same environment the agent sees — including installed dependencies.
All expressions in a single prompt run in parallel for faster expansion. If any command exits with a non-zero code, the run fails immediately.
Substitution order
Prompt argument substitution always runs before shell expansion. This means you can embedpromptArgs values inside shell expressions:
{{ISSUE_NUMBER}} with its value first (on the host), then evaluates the shell expression inside the sandbox.
Example prompt template
Here is a complete prompt template that uses both features:Completion signals
By default, when the agent outputs<promise>COMPLETE</promise>, the iteration loop stops early. This signal is a convention — you document it in your prompt, and the agent outputs it when finished.
You can override the default signal using the completionSignal option:
result.completionSignal.