Functions in a flow — the model asks, your code runs
Define a function on a model node, read the call the model asks for, and continue the conversation with a new run.
4 min read
A function is a tool your code runs. The model node describes it to the model; when the model asks for it, the run answers with the call — the name of the function and its arguments — and your code runs the function and sends the result in the next run. This page shows that round from the settings to the second request.
Why the round is outside the flow
A flow runs forward: no connection may lead back to a node that already ran. A flow therefore makes the call of the model once, and the round «model → function → model» is made by your code — one run asks, your code answers, the next run continues. A model node does not run a function by itself.
Define a function
In the Tools section of the AI Model node press Add a function, then fill in:
the name — Latin letters, digits,
_and-, up to 64 characters, unique in the node;the description — what the function does and when to call it; the model reads it;
the arguments — a JSON Schema of an object (
"type": "object"), at most 16 KB;Strict arguments — whether the model has to keep to the schema exactly.
Tool choice says whether the model must use a tool: by default the model decides; it can also be asked always to use one, never to use one, or always to call one function. In the settings the function is:
{
"type": "function",
"name": "get_weather",
"description": "The current weather in a city",
"parameters": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] },
"strict": true
}Every model of the catalogue takes functions. Gemini 2.5 takes them only without a built-in tool beside them — Tools.
Wire the port
An answer that asks for a function leaves the node through Function call. Connect it to Return Response: the run then answers the caller with the call. Without a connection such an answer leaves through Success, like any other, and the check of the flow warns about a node with functions and no such connection (tool_calls_port_not_connected).
The template Function through the caller is this flow ready to publish — AI flow templates.
- Request — Default → AI Model
- AI Model — Success → Return Response
- AI Model — Function call → Return Response
Read the call
The output of the node has finish_reason tool_calls, and tool_calls lists the functions the model asked for — in one shape for every provider:
{
"model": "gpt-4o-mini",
"content": null,
"finish_reason": "tool_calls",
"tool_calls": [
{ "id": "call_8fz2", "name": "get_weather", "arguments": { "city": "Kyiv" }, "arguments_json": "{\"city\":\"Kyiv\"}" }
]
}idnames the call; your answer refers to it. A provider that gives a call no id gets one from Slen.argumentsis the parsed object, andarguments_jsonthe text as the provider sent it. When that text is not valid JSON,argumentsisnulland the text is still there.The call of the model that asked is paid like any other call: its input and output. A function costs nothing at the provider.
Continue with a new run
Run the function, then send a new request to the same operation. Its input.messages carries the conversation so far: the messages you sent, the answer of the model with its call, and a message with role tool that holds the result under the id of the call. Slen translates that history into the form of the provider of the model.
{
"operation": "weather_assistant",
"input": {
"messages": [
{ "role": "user", "content": "What is the weather in Kyiv?" },
{ "role": "assistant", "content": null, "tool_calls": [{ "id": "call_8fz2", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"Kyiv\"}" } }] },
{ "role": "tool", "tool_call_id": "call_8fz2", "content": "{\"temperature_c\": 12, \"sky\": \"cloudy\"}" }
]
}
}Over HTTP the request is POST /v1/operations/execute with that body and an idempotency key of its own:
curl https://api.slen.ai/v1/operations/execute \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Idempotency-Key: weather-42:round-2" \
-H "Content-Type: application/json" \
-d @next-round.jsonFrom an SDK it is the same operations.execute() as the first request, with these messages in the input — Send a request. The second run answers with text through Success, or asks for another function.
Where to go next
Tools — built-in tools, their prices and what bounds a call.
AI Model — the ports and the output of the node.
Return Response — what the run answers with.
Send a request — the request to a flow from your application.