Skip to main content

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.

Build with AI

Prompt-heavy agents are easiest to iterate via MCP; see Vibe coding.

Model sizes

model_typeWhen to use it
smallStructured extraction, tagging, short summaries, JSON you will parse downstream.
largeMulti-input reasoning, long narratives, nuanced recommendations.

CALL steps vs tools on LLM steps

FunnelStory has a shared catalog of functionssemantic.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.query
  • email.send
  • slack.send_message
  • tasks.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.

FieldPurpose
thread_idOptional stable id so repeated runs can restore prior LLM context.
variable_storeWhen true, exposes persistent key-value storage tools (variable_get, variable_set, variable_push, variable_pop, variable_clear) for scratchpad memory inside the step.
multi_turnWhen 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" }
]
}
}