Prompts created in Braintrust can be called directly from your application code. Changes made in the UI immediately affect production behavior, enabling rapid iteration without redeployment.
Invoke a prompt
Use invoke() to call a deployed prompt by its slug:
import { invoke } from "braintrust";
const result = await invoke({
projectName: "My Project",
slug: "summarizer",
input: {
text: "Long text to summarize...",
},
});
console.log(result);
from braintrust import invoke
result = invoke(
project_name="My Project",
slug="summarizer",
input={"text": "Long text to summarize..."},
)
print(result)
The input parameter values map to template variables in your prompt. For example, {{text}} in your prompt gets replaced with the text value from input.
The Ruby SDK doesn’t support server-side invocation. Instead, load a prompt and build it locally, then call your own LLM client. See Build prompts locally.
Use within a trace
When calling prompts from instrumented code, they automatically nest within your parent trace:
import { initLogger, traced } from "braintrust";
const logger = initLogger({ projectName: "My Project" });
const summarize = traced(async (text: string) => {
return await logger.invoke("summarizer", { input: { text } });
});
// This creates a trace with "summarize" as parent
const result = await summarize("Long text to summarize...");
from braintrust import init_logger, traced
logger = init_logger(project_name="My Project")
@traced
async def summarize(text: str):
return await logger.invoke("summarizer", input={"text": text})
# This creates a trace with "summarize" as parent
result = await summarize("Long text to summarize...")
This creates a hierarchical trace where the prompt execution appears as a child span of your function.
When a prompt includes tools, the response contains tool calls that your code must handle:
import { invoke } from "braintrust";
const result = await invoke({
projectName: "RAG App",
slug: "document-search",
input: { question: "What is Braintrust?" },
});
// Handle tool calls
if (result.toolCalls) {
for (const toolCall of result.toolCalls) {
console.log(`Tool: ${toolCall.function.name}`);
console.log(`Arguments: ${toolCall.function.arguments}`);
// Execute tool and return results...
}
}
from braintrust import invoke
result = invoke(
project_name="RAG App",
slug="document-search",
input={"question": "What is Braintrust?"},
)
# Handle tool calls
if hasattr(result, "tool_calls"):
for tool_call in result.tool_calls:
print(f"Tool: {tool_call.function.name}")
print(f"Arguments: {tool_call.function.arguments}")
# Execute tool and return results...
See Deploy functions for details on deploying tools alongside prompts.
Version prompts
Every prompt save creates a new version with a unique ID. Pin specific versions in production code:
import { invoke } from "braintrust";
const result = await invoke({
projectName: "My Project",
slug: "summarizer",
version: "5878bd218351fb8e", // Pin to specific version
input: { text: "Long text to summarize..." },
});
from braintrust import invoke
result = invoke(
project_name="My Project",
slug="summarizer",
version="5878bd218351fb8e", # Pin to specific version
input={"text": "Long text to summarize..."},
)
require "braintrust"
prompt = Braintrust::Prompt.load(
project: "My Project",
slug: "summarizer",
version: "5878bd218351fb8e" # Pin to specific version
)
params = prompt.build(text: "Long text to summarize...")
Without a version parameter, invoke() and Braintrust::Prompt.load use the latest version.
Use environments
Environments separate dev, staging, and production configurations. Use loadPrompt() with the environment parameter to fetch the prompt version assigned to a specific environment:
import { loadPrompt } from "braintrust";
const prompt = await loadPrompt({
projectName: "My Project",
slug: "summarizer",
environment: "production",
});
const { messages, model, temperature } = prompt.build({
text: "Long text to summarize...",
});
// Use messages with your own LLM client
from braintrust import load_prompt
prompt = load_prompt(
project="My Project",
slug="summarizer",
environment="production",
)
result = prompt.build({"text": "Long text to summarize..."})
# Use messages with your own LLM client
See Manage environments for details.
invoke() does not accept an environment parameter. To execute an environment-pinned prompt server-side via invoke(), resolve the version with loadPrompt() first and pass it to invoke():const prompt = await loadPrompt({
projectName: "My Project",
slug: "summarizer",
environment: "production",
});
const result = await invoke({
projectName: "My Project",
slug: "summarizer",
version: prompt.version,
input: { text: "Long text to summarize..." },
});
This pins the call to a concrete version at resolve time. Re-call loadPrompt() if you need to pick up environment reassignments.
Build prompts locally
Use build() to compile a prompt’s template without making an API call. This is useful for testing or generating messages to pass to your own LLM client:
import { loadPrompt } from "braintrust";
const prompt = await loadPrompt({
projectName: "My Project",
slug: "summarizer",
});
const { messages, model, temperature } = prompt.build({
text: "Long text to summarize...",
});
console.log(messages);
// Use messages with your own LLM client
from braintrust import load_prompt
prompt = load_prompt(
project="My Project",
slug="summarizer",
)
result = prompt.build({"text": "Long text to summarize..."})
print(result["messages"])
# Use messages with your own LLM client
require "braintrust"
prompt = Braintrust::Prompt.load(
project: "My Project", # Or project_id: "your-project-uuid"
slug: "summarizer"
)
params = prompt.build(text: "Long text to summarize...")
puts params[:messages]
# Pass params to your own LLM client, e.g. openai.chat.completions.create(**params)
The build() method returns the compiled messages, model, and parameters without executing the prompt.
In Ruby, identify the project by name (project:) or by UUID (project_id:). Providing neither raises an ArgumentError. After loading, prompt.version returns the resolved version’s transaction ID, which you can pass to Braintrust::Prompt.load(version:) to re-pin the exact same version later.
Stream responses
Enable streaming to receive responses incrementally:
import { invoke } from "braintrust";
const stream = await invoke({
projectName: "My Project",
slug: "summarizer",
input: { text: "Long text to summarize..." },
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk);
}
from braintrust import invoke
stream = invoke(
project_name="My Project",
slug="summarizer",
input={"text": "Long text to summarize..."},
stream=True,
)
for chunk in stream:
print(chunk, end="")
Streaming works through the gateway and automatically logs the complete response to Braintrust.
Manage from the CLI
Use the bt CLI to browse and test deployed prompts without opening the UI.
Browse prompts:
bt prompts list # List all prompts in the active project
bt prompts view summarizer # View a specific prompt's definition
Test a deployed prompt:
Use bt functions invoke to call a prompt and see its output directly from the terminal:
bt functions invoke --slug summarizer --input '{"text": "Long text to summarize..."}'
Use the REST API
Call prompts directly via HTTP.
In the examples below, organizations on the EU data plane should replace api.braintrust.dev with api-eu.braintrust.dev.
curl https://api.braintrust.dev/v1/function \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BRAINTRUST_API_KEY" \
-d '{
"project_name": "My Project",
"slug": "summarizer",
"input": {
"text": "Long text to summarize..."
}
}'
The REST API supports all the same parameters as the SDK, including versioning, environments, and streaming.
Next steps