LLM steps (AGENT)
An AGENT step runs an LLM with a system prompt, a user prompt, optional tools, and optional multi-turn behavior. Use it whenever you need summarization, classification, routing decisions, or natural-language output—while keeping deterministic work in CALL steps.
Prompt-heavy agents are easiest to iterate via MCP; see Vibe coding.
Model sizes
model_type | When to use it |
|---|---|
small | Structured extraction, tagging, short summaries, JSON you will parse downstream. |
large | Multi-input reasoning, long narratives, nuanced recommendations. |
CALL steps vs tools on LLM steps
FunnelStory has a shared catalog of functions — semantic.query, slack.send_message, email.send, tasks.create, CRM read/update, dataset operations, web search, and more. The difference is who decides when to call them:
- CALL steps let you (the flow author) invoke any function in the catalog with arguments you control. You decide which step runs the function and what values go in.
- Tools on an AGENT step let the model invoke functions during the step. Only functions the product exposes as agent tools can be attached — currently a smaller set than the full CALL catalog.
Functions not in the agent-tool list remain available in ordinary CALL steps. See Functions reference for the full catalog.
Available agent tools
These functions can be attached as tools on an AGENT step today:
semantic.queryemail.sendslack.send_messagetasks.create
Each tool entry maps a name (what the model sees) to a function_id (what actually runs):
{
"tools": [
{
"name": "query_workspace",
"function_id": "semantic.query"
}
]
}
Fixed arguments
For each tool, you can lock specific arguments so the model cannot choose them. Fixed keys are merged at runtime and hidden from the model's view of the tool schema — the model only sees the remaining parameters it is allowed to fill in.
Use fixed arguments to narrow scope: force a specific connection, pin a Slack channel, or constrain part of a query.
{
"tools": [
{
"name": "post_to_slack",
"function_id": "slack.send_message",
"fixed_args": {
"connection_id": "slack_conn_123",
"channel_id": "C01234567"
}
}
]
}
In this example the model can only choose the message content; connection and channel are locked by the flow author.
Prompting for JSON
When downstream steps parse JSON, add explicit instructions — for example: "Output ONLY raw JSON, no markdown, no backticks." to the system prompt.
Threads, memory, and multi-turn (advanced)
These are optional add-ons for specialized flows. Most agents do not need them.
| Field | Purpose |
|---|---|
thread_id | Optional stable id so repeated runs can restore prior LLM context. |
variable_store | When true, exposes persistent key-value storage tools (variable_get, variable_set, variable_push, variable_pop, variable_clear) for scratchpad memory inside the step. |
multi_turn | When true, allows the agent to pause execution and wait for external input before continuing (uses the signal tool path). |
Details on these capabilities belong in the flow authoring guide.
Chat responses
For agents you talk to in the product Chat experience, the final AGENT step should write its user-visible text to the global @.response variable ("out": { "set": "@.response" }). If you skip this, the thread may complete without showing a reply.
Example
{
"id": "analyze",
"op": "AGENT",
"next": "",
"out": { "set": "@.analysis" },
"agent": {
"model_type": "small",
"system": "You are an analyst. Output ONLY raw JSON, no markdown, no backticks.",
"user": "Classify renewal risk for this payload:\n{{ $.account_payload }}",
"tools": [
{ "name": "query_semantic_db", "function_id": "semantic.query" }
]
}
}
Related
- Flow authoring guide — full JSON reference for
agentblocks - Operations
- Functions reference
- Testing and runs