Prompts & Messages
Build Prompt and Message objects with Jinja templating, send images and files with VisionMessage, and attach tools and response schemas.
A Prompt is an ordered list of messages plus optional tool definitions and a response schema. Message content is a Jinja template, so the same prompt object serves every request — you pass the variables as input_data at run time. Everything on this page is imported from dynamiq.prompts.
Messages and roles
A Message has content and a role — one of user, system, assistant, or tool (the MessageRole enum, plain strings also work):
from dynamiq.prompts import Message, MessageRole, Prompt
prompt = Prompt(
messages=[
Message(role=MessageRole.SYSTEM, content="You are a concise technical writer."),
Message(role=MessageRole.USER, content="Explain {{topic}} to a {{audience}}."),
]
)Assistant messages can carry tool_calls, and tool messages take tool_call_id and name, following the OpenAI function-calling protocol — you only need these when replaying a tool-use conversation manually.
Jinja templating
{{variable}} placeholders are rendered with the keyword arguments you pass at execution time. The LLM node validates inputs against the template, so a missing variable fails fast with the expected parameter names:
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.nodes.llms import OpenAI
from dynamiq.prompts import Message, Prompt
prompt = Prompt(
messages=[Message(role="user", content="Explain {{topic}} to a {{audience}}.")]
)
print(prompt.get_required_parameters()) # {'topic', 'audience'}
llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o-mini", prompt=prompt)
result = llm.run(input_data={"topic": "vector search", "audience": "PM"})
print(result.output["content"])Anything Jinja supports works inside content — conditionals, loops, filters:
from dynamiq.prompts import Message, Prompt
prompt = Prompt(
messages=[
Message(
role="user",
content=(
"Answer using only these documents:\n"
"{% for doc in documents %}- {{ doc }}\n{% endfor %}"
"Question: {{question}}"
),
)
]
)Set static=True on a message to skip template rendering entirely — useful when the content legitimately contains {{ }} sequences (code samples, user-provided text) that must not be interpreted:
from dynamiq.prompts import Message
raw = Message(role="system", content="Literal braces: {{not_a_variable}}", static=True)Utilities
prompt.get_required_parameters()returns the set of variables across all non-static messages.prompt.count_tokens(model="gpt-4o-mini")counts prompt tokens for a given model.
Vision inputs
To send images or files, use a VisionMessage whose content is a list of typed parts: VisionMessageTextContent, VisionMessageImageContent, and VisionMessageFileContent. Image URLs are templates too, and they accept more than strings — if the rendered variable is bytes or io.BytesIO, Dynamiq detects the file type and converts it to a base64 data URL automatically.
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.nodes.llms import OpenAI
from dynamiq.prompts import (
Prompt,
VisionMessage,
VisionMessageImageContent,
VisionMessageImageURL,
VisionMessageTextContent,
)
prompt = Prompt(
messages=[
VisionMessage(
role="user",
content=[
VisionMessageTextContent(text="{{user_message}}"),
VisionMessageImageContent(
image_url=VisionMessageImageURL(url="{{img_url}}")
),
],
)
]
)
llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o-mini", prompt=prompt)
result = llm.run(
input_data={
"user_message": "What is in this image?",
"img_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
}
)
print(result.output["content"])import io
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.nodes.llms import OpenAI
from dynamiq.prompts import Prompt, VisionMessage, VisionMessageImageContent
with open("photo.jpg", "rb") as f:
image = io.BytesIO(f.read())
prompt = Prompt(
messages=[
VisionMessage(
content=[VisionMessageImageContent(image_url={"url": "{{image}}"})]
)
]
)
llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o-mini")
# Bytes / BytesIO inputs are base64-encoded into a data URL automatically.
result = llm.run(input_data={"image": image}, prompt=prompt)
print(result.output["content"])VisionMessageImageURL also takes a detail level (auto, high, or low) for providers that support it. For non-image documents such as PDFs, use VisionMessageFileContent with file.file_data set to a base64 data URL (bytes variables are converted the same way); check llm.is_pdf_input_supported first — see LLM Providers.
If a VisionMessage ends up containing only a single text part after rendering, it is sent as a plain text message — so a prompt with optional image inputs degrades gracefully.
Tools and response format
A Prompt can carry function-calling tools and a structured-output response_format alongside its messages. Values set directly on the LLM node take precedence over the prompt's:
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.nodes.llms import OpenAI
from dynamiq.prompts import Message, Prompt
prompt = Prompt(
messages=[Message(role="user", content="Extract the city from: {{text}}")],
response_format={
"type": "json_schema",
"json_schema": {
"name": "city_extraction",
"schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
},
},
)
llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o-mini", prompt=prompt)
result = llm.run(input_data={"text": "Our office in Milan opens at 9."})
print(result.output["content"]) # {"city": "Milan"}When the model calls a tool instead of answering, the node output includes tool_calls with each call's function name and JSON-parsed arguments.
Per-call prompts
The prompt attached to the node is just a default. run() and execute() accept a prompt= argument, so one configured node can serve many prompts:
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.nodes.llms import OpenAI
from dynamiq.prompts import Message, Prompt
llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o-mini")
summarize = Prompt(messages=[Message(role="user", content="Summarize: {{text}}")])
translate = Prompt(messages=[Message(role="user", content="Translate to French: {{text}}")])
print(llm.run(input_data={"text": "Dynamiq is an orchestration framework."}, prompt=summarize).output["content"])
print(llm.run(input_data={"text": "Good morning"}, prompt=translate).output["content"])Next steps
LLM Providers
One unified LLM node across 27 providers — provider table, connection env vars, common parameters, vision and PDF support, and fallbacks.
Tracing to Dynamiq
Send traces from open-source SDK workflows to the Dynamiq platform with DynamiqTracingCallbackHandler and view them under Gateway → Tracing.