Prompt Flow gives you three built-in node types that cover the vast majority of generative AI application patterns:
| Node Type | Primary Purpose | Template Engine | Required Input |
|---|---|---|---|
| LLM NodeThe primary Prompt Flow node type for invoking a language model. Requires a connection, an API type (chat or completion), a deployment name, and a Jinja2 prompt template. Returns the model-generated text as its output. | Call an Azure OpenAI or OpenAI model to generate text | Jinja2 | prompt, model/deployment_name |
| Prompt NodeA Prompt Flow node that renders a Jinja2 template into a plain string. It does NOT call any model — it only builds the prompt text, which is then wired into an LLM node's prompt input. | Compose and render a reusable prompt template before it reaches an LLM | Jinja2 | prompt (Jinja template string) |
| Python NodeA Prompt Flow node that executes custom Python code. Must contain exactly one function decorated with @tool imported from promptflow. The function's parameters become bindable node inputs; its return value is the node output. | Run arbitrary Python code for data transformation, API calls, or business logic | Python 3.x | code (decorated function) |
Understanding when to use a Prompt node versus an LLM node is a common exam trap. A Prompt node only renders a Jinja template into a string — it does not call any model. Wire the Prompt node's output into an LLM node's prompt input when you want to separate template authoring from model invocation.
LLM Node — Required Configuration
When you add an LLM node you must configure:
- Connection — an Azure OpenAI connection from your project's connected resources (e.g.,
Default_AzureOpenAI) - API type —
chat(chat completions endpoint, preferred for GPT-3.5-Turbo, GPT-4) orcompletion(legacy text completions) - Deployment name — the deployment identifier you set when you deployed the model
- Prompt — a Jinja template string following the system/user/assistant message structure for chat API
LLM Node — Key Optional Parameters
| Parameter | Type | Default | Effect |
|---|---|---|---|
temperature | float | 1.0 | Higher = more random; lower = more deterministic |
max_tokens | integer | inf (chat) / 16 (completion) | Upper bound on generated tokens |
top_p | float | 1.0 | Nucleus sampling probability mass |
presence_penalty | float | 0.0 | Penalizes tokens that have already appeared; encourages new topics |
frequency_penalty | float | 0.0 | Penalizes repeated tokens; reduces verbosity |
stop | list | null | Token sequences that halt generation |
The
max_tokensdefault differs by API type:inffor chat,16for completion — a common exam trap.
Prompt Node — Jinja Templating
Variables in Jinja templates use {{ variable_name }} syntax. Conditional logic uses {% if %} / {% else %} / {% endif %} blocks. Loops use {% for item in list %} blocks:
{% for item in chat_history %}
user: {{ item.inputs.question }}
assistant: {{ item.outputs.answer }}
{% endfor %}
user: {{ question }}
The Prompt node's only output is a single rendered string. Wire it into an LLM node's prompt input.
Python Node — Four Requirements
- All imports must be at the top of the snippet
- Exactly one function decorated with the @tool decoratorThe required entry-point marker for Python node functions in Prompt Flow. Imported from promptflow and applied to exactly one function per snippet. Without this decorator, the function is not recognized as the node entry point. — the entry point
- The
@toolfunction must have a return statement — the return value is the node's output - Function parameters are automatically exposed as node Inputs (type annotations enable proper type selectors)
from promptflow import tool
@tool
def process_response(llm_output: str, max_length: int) -> str:
return llm_output.strip()[:max_length]
For authenticated external services, declare a CustomConnection parameter:
from promptflow import tool
from promptflow.connections import CustomConnection
@tool
def call_external_api(query: str, conn: CustomConnection) -> str:
api_key = conn.api_key
# ... call external service ...
return result
Wiring Nodes Together
Link nodes by referencing one node's output in another node's input:
${<node_name>.output}— entire output${<node_name>.output.<field_name>}— a specific field of a structured output
The graph view automatically draws directed edges based on these references. Execution order is determined by dependencies, not declaration order.
Goal: Add and configure an LLM node, a Python node, and a Prompt template node in a Prompt Flow graph, and wire them together.
Step 1 — Add a Prompt node. In your open flow, select + Prompt in the node toolbar. Name the node (e.g., build_system_prompt). In the prompt editor, write a Jinja template that incorporates dynamic variables such as {{user_topic}}. Select Validate and parse input — the portal creates an input field for user_topic. Bind user_topic to a flow input using the dropdown.
Step 2 — Add an LLM node. Select + LLM in the toolbar. Name the node (e.g., generate_answer). In the Connection dropdown, select your Azure OpenAI connection (e.g., Default_AzureOpenAI). In the Api dropdown, select chat. In the deployment_name dropdown, select your deployed model (e.g., gpt-4o).
Step 3 — Write the LLM prompt and parse inputs. In the prompt text area, write a Jinja template referencing {{system_prompt}} and {{question}}. Select Validate and parse input. The portal surfaces system_prompt and question as input fields. Bind system_prompt to ${build_system_prompt.output} (the Prompt node) and question to ${inputs.question} (the flow input).
Step 4 — Configure LLM parameters. Expand the Parameters section of the LLM node. Set temperature to 0.7 for balanced creativity. Set max_tokens to 800 to cap response length. Leave other parameters at defaults unless the scenario requires specific tuning.
Step 5 — Add a Python node for post-processing. Select + Python. Name it format_output. In the code editor, write a @tool-decorated function that accepts the LLM output string and returns a cleaned version. Select Validate and parse input. Bind the function's input parameter to ${generate_answer.output}.
Step 6 — Set the flow output. In the Outputs section, set the output value to ${format_output.output} to make the Python node's result the final flow response.
Step 7 — Run and verify the graph. Select Run (top-right). After completion, select View outputs. Confirm each node shows green status and the final output contains the expected formatted response. Use the Trace tab to inspect per-node token usage and latency.
AI-3016 Assessment Focus
Prompt vs. LLM node confusion and Python node @tool decorator rules are the most frequently tested traps. Also know the max_tokens default difference between chat and completion APIs.
Exam Trap
"The Prompt node calls the language model and returns the AI response." The Prompt node only renders a Jinja template into a string. It does not call any model. You must wire its output into an LLM node to get an AI-generated response.
Exam Trap
"For the chat API, max_tokens defaults to 16." The max_tokens default of 16 applies to the completion API. For the chat API, max_tokens defaults to inf (no limit).
Exam Trap
"You can have multiple @tool decorated functions in a single Python node." Each Python node must have exactly one @tool-decorated function. Multiple @tool decorators in the same snippet will cause an error.
Exam Trap
"The @tool decorator is optional if you name your function 'main'." The @tool decorator is required and must be imported from promptflow. There is no convention-based entry point.
Exam Trap
"temperature=0 and top_p=0 should both be set for fully deterministic output." Microsoft recommends changing one of these parameters at a time. Setting both to extreme values simultaneously can produce unexpected behavior.
Exam Tip
After writing a Jinja template or Python function, always select Validate and parse input — this step is required to surface template variables and function parameters as bindable node inputs in the portal.
Must Memorize
Prompt node → string only (no model call). LLM node → model call, returns AI text. Python node → requires @tool on exactly one function with a return statement.
Question — click to flip
Q: What is the primary difference between a Prompt node and an LLM node in Prompt Flow?
Question — click to flip
Q: What is the default value of max_tokens for an LLM node configured with the chat API?
Question — click to flip
Q: What are the four requirements for valid Python node code in Prompt Flow?
Question — click to flip
Q: You have a Python node named 'extract_entities' returning a dict. How do you reference only the 'names' field downstream?
Question — click to flip
Q: For maximum determinism in an LLM classification task, which parameter should you adjust first?
Question — click to flip
Q: What does the 'Validate and parse input' button do after you write a Jinja template or Python function?