Variable Substitution
Inject runtime values into tool parameter schemas using Mustache placeholders.
Variable Substitution
Tool schemas can contain {{placeholder}} markers that are resolved at compile time. This lets you store a single parameterised tool definition and inject environment-specific or request-specific values when fetching the tool.
How It Works
The compile() method on the tool returned by Tool.get() accepts two maps:
| Map | Purpose |
|---|---|
strings | Inline string substitution — values are rendered into surrounding text |
objects | Typed value injection — replaces a sole {{placeholder}} with any JSON value (object, array, number, etc.) |
The substitution rules differ depending on whether the placeholder is the entire string or embedded within text:
Sole placeholder — the entire string value is "{{key}}" (whitespace-tolerant):
- Checks
objectsfirst; injects the typed value as-is (object, number, boolean, etc.) - Falls back to
stringsif the key is absent fromobjects - Returns
''if the key is in neither map
Inline placeholder — {{key}} embedded within other text, e.g. "Search in {{region}}":
- Rendered with Mustache using the
stringsmap only objectsvalues have no effect on inline placeholders
Arrays and nested objects are traversed recursively, so placeholders anywhere in the parameters schema are resolved.
Examples
String substitution
const result = await tools.get('search_web');
const compiled = result.compile({
strings: { defaultRegion: 'us-east-1' },
});
// Replaces "{{defaultRegion}}" in any description string with "us-east-1"Object injection
const compiled = result.compile({
objects: { extraParams: { timeout: 30, retries: 3 } },
});
// Replaces a sole "{{extraParams}}" value with the full objectCombined
const compiled = result.compile({
strings: { category: 'electronics' },
objects: { priceRange: { min: 0, max: 500 } },
});
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Find laptops.' }],
tools: [compiled as any],
tool_choice: 'auto',
});Key conflict: same key in both maps
When the same key appears in both maps, objects wins for a sole placeholder and strings wins for an inline placeholder:
// Sole placeholder → objects wins
result.compile({
strings: { input: 'Browserstack' },
objects: { input: { name: 'Browserstack' } },
});
// "{{input}}" → { name: "Browserstack" }
// Inline placeholder → strings wins
result.compile({
strings: { input: 'Browserstack' },
objects: { input: { name: 'Browserstack' } },
});
// "Hello {{input}}" → "Hello Browserstack"Missing key
result.compile({});
// "{{missing}}" → ""
// "Hello {{missing}}" → "Hello "Compiling a ToolList
When a prompt has tools attached, compile all tools with shared variables in one call:
import { AISDK, Prompt } from '@browserstack/ai-sdk';
const prompt = await Prompt.get('agent-prompt');
const compiledTools = prompt.tools.compile({
strings: { env: 'production' },
objects: { config: { timeout: 30 } },
});String substitution
from browserstack_ai_sdk import Tool
tool = Tool.get("search_products", provider="openai")
compiled = tool.compile(
strings={"category": "electronics"},
)
# Replaces "{{category}}" in any description stringObject injection
compiled = tool.compile(
objects={"price_range": {"min": 0, "max": 500}},
)
# Replaces a sole "{{price_range}}" value with the full dictCombined
import openai
compiled = tool.compile(
strings={"category": "electronics"},
objects={"price_range": {"min": 0, "max": 500}},
)
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Find me a good laptop."}],
tools=[compiled],
tool_choice="auto",
)Key conflict: same key in both maps
When the same key appears in both maps, objects wins for a sole placeholder and strings wins for an inline placeholder:
# Sole placeholder → objects wins
tool.compile(
strings={"input": "Browserstack"},
objects={"input": {"name": "Browserstack"}},
)
# "{{input}}" → {"name": "Browserstack"}
# Inline placeholder → strings wins
tool.compile(
strings={"input": "Browserstack"},
objects={"input": {"name": "Browserstack"}},
)
# "Hello {{input}}" → "Hello Browserstack"Missing key
tool.compile()
# "{{missing}}" → ""
# "Hello {{missing}}" → "Hello "Compiling a ToolList
When a prompt has tools attached, compile all tools with shared variables in one call:
from browserstack_ai_sdk import Prompt
prompt = Prompt.get("agent-prompt", type="chat")
compiled_tools = prompt.tools.compile(
strings={"env": "production"},
objects={"config": {"timeout": 30}},
)Tool Schema with Placeholders
A stored tool schema might look like this:
{
"name": "search_products",
"description": "Search for {{category}} products in {{region}}.",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string" },
"priceRange": "{{price_range}}",
"maxResults": { "type": "integer", "default": 10 }
},
"required": ["query"]
}
}At compile time:
"{{category}}"and"{{region}}"(inline) → resolved fromstrings"{{price_range}}"(sole) → replaced with the full object fromobjects