Skip to content

Workflows

A workflow is a named, saved automation for one of your agents: its steps run in a fixed order, though some of them may run at the same time instead, as a parallel group (see Parallel groups below). Unlike a chat — where the agent decides what to do turn by turn — a workflow runs the same multi-step process every time, so it's the right tool for anything repeatable: pull data on a schedule, process it, and send a report; watch a source and notify a channel; run a recurring back-office task unattended.

An agent can have many workflows, each with its own steps — and everyone who runs one can give it a schedule of their own (see Personal schedules and webhooks). The Workflows tab lists them all, with a step count, your schedule, and the status of your last run for each. A schedule that will not fire is crossed out and labelled with the reason — Off when the schedule is switched off, Not running when the workflow is not ready to run — so the list never advertises a run that isn't coming.

What you can build

Each workflow is a series of steps, and the Builder picks a kind for each one — an exact, predictable step wherever the work is exact, a reasoning step only where the work needs judgment. The step types are:

  • Transform step — a pass through a model that turns loose input into a fixed set of fields: pull the address out of an order email, sort a ticket into a category, score a lead. It has no tools and looks nothing up, so it's the quick, predictable choice whenever a step comes down to "read this and give these fields back".
  • Agent step — a reasoning step that can use tools and take several turns to reach an answer. It gets only what the Builder gave it — the agent's own tools, its knowledge, its skills, a connected integration; see What an Agent step can be given below. Its tools aren't limited to looking things up: an agent step can call anything it was given, including a tool that makes a change — write a file, post a comment, approve a request, create a record. Google Workspace counts: a step can read a calendar, a sheet or a doc, and — when the agent's Google access allows it — write one. The mailbox connected for the agent counts too: a step can read and search that mail, and reply, send or forward from it, including files. See The connected mailbox. The Builder reaches for it when a step needs judgment or has to go looking: research a topic, work out why a number looks off, follow a trail across sources. It runs inside its own limits, so it stops instead of drifting (see Limits below).
  • Agent call — runs one agent all the way through: this workflow's own agent, or an agent connected to it. The step comes back with one piece of text the next step can use. See Calling an agent.
  • Action step — a single call to one thing the agent is connected to: create the Notion page, fetch the issue list, file the record. No model runs — the step makes exactly that one call, with the values handed to it.
  • Database write step — writes rows into the agent's database, each value landing in a named column. The table has to exist first; if there isn't one, ask the Builder to design it before wiring up the write. The step matches rows on a key, so running the workflow again updates what it wrote last time instead of piling up duplicates. For a member of a team with a shared team database, the step's Database setting can target either the agent's own database or the team's shared one. Labeled Database write in the UI.
  • Script step — runs code when you need exact, deterministic logic. It reads and writes the agent's own database through a db_query(sql, params) helper, and, for a team member with a shared team database, a second team_db_query(sql, params) helper alongside it.
  • Notify step — sends the result out over webhook, email, or Telegram, using a message template. Email goes out from the platform mailbox with no setup on your side; fill in the SMTP fields only if you want it sent from your own mail server. That is one prepared message, sent the same way every run. It is not the mailbox connected in Integrations — an Agent step uses that one, see The connected mailbox.
  • Condition step — branches the flow based on an expression.
  • Agent (legacy) step — the older LLM step: a full agent loop through a model (with its own model, temperature, and length settings). Workflows built before the step types above still use it and keep working as they are; new ones the Builder writes use Transform and Agent instead. Labeled Agent (legacy) in the UI.
  • Parallel group — not a kind of step on its own, but a way to run several steps of any of the kinds above at the same time instead of one after another. See Parallel groups below for how a group's success is decided.

Steps can pass results forward — a later step can reference an earlier step's output — and workflows support variables ({{like_this}}) so the same workflow can be reused with different inputs. Transform and Agent steps declare up front what shape their answer has — which fields, and of what kind — which is why a later step can take one field out of the result instead of the whole thing as a block of text. Open a step from the diagram to see the input it takes and the output it declares.

Configuration. The settings a workflow needs appear in its Configuration form, and a field there is one of two kinds:

  • A field that comes from one of the agent's integrations — a Telegram chat ID, a mailbox, an MCP server's key, a variable from the agent's Environment — is shown, never typed into. Its caption says where the value comes from, such as From your Telegram connection or From this agent's variables, secrets stay masked, and every run takes the value its source holds at that moment. For an integration, that is the connection of the person the run acts as (see Whose run it is): their own for an integration each user connects, the owner's for one the owner shares. When there is nothing to show, the field says who can fix it — Not connected — connect it in the agent's setup window when it is yours to connect, or that the agent's owner has to connect it.
  • A field of the workflow's own — how many items, which recipients — is filled in by hand, and every person who runs the workflow keeps their own value in it.

Secrets, API keys, and values that come from an integration are always required: the Builder marks them so, and a run doesn't start until each of them has a value. Fill in the workflow's own fields in the form; for the rest, connect the integration. A value someone typed by hand into a field that comes from an integration, back when such fields could still be typed into, is kept, so nothing changes under anyone: the field shows it with Set by hand earlier and a Use the connection's value button, which clears it and hands the field back to the connection.

Calling an agent

A step can call the agent this workflow belongs to, an agent you have connected to it, or a member of its team, and wait until that call finishes. Team membership is enough; you do not need to add a second connection. What comes back is one piece of text, and the next step can use it the same way it uses any earlier step's result.

For work with shared team records, the Builder selects the team for each agent call. That call uses the selected team's shared database and memory. When specialists belong to several teams, the workflow must identify which team's work they are doing. Removing an agent from the selected team stops the call rather than switching it to another team.

For example, an SMM workflow can pass a campaign from a Strategist to a Copywriter, then a Designer and a Publisher. Each receives the previous result or the campaign's saved records, so you do not copy answers between agents. Publishing still requires a working integration with the destination and a configured trigger for the workflow.

The Builder prepares and connects the specialists a workflow needs before building it. It uses each specialist's description, delegation instructions, tools, skills and knowledge to decide which work belongs to it, what to send and what result to expect. If that role is unclear, the Builder asks for the missing detail.

If a required specialist is still being built, its workflow waits while independent work can continue. A failed build, paused agent or missing configuration must be fixed first; the Builder reports what is blocking the workflow. Unrelated agents that are still building do not hold it up. A workflow can call its own agent once that agent's instructions are configured, without waiting for the whole build to finish. The same readiness check applies when saving a new workflow or changing its steps. Each person's integration connections are still checked when they run it.

Every step of that run shares one scratch folder and one scratch memory. A file or a note written during the run is there for the later steps of the same run, and a retry keeps the same folder. The agent's permanent files stay as they are, and so does its lasting memory — nothing this run writes is kept as the agent's own.

A retry runs the step again. If it did something outside the run, such as posting a message, doing it again can do that again.

Parallel groups

A parallel group is a set of steps that all start together and run at the same time, instead of the workflow waiting for one to finish before starting the next. The Builder decides which steps belong in a group — usually steps whose work doesn't depend on each other's results, like researching three unrelated topics or checking three different sources at once. Any step type can be part of a group: a Transform step, an Agent step, an Action step, whatever the work calls for. In the workflow diagram, a group shows as its own block you can expand to see the steps inside.

How success is decided. A group has more than one step, so "did the group work" needs its own rule — that's the group's success policy, and it's one of three:

  • All steps succeed — the group only counts as a success if none of its steps failed.
  • At least one step succeeds — one clean result out of the group is enough, even if the rest failed.
  • At least N steps succeed — you pick the number; the group counts as a success once that many steps came back clean, regardless of the rest.

What you see on partial success. Open a run that included a group and you'll see a verdict sentence such as "3 of 4 steps succeeded — enough, the policy needs at least 2." — it says how many steps actually succeeded and whether that was enough for the policy. The policy it names is the one that run actually applied, which is your own rule if you had set one (see Changing the policy below). A run that kept no record of its policy shows only how many steps succeeded. With no run on the diagram, each group names the policy the next run will use. Each step inside the group also keeps its own status in run history, same as any other step, so you can tell exactly which one failed even when the group as a whole met its policy.

Failed steps inside a met group aren't repaired. When a group's policy is met, the run carries on as though the group succeeded — even though one or more of its steps genuinely failed. Self-healing doesn't touch those failed steps, because nothing about the run looks broken to it: the policy was satisfied, so there's nothing flagged to fix. Worth remembering: a step that's actually broken — a connection that stopped working, a source that changed shape — can keep failing run after run without ever triggering a repair, as long as the rest of the group keeps meeting the policy.

Changing the policy. The Builder sets each group's policy when it writes the workflow. You can set your own rule instead: open the workflow's Configuration card, press Edit, and under Group of parallel steps choose when a group succeeds — "all steps succeed", "at least one step succeeds", or "at least N steps succeed" — then press Save. It is one rule for every parallel group of the workflow, and it applies from the next run. The card shows this setting only when the workflow has at least one parallel group, and it offers only the numbers that fit every group. The Builder's option — marked "(Builder)", or "as set by the Builder" when the Builder gave the groups different policies — hands the decision back to the Builder, and each group again uses the policy the Builder gave it. If your groups were set to different rules earlier, the card shows "different per group" until you choose one.

What a step can reach

Open a step and the Side effects panel lists what it can reach outside itself: the tools an AI step may call, whether a code step reads or writes your agent's database, and which table a database-write step writes to. The list is read from the step's own settings, so it is never out of date — change the settings and the list changes with them. A step with nothing listed simply made none of those choices — though a code step can always call external APIs over the internet, regardless of what's listed for it. The one exception: on a very old workflow, the panel may say the step's details aren't available instead of showing a list, and there the list can't be trusted at all.

A step that can make a change — not just look something up — carries a small writes tag directly on it in the workflow diagram, so you can spot which steps can write without opening each one. That covers an Agent step whose tools include one that writes, and an Action step whose one call writes. Open an Agent or Action step like that and its panel also says Can write through its connected tools, so you know at a glance which steps only read and which can act.

Once a run has finished, its record shows not just what a step could do but what it did, for Agent and Action steps alike. In the run history, a step that actually called one of those writing tools carries a Side effects used count, and hovering it lists the tools it called. Open that step and its detail keeps the two apart: Allowed in this run is what the step was permitted to do, Used in this run is what it actually called — so a step that could have written and chose not to reads differently from one that wrote.

Some tools in those two lists carry a further word after write. overwrites means the call replaces something that was already there — a spreadsheet range, an event's details — rather than adding beside it. seen outside the company means the result reaches people outside your company: a calendar event appears on its attendees' own calendars, whoever they are. Both are shown, never blocked — a workflow is allowed to do what the agent can do, and the words are there so you can see which steps do it. You don't have to wait for a run to see them: a step that may overwrite existing data or make something visible outside the company says so in its panel's Side effects list with the same overwrites or seen outside the company, before the workflow has ever run.

The step panel can show three more words, about how a tool reaches beyond the run rather than what it changes — so they can appear on a tool that only reads. reaches the internet means the call goes out to the web: a search, a page fetch, a browser. runs code means the call runs a program in a sandbox, such as a skill's own script. controls a browser means the call drives a browser paired with a person's account. Like the other two, they are shown and never blocked.

What an Agent step can be given

An Agent step gets only what the Builder gave it — nothing else of the agent comes along. The Builder asks for as little as the step needs, and the step's panel lists all of it. What it can give:

  • The agent's own tools — reading and writing files in the agent's working folder (the same folder code steps use), web search and reading web pages, the browser you've paired, and looking at images the run produced. Web search and reading web pages spend credits, charged to the same balance as the rest of the run, and aren't offered on an installation that has no web search.
  • Knowledge — a collection from the agent's documents, to search it or read a document from it. The step searches only the collections it was given. It can also be someone's task files: on an agent that keeps each conversation's files apart, the files a person attached to one of their conversations.
  • Skills — one of the agent's skills: its instructions, its files and, for a skill that ships scripts, running those scripts. A skill that connects to an external account through Authorize can't run its scripts in a workflow yet; its instructions and files can still be given.
  • Integrations — operations of a connected MCP server, of Google Workspace, or of the mailbox connected for the agent. An integration works on the connection of the person the run acts as — see Whose run it is. For the mailbox, see The connected mailbox.

A step keeps every tool the Builder gave it. The switches in the agent's Tools settings decide what the agent may use in a chat; a step keeps its tools even when one is switched off there. To take a tool away from a step, ask the Builder to change the step. The Agent (legacy) step is the exception: it runs the chat agent itself, with the tools switched on in the agent's Tools settings.

Task files and the browser. Every run acts as one person (see Whose run it is), but task files and a paired browser go further: a step can use them only when that person started the run themselves — by pressing Run, or through their own schedule. A run started by a webhook or by the agent from a chat can't read anyone's task files or drive anyone's browser, even though it acts as a person for everything else; and a step never reads one person's task files in another person's run. Collections from the agent's documents, and everything else above, work in every run.

On the diagram, the step shows the names of what it was given under its title — a skill as "Skill: …", a collection as "Knowledge: …", tools and integrations by their names — with +N when there are more than four. Open the step and its panel lists everything, grouped into Tools, Knowledge, Skills and Integrations, each with a one-line description and the words above. When two of them have the same name — two collections both called "Notes", or the task files of two conversations — they are numbered, "Notes (1)" and "Notes (2)", the same way on the diagram and in the panel.

Skill versions. A step uses the version of a skill that was current when the Builder added it, and keeps using it when the skill changes later, so a workflow that works doesn't change under you. When the agent has moved on to a newer version, the skill's name on the diagram carries an arrow — hover it for Newer version available — and the step's panel shows Newer: vN beside the version the step uses. To move the step to the newer version, ask the Builder; it updates the step for you. Self-healing never changes a skill's version on its own.

Done by a separate step, never by an Agent step. Running code, and reading or writing the database with SQL, each have their own step — a Script step, a Database write step — so that work runs the same way every time. A message the workflow sends from the platform, or from a mail server you fill in, is a Notify step for the same reason. The one exception for code is a skill's own scripts, above, which the step panel marks runs code. The mailbox connected for the agent is not that broadcast: an Agent step can be given it, and then read, search, reply, send and forward on that account. See The connected mailbox.

Never available in a background step. Some of the agent's tools only make sense in a live chat, so no workflow step gets them: asking the user a question, showing something in the chat canvas, showing images or citing sources in the chat, opening a file attached to the current chat or adding it to knowledge, working with the agent's own workflows, building agents, and changing the database's structure. Saving to memory, generating images and video, and downloading from Google Drive aren't available to workflow steps yet. Calling this agent or a connected agent is its own step — see Calling an agent — not a tool an Agent step is given.

When something a step was given goes away. If a collection or a skill is removed from the agent, a skill's secret is missing, the browser isn't paired, a connection of the person the run acts as is missing or needs reconnecting by the time the step reaches it, or the run was started by a webhook or from a chat while the step needs the browser or someone's task files, the step stops before it does any work. The run is marked Needs a key or setting, with a note naming where to fix it — Skills, Knowledge, Browser Control, or, for a connection of the person the run acts as, the agent's setup window, where that person connects or reconnects it — and the step's error says exactly what to change. Some of these only a change to the step fixes — running the scripts of a skill that connects through Authorize, say, or someone's task files in a run started by a webhook — and then the error says to ask the Builder to change the step. A few only your installation's administrator can fix, such as web search the installation no longer has; then the note says that instead of naming a panel. Automatic retries and self-healing leave it alone, so no credits go on guessing. A scheduled run that stops this way turns off the schedule it came from, as with Google below, so switch it back on once the setting is fixed. A browser that is paired but offline at that moment is different: the step sees the error and carries on as best it can.

The connected mailbox

An Agent step can work in the mailbox already connected for the agent in Integrations. It can list messages, read one, search, mark one as read, reply, send a new message, and forward one. A reply or a new message can include files the run already has — a file an earlier step of the same run wrote, or one in the working folder of the person the run acts as. Reading a message can bring back one of its attachments. Forwarding sends the text of the original message, plus a comment when the step adds one; it does not attach the original files or new ones.

On the diagram the step names that mailbox the way it names any other integration: the kind of account and the address, such as Email — Gmail and the address itself. Outlook, Yahoo, Yandex, Mail.ru and iCloud are named the same way. An account that isn't one of those still shows Email and the address. When the address isn't yours to see, the step says uses email and does not show someone else's address. Open the step and the same name is in the Integrations group of its panel.

Whose mailbox a run opens follows the mode set in Integrations, the same rule as Whose run it is:

  • Each user connects their own — the run uses the mailbox of the person it acts as. That person connects it in the agent's setup window, or picks one from their Connections library, before the run. If they haven't, the step stops and tells them to connect a mailbox. A run that isn't acting as a person at all stops too, and tells the owner to switch the mailbox to one shared account or to run the step as someone who has connected one.
  • Shared — my connection for everyone — every run uses the owner's mailbox, whoever started it. If that mailbox isn't connected, the step stops and points at Integrations.

This is not the Notify step. Notify sends one prepared message from the platform mailbox, or from a mail server you set on that step. It does not open a mailbox, and it does not send as the person who connected one. Ask the Builder for a Notify step when a report or an alert should go out the same way every time. Ask it to give an Agent step the mailbox when the step has to look at the mail, answer it, or write from that account.

Sending, replying and forwarding are marked seen outside the company on the step, and every call to the mailbox is marked reaches the internet — the same words as What a step can reach.

Subagents in an Agent step

An Agent step can also hand pieces of its own work to subagents — extra runs of that same step, started alongside it. A subagent gets exactly what the step itself was given, nothing more: the same tools, the same model. It works on one piece of the job with a clean slate and hands its result back to the step. This is how a step handles "however many turn up" work — look into each ticket a search turned up, gather details on each competitor a search finds — without working through every piece one after another in a single long conversation.

When the Builder reaches for subagents. If the number of pieces is already known while the workflow is being built — three named sources to check, say — the Builder lays that out as a parallel group of separate steps instead: a group is easier to follow on the diagram, and each step in it keeps its own history and its own Resume. Subagents come in once the count is only known while the workflow is running — "however many tickets came in today" might be two or might be twelve — and a single Agent step starts one subagent per piece as it goes.

Limits. Subagents can nest up to three levels deep (a subagent can hand out subagents of its own, and so on), an attempt of the step (one try at that step — a step can be retried within a run, separately from a new attempt of the whole run) can start up to 20 subagents in all, and up to 5 work at once. That count of 5 only includes subagents actively doing their own work — one that's simply waiting on subagents of its own doesn't take one of those places, though it still counts toward the "running" number shown on the step's card. Each subagent runs inside the same ceilings as the step itself — how many times it may call the model or a tool, how much text it may handle, how long it may run — and its own time limit includes however long it spends waiting on its own subagents. The step's overall time limit grows to add its subagents' time on top of its own: with up to 20 subagents running 5 at a time, that can take up to four rounds, each allowed as long as the step's own time limit — so a step with subagents may run up to five times as long as one without. A run only has the one browser you've paired, so a well-built step hands browser work to one subagent at a time — the Builder writes the step's task with that in mind; several subagents reaching for the browser at once would just interfere with each other.

Watching them work. While a step is running, its card on the diagram carries a counter — "N subagents · M running" — and opening the step's panel shows a Subagents section: a tree of every subagent the step has started, each row labeled by the first line of its task, with a live timer and its current tool while it's still going. Expand one to see its full task, the tools it called, and its answer; values from the workflow's Configuration and the agent's Environment show there as ***. A well-built task opens with a short line naming the part it covers — a story's title, a region's name — so the collapsed rows tell subagents apart at a glance instead of repeating the same opening words. A webhook body isn't masked there: subagents keep it as it arrived, the same as step results, and only what streams in live while the step runs masks it — see Using the request body. Subagents from an earlier attempt of the same step collapse into a single line you can open to look back. The Android app shows the same counter on the step's card.

A subagent that fails doesn't fail the step. If a subagent runs into trouble — a site it needed is unreachable, it hits one of its own limits — that comes back to the step as an ordinary result, and the step's model decides what to do next: try that piece again a different way, finish it itself, or say in its answer that this one piece is missing. The step only fails on its own account, never because a subagent did.

Stop lets them finish; Force stop cuts them off. Stop lets the running step — and so its subagents — finish what they're doing; it just keeps the next step from starting once they're done. Force stop, and the platform's own automatic stop when the account's balance runs out, cut the step off right away instead, including every subagent it has running, even one in the middle of calling a tool.

Resuming. Resume a run whose step was interrupted, and — as long as nothing has changed the step since (self-healing hasn't rewritten it) — the step picks up with what its subagents from the interrupted attempt had already finished, instead of redoing that work. A new run, a Restart, or a step that self-healing has changed starts its subagents from zero.

Cost. A step's cost already includes everything its subagents spent, so there's nothing extra to add up — but a step that uses subagents can cost considerably more than one that doesn't, since each of up to 20 subagents in an attempt spends inside its own copy of the step's ceilings.

Steps that write into a spreadsheet

A step that writes into a Google spreadsheet writes text. A value starting with = is stored as those characters, not run as a formula, and text that looks like a number or a date is kept exactly as it arrived rather than converted. So a phone number such as +7 900 123-45-67 stays a phone number instead of turning into a formula error, and text the workflow picked up from a page, an email or a form cannot quietly turn into a formula that reads other cells and sends them somewhere.

Sometimes a formula is the point — a totals row, a link between sheets. Open the step and untick Write values as text; you'll be asked to confirm with I trust this step, because from then on everything that step writes beginning with = runs as a formula — including text it picked up from a page, an email or a form. Ticking the box again needs no confirmation. Each step has its own box, and you change it on the workflow's current version: a step opened from an older run shows the box but doesn't let you change it.

The workflow diagram shows which is which: a step whose values are written as text carries a shield, a step allowed to write formulas carries a red not safe, and a step that writes nothing a spreadsheet could interpret carries neither. The same shield or red tag sits beside the box in the step's panel. The Builder can also allow formulas on a step when you ask it for one in words — and then there is no confirmation to see, so the red tag on the diagram is the thing to look for.

Only the two spreadsheet writes — writing a range and adding rows — have this switch. Adding text to a document or creating a calendar event has nothing to interpret, and a file a workflow uploads to Google Drive is always stored as a plain file, never converted into a Google spreadsheet or document.

The run's date

Every run has its own date and time: the moment it started — for a scheduled run, the time it was scheduled for, not the moment the scheduler got to it. Every AI step is told that date, so a step asked for "today's report" or "this week's news" knows which day it is, and the date stays the same when the run is retried or resumed later: a run resumed the next morning still writes the report for the day it started. A Restart, from the start or from a step, keeps the original run's date too. To put the date into a step's text, write {{run.date}} (for example 2026-09-26), {{run.datetime}} (the date and time) or {{run.timezone}}; a Script step reads the same values as RUN_DATE, RUN_AT and RUN_TZ. Inside a Script step these three names belong to the platform: a variable of the same name in the agent's Environment is not what the script sees there. The date is given in UTC whatever your own timezone, and whatever time zone the schedule runs in, so a schedule that fires shortly after midnight in Moscow (UTC+3) carries the previous day's date.

Limits

Every workflow carries limits it runs inside: how many times it may call a model, how many calls it may make out to connected tools, and how long the whole run may take. The Builder sizes them when it writes the workflow. There's no panel to tune them by hand — if they need to change, ask the Builder. How much text a step takes in or passes on isn't one of these limits — a step handles as much as the model it runs on can hold, and a run is held in check by its model-call, tool-call and time ceilings instead.

They are ceilings, not targets. A run doing its job finishes well below them; they're there to stop a run that has gone wrong rather than let it keep going and keep spending credits. A run that reaches one stops there, and the run history shows which step it was on.

A workflow that keeps hitting its limits doesn't need bigger ones. Raising a ceiling on a step that never finishes only moves the point where it stops — the real problem is a task with no end in it ("go through every category", "collect the full list"). Give the step something that finishes: say how many sources or items it should stop at, or have the Builder split the work across several steps that each do one part.

If a step's input is too big for the model. A model can only take in so much at once. When an earlier step hands a step more than the model it runs on can hold, that step stops and says the data is too large for the model — reduce what the step takes in, or have the Builder split the work so each step handles a smaller piece.

Creating and running one

  • Create: ask the Builder in chat — describe the automation you want ("every morning, summarize new support tickets and email me") and it builds the workflow. Creating your first workflow automatically switches on the Workflows capability for that agent. You can then fine-tune steps, variables, and the schedule.
  • Ask for an event-driven one too: describe what should start it ("when GitLab opens a merge request, post a summary to Telegram") and the Builder writes the steps around the incoming event. What it can't do is switch the webhook on — minting the URL and the secret is yours, in the workflow's settings, and the Builder will tell you to do it once the steps are ready.
  • Run manually: the Run button on any workflow. A workflow must pass validation and be marked ready before it can run.
  • Run on a schedule: set a schedule with presets (every hour, daily at a time, weekly, monthly) or a custom expression. The schedule is yours: it runs as you, on your connections, on the clock of its own time zone — yours, when you set it up — and anyone else who runs the workflow keeps a schedule of their own — see Personal schedules and webhooks. If a run is interrupted because a server on our side restarted — not anything wrong with your workflow — it's retried automatically, picking up from where it left off, up to three times a few minutes apart, with the schedule staying on the whole time; you'll only hear about it by email if the problem doesn't clear up after those retries. The same holds when a Script step or a Database write step can't reach a service on our side — the one that runs the script's code, or the one that reads and writes the agent's database for either step: the step is retried a few times straight away, and if the service is still down, the run gets the same few-minutes-apart retries, with the schedule staying on. Self-healing doesn't try to rewrite a step that was never broken, and you're never asked to fix a key in Environment for the step's database access — the platform handles that access itself. A rarer problem on our side that isn't a restart doesn't get retried the same way, but it's handled the same in every way that matters to you: it's not treated as your workflow's fault, so the schedule stays on and you're notified by email rather than left guessing. If a scheduled run fails for a reason on your end instead, your schedule turns off so it does not keep retrying a workflow that needs a fix — only yours: anyone else's schedule of the same workflow keeps running. Turn it back on after you fix the workflow. The schedule you saved stays visible on the Workflows tab while it is off, so you can see what it used to run at — and it comes back as it was when you switch it on again.
  • Track runs: the Run history shows each of your runs' trigger, status (completed, partial, interrupted, failed), duration, and per-step output, so you can see exactly where a run went wrong. On the Workflows tab, the Activity strip plots the last 24 hours of your runs — one lane per workflow, one dot per run, coloured by the run's own status and explained by the legend underneath. You can opt in to an email when an unattended run fails — scheduled runs and webhook deliveries alike; it goes to the person whose schedule or webhook started the run (see When an unattended run fails) — and the Cost section on the workflow list, for what your runs are spending. Other people's runs of the agent's workflows are theirs: you see only the ones that failed, as short rows — see What the owner sees of other people's runs.

A run can finish partial, not just completed or failed. Every step can run cleanly and the workflow still not have done its job — an API call that succeeds at the HTTP level but answers with a body that says the real operation failed. If you've told the Builder what a real success looks like (below), a run that finishes without any step failing but misses that bar settles as partial rather than completed. A partial run reaches you the same way a failure does — it's covered by the email when an unattended run fails opt-in above — but nothing else about the workflow changes: a scheduled workflow keeps firing on its schedule (only a genuine failure turns the schedule off), and self-healing doesn't attempt a fix, because nothing crashed for it to fix — the workflow ran exactly as built and simply didn't meet the condition you gave it.

Declaring what counts as success. By default, any run that finishes without a step failing counts as a success. When that's not good enough, describe the real condition to the Builder ("only count this run as successful if the ticket's status comes back solved") and it adds a success check to the workflow, free to read any step's output, not just the last one. The check runs once, right after the workflow's last step finishes; a run that fails it settles partial, as above. Leave it undescribed and a workflow behaves exactly as it always has — finishing its steps is enough.

A script step's files persist in the working space of the person the run acts as. A run you start acts as you, and so do runs of your own schedule and your own webhook (see Whose run it is). So a file one run's script step creates is still there for that person's next tick, their manual run, and their chats with the agent to read. That's the ordinary case, because Max parallel runs on the webhook trigger defaults to 1 — see below. Raise it above 1 and every webhook delivery of that workflow gets its own private, run-scoped file space instead — as soon as the pool itself is raised, whether or not another delivery happens to be running at the same moment — so two deliveries genuinely in flight at once can't collide on the same file. That private space does not carry over to the next run, not even the very next delivery. What every run CAN always see, whatever the pool setting: the agent's own files, and anything an earlier step of that same run wrote. If a workflow needs to remember something between runs while its pool is raised — a running total, a "last seen" marker, a checkpoint — don't keep it in a file; have the script step store it somewhere that outlives the run, such as the agent's own database. A run that calls an agent is separate from both of those: its steps share that run's scratch folder, and do not write the agent's permanent files.

Whose run it is

Every run acts as one person — the person behind whatever started it:

How the run started Whose run it is
Run was pressed whoever pressed it
The agent started it from a chat whoever asked — or the agent's owner, when the owner, or an Owner or Admin of an organization the owner owns, asked
A schedule came due whoever set up that schedule
A webhook was called whoever enabled that webhook

The run works on that person's connections. Its MCP servers, Google, mailbox and Telegram — and the Configuration fields that come from them — are that person's own for every integration the owner set to Each user connects their own, and the owner's for an integration the owner shares with everyone (such as Shared (my connection) on an MCP server, or One shared account for Google). So wherever an agent someone shared with you asks you to connect your own account, its workflows run on yours — never quietly on the owner's; see Shared vs per-user connections. The workflow's own Configuration fields hold that person's values, their script files land in their own working space, and the run is paid for the way that person's chat with the agent would be — see Who pays for a run.

An MCP step is wired to an operation of the server as the server offered it when the workflow was published. If the connection of the person the run acts as doesn't offer that operation, or offers it in another shape, the step stops and tells that person they need broader access on that service, or a reconnect. The workflow keeps working for everyone else, and the owner isn't asked to republish anything.

Before a run starts

Before a run does any work, Donkit checks that everything it uses is set up for the person it acts as — and only what this workflow uses: the connections its steps call on (an MCP server, or Google with the access its steps need), the integrations its Configuration fields come from, and that person's own values for settings marked Filled by each user. A workflow with an Agent (legacy) step runs the whole chat agent, so there every connection the agent has counts. A connection that needs reconnecting stops the run here too: in a chat the agent can ask you to reconnect as it goes, but nobody is beside a run to do that halfway through its work.

  • Pressing Run, or asking the agent in chat, is checked before the run is created, so a refused run never lands in the run history. When something of yours is missing, Run opens the agent's setup window — Set up this agent, with This workflow needs a few connections or values from you before it can run. — listing only what this workflow needs; connect it there and press Continue. On the Workflows tab of a shared agent's page, Run takes you to the Connections tab of the same My settings panel instead, with the same list (see What a person the agent is shared with sees). In a chat, the agent tells you which of your connections to set up in the setup window, and you ask again once they are. When what's missing is a connection the owner shares with everyone, you're told instead that the agent's owner has not connected it yet: only the owner can fix that, in the agent's settings.
  • A scheduled run or a webhook delivery has nobody to ask, so the check comes as the run starts: the run ends before its first step, its error names what is missing (This workflow is missing connections or settings it uses: …), and the person whose schedule or webhook it was is told — see When an unattended run fails. A scheduled run that stops this way switches off that person's schedule.
  • Every new attempt of a run is checked again, so a Resume or a Restart doesn't start on a connection that has broken since.

Every refusal names who can fix it: the person the run acts as for their own connection, their Google access or their own value; the agent's owner for a connection the owner shares, and for a Google service switched off or set to too low a level in the agent's Integrations settings; your installation's administrator for a tool the installation doesn't allow. Which Google services the agent may use, and at which level, is checked by the step itself as it runs — see below.

Who pays for a run

A workflow run is paid the way a chat with the agent is, for the person the run acts as. They can pay from their own personal wallet or an organization they belong to, or leave the agent's default (see Choose who pays).

  • Agent default, when the owner pays. The run draws on the owner's balance — the account the agent belongs to. The owner's own runs, and those of an Owner or Admin of an organization the owner owns, always draw on the owner's balance — or, on an agent published to your organization, on the organization's balance, as in chat.
  • Agent default, when the user pays. The person the run acts as pays from their own balance: the account they were in when they pressed Run, asked in chat, set up the schedule or enabled the webhook. That membership is checked again on every run; if the person has left that organization since, the run is charged to their own main account instead.
  • A wallet they chose. The run draws on that wallet. If it has been revoked or deleted, a new run is refused until they choose again. Donkit does not switch the run back to the owner. Work that already started keeps the wallet it started on.
  • An agent published to your organization, when they leave the default, charges the organization's balance, recorded against the member the run is for, as its chats do. A wallet they chose is used instead.

The owner's monthly allowance for that person applies only to runs the owner pays for — your balance, or the organization's when the agent is published to it. Runs the person pays for themselves are not counted against it. An empty allowance means no limit. Zero stops new runs you would pay for. The allowance does not cover building the agent, evaluations, or optimization.

The allowance is checked before each model request, including the ones that come after tool calls, and each new step of a run is checked again. A step in progress can stop midway once the sponsored spend already recorded for that person reaches the allowance; what was already used is charged. Several runs at once can all pass before their charges are recorded, so the total can finish above the allowance. The allowance resets with the billing period of the wallet that pays. Changing the number does not erase spend already recorded this period.

Who pays is settled when the run starts. A Resume or a self-healing pass of that run keeps the same wallet. A Restart is a new run and uses the choice in effect then. Everything the run spends goes to that balance — model calls, web search, reading web pages — and the models the run may use follow the plan of whoever pays. Pressing Run and a webhook delivery are refused up front when that balance is empty, when the allowance is already used up, or when the chosen wallet is no longer available. A scheduled run or one started from a chat stops as it starts instead, and a scheduled run that stops this way switches off that person's schedule. The run says why: the owner's allowance for this agent is exhausted, or the wallet has to be chosen again. The emails about running out of credits for scheduled or webhook workflows go to whoever pays for them.

Owner-paid agents and other people's schedules

When you pay for an agent you share, runs other people start on the default are yours to pay for — their presses of Run, their chats, and each run of their own schedules and webhooks. If they have chosen their own wallet, those runs are theirs to pay for and do not count against the monthly allowance. Let shared users run workflows is on unless you turn it off; turning it off keeps the people you share the agent with from running its workflows at all (see Share workflows, knowledge and API access).

Personal schedules and webhooks

A schedule and a webhook belong to whoever set them up, and they are never shared along with the agent. Each person has their own on a workflow — one schedule, with its own time zone, and one webhook, with its own address and secret — and setting yours up, changing it or switching it off touches nobody else's.

Who can set them up. The agent's owner, an Owner or Admin of an organization the owner owns, and everyone the agent is shared with, as long as Let shared users run workflows is on in the agent's sharing settings — it is on unless the owner turns it off (see Share workflows, knowledge and API access). The owner sets theirs in the workflow's Triggers card; a person the agent is shared with, in the Triggers section of the workflow's card on the Workflows tab of the agent's page (see What a person the agent is shared with sees). Being a platform admin doesn't put anyone on this list: a platform admin the agent isn't shared with can't keep a schedule or a webhook of their own on it.

Switching a schedule on is checked the way pressing Run is, when you do it yourself — in a Triggers section or by asking the agent in a chat. Your connections for this workflow have to be set up and its own required fields filled in first; if something is missing, you're shown what, the same way Run shows it. A schedule the Builder sets up for the owner is saved without this check; the first run then checks the setup as it starts, like any scheduled run. Switching a schedule off is never held up by these checks, so a broken schedule can always be stopped. A workflow that reads a request body can't be scheduled at all (see Using the request body).

Asking the agent in a chat. "Run this for me every Monday at 9" — the agent sets up your own schedule of that workflow, in your local time, as your browser or device reports it. It's switched on straight away, so the same checks apply, and the agent tells you what to set up if something is missing. You have one schedule per workflow, so asking for a new time replaces the one you have. You can also ask which schedules you have, or to cancel one. When an Owner or Admin of an organization the owner owns asks, all of this acts on the owner's schedule, not on one of their own — the same rule as a run they ask for in a chat (see Whose run it is).

Your time zone. Every schedule runs on the clock of its own time zone, shown under the time picker (Time zone: Europe/Moscow). A new schedule takes yours — the zone your browser or device reports when you save it. An existing schedule keeps the zone it was saved in when you edit it. Older schedules, saved before each schedule kept a time zone of its own, run in UTC, as they always did. When a schedule's zone isn't yours, the picker offers Use my time zone (with your city's name): it rewrites the schedule in your zone so that it fires at the same moments it fires at today — 06:00 in UTC becomes 09:00 in Moscow — and takes effect when you save. It's offered only where the same moments can be written exactly in your zone; a schedule that runs at several set hours of the day, for example, doesn't get it.

Daylight saving. A schedule keeps its local time through daylight-saving changes: a schedule for 09:00 fires at 09:00 on its zone's clock in summer and in winter. On the night the clocks go back, a schedule for a set time of day runs once, not twice; on the night they go forward, a time the clocks skip (02:30, say) runs at the moment they jump. A schedule that runs every hour or every few minutes follows the real clock, so it also runs through the repeated hour.

Your own webhook. Everyone who enables the webhook trigger on a workflow gets their own address and their own secret, and a delivery to it starts a run that acts as them. De-duplication, the rate limit, Max parallel runs and the queue of waiting deliveries all apply to each person's webhook separately — see Webhook trigger.

Everyone has their own place to run. Two people's runs of the same workflow never wait for each other. Your own runs still take turns: a tick of your schedule that comes while your previous run is still going is skipped, Run answers You already have a run of this workflow in progress., and a delivery to your webhook competes only with your own runs, as Webhook trigger describes.

When an unattended run fails

If the person whose schedule or webhook started the run has Email me when an unattended workflow run fails switched on in their account, the failure email goes to them — not to the agent's owner. When the email is about a single workflow of an agent that person owns, its button and the mobile app's notification open that workflow in the builder; otherwise they open the person's list of agents, or the page of the agent that is shared with them. A scheduled run that fails for a reason on that person's end switches off their schedule only; everyone else's schedule of the workflow keeps running. Two cases go further:

  • A connection the owner shares needs reconnecting. A person's run that stops before its first step for that reason switches their schedule off — switch it back on once the owner has reconnected it — and, if that setting is on, their email says the agent's owner has to reconnect it. The owner is emailed too, if the owner has that setting on, to reconnect it in the agent's settings; the owner's own schedule isn't touched.
  • The owner pays and is out of credits. The person's schedule switches off, and, if that setting is on, their email says the account that pays for these runs is out of credits — the out-of-credits email itself goes to whoever pays, so this is how the person learns why their schedule stopped.

When someone loses access

If the agent is no longer shared with a person, the owner turns Let shared users run workflows off, or the person's account is switched off, their schedules stop — each one switches off the next time it comes due — and their webhooks answer every delivery with 404. A schedule switched off this way stays off until the person it belongs to switches it back on; a webhook accepts deliveries again as soon as the person it belongs to may run the workflow again. Nothing is left for the person to undo: their schedules and webhooks stop working by themselves. As long as they can still open the agent, they can also ask it in a chat to cancel their schedule. Setting one up or switching one back on needs access again.

Workflows on a shared agent

While Let shared users run workflows is on — and it is, unless the owner turns it off — the people the agent is shared with use its workflows without seeing what happens inside their steps, and every person's runs stay their own: nobody, the owner included, reads another person's results.

What a person the agent is shared with sees

People the agent is shared with get a Workflows tab in the My settings panel of the agent's page — a published agent's page, or a team's page for its lead agent. For each workflow they may run, it shows the name and description, their own Configuration values, Run, their own schedule and webhook in a Triggers section, and their own runs, with a plain sentence saying why when one failed. What happens inside the steps stays hidden (an installation may choose to list the steps' names and kinds), and Max parallel runs stays the owner's setting. Run and switching a schedule on are checked as Before a run starts and Personal schedules and webhooks describe; when something of theirs is missing, they're taken to the panel's Connections tab. The full description, written for them, is Your workflows.

In a chat, the agent does the same for them: it runs a workflow, sets up, lists or cancels their schedule, and tells them how one of their runs went — its status, why it failed if it did, and its final result. In their chat the agent itself never gets what happens inside a workflow's steps, a run's output step by step, or anyone else's runs, so asking it for them doesn't get them.

What the owner sees of other people's runs

You see your own runs in full, as before. Of other people's runs:

  • Health and Cost count your own runs only. Runs other people start aren't in them — not even the ones you pay for, which still draw on your balance (see Who pays for a run).
  • Activity shows your own runs only.
  • Run history shows your own runs, plus a short row for each run of another person's that failed — ended with an error, or was cut short because something broke on the way. The row gives when the run started, how it was started, its status, the step it stopped at and what kind of failure it was, marked Another person's run did not finish — its content is private. It doesn't open: the run's inputs, outputs, logs and error text stay hidden, and so does the person's name. Other people's runs that finished, that they stopped themselves (or whose repair they stopped), or that waited too long in the queue aren't failures, and aren't listed.
  • Run history also lists each run of another person's that is still going, as a row with when it started, how it was started and Running (or Stopping), marked Another person's run is in progress — its content is private, and a Stop button (where this control is available on your account) — so a runaway run can be stopped. Like a failed run's row, it doesn't open and doesn't name the person.
  • Opening, resuming and restarting a run are for your own runs only; of another person's run, you can only stop one that is still going.
  • The agent in your own chat keeps to the same rule: of another person's runs, it can tell you only about one that failed — when and how it ended, at which step and with what kind of failure.

Your own published page shows you the same Workflows tab, with your own schedule, webhook and runs.

A co-editor — someone you gave the Can edit level — works on the workflows in the builder as you do, but other people's runs stay yours alone: their Run history holds their own runs only, without the short rows of other people's failed runs, and they stop only their own runs. Their Run, schedule and webhook follow the rule for everyone the agent is shared with: with Let shared users run workflows off, Run tells them running workflows is disabled for shared users. When a run is held back by something the agent provides, a shared connection is named as the owner's to connect, and an empty agent variable as theirs to fill in, in the agent's settings. See Editing together.

When a step needs an integration you haven't connected

A workflow that uses Google Workspace can be built and published before Google is connected — that is the normal order, and the Builder won't hold a workflow back waiting for a Google account. Donkit itself defines what each Google step can call, so the Builder can wire the step with no account behind it, and the connection lives on the agent rather than among the workflow's Configuration fields above. The requirement shows up the first time the workflow runs. A Google account that is missing, needs reconnecting, or hasn't granted the access a step needs is caught before the run starts, as Before a run starts describes — addressed to the person the run acts as for their own account, and to the owner for the agent's one shared account. What the agent's Integrations settings allow is checked by the step itself: when a service is switched off, or set to a lower level than the step needs, the step stops before it does any work, the run is marked Needs a key or setting with a note to open Integrations, and the step's error in the run history says exactly what the owner should switch on there. Automatic retries and self-healing leave the step alone, because no change to the workflow can connect an account or change a setting, so no credits go on guessing; fix the setting and run the workflow again. A scheduled run that stops this way also turns the schedule off — the schedule of the person it ran for — like any scheduled run that stops for a reason on the person's end, so once Google is set up, switch the schedule back on too.

An MCP server works the other way round. Its tools are whatever the server itself reports, so a step can only use one once the server has been added to the agent — and authorized, if it asks you to sign in — and the platform has read its list of tools. Until then the Builder has nothing to wire the step to, and the workflow doesn't publish; see What a server can do.

Google steps work on the access of the person the run acts as, like everything else (see Whose run it is). With the agent's Google connection set to Each user connects their own Google account, a step reads and writes the Google account of the person the run acts as — in per-user mode the workflow never borrows the owner's account, and each person connects their own in the agent's setup window before their first run. With One shared account, every run uses that one account. Both modes work for every step type, the older Agent (legacy) step included. The service levels stay the owner's: whoever the run acts as, a step can do only what the level set for each service in Integrations allows.

When Google itself answers with an error. On an Action step that calls Google, a temporary problem on Google's side, or a connection that drops or times out while the step is talking to Google, is retried automatically for every step, whether it reads or adds something. A rate limit or quota for the account (HTTP 429, or a 403 that Google marks as a rate limit) means Google did nothing with the request; it is retried after waiting at least as long as Google asks. Server errors (500, 502, 503, 504), timeouts and dropped connections are retried too, but they can arrive after Google has already made the change. So on a step that adds or creates something — appending rows, creating an event, a document or a file — a retry can create a duplicate: an extra row, a second event. A step that reads, or one that overwrites the same cells of a sheet, can't end up with a duplicate. If the retries run out on a step that adds something, check whether the change was made — possibly more than once — before you run it again; the step's error says so when Google's answer is what failed. A problem that comes up before the step's request reaches Google — while the step is getting its access to your Google account, when Google's sign-in service is briefly busy, slow or doesn't answer, or the connection drops at that moment — is retried the same way and can't create a duplicate: nothing was sent to Google yet, so nothing can have been changed. A short blip costs only a retry, and a scheduled workflow keeps its schedule. Only if Google is still refusing after the automatic retries does the run stop, like any run whose retries run out. An error about the request itself — an id or range that doesn't exist (404), a value Google rejects (400) — is not retried, because repeating it would get the same answer: the run stops under Step refused with This step was refused — by a workflow policy or by the service it called., and the step's error names the status and what to check. An answer from Google that arrives but can't be read isn't retried either, for the same reason, and stops the run the same way; on a step that adds something, check whether the change was made before you run it again. On an Agent step the agent reads Google's answer itself and decides what to do next, as it does with any tool.

Run cost

The Run history list shows the total cost in credits of each of your runs — another person's row shows none — and opening a run shows what each of its steps cost individually. The workflow diagram shows a total too — the total for whichever run it is currently displaying, which can be any run from the history, not only the latest.

The figure is the cost of the run's steps. It's calculated from the same usage your account draws on, but it isn't your account statement: web search, media generation, knowledge indexing, and automatic repair are metered separately and aren't part of it.

Cost builds up attempt by attempt. A run still on its first attempt shows no cost yet; once an attempt has ended, the run shows what the ended attempts cost so far — including attempts that were stopped or crashed rather than finishing. A run that fails and is retried automatically as a whole — a new attempt, not a single step re-asking the model within one attempt — shows the combined cost of every attempt, not just the most recent one.

A total shown with a leading ≥ means the run spent at least that much, and possibly more. You'll see it when a run was stopped by hand, ran out of credits, or was interrupted by the platform while a step was still working. The steps that had already finished are priced normally and counted; the step that was cut off mid-way was charged for the work it had done, but it never got to report how much, so it can't be included. The number is a floor, not the final bill.

A run stopped between steps, with nothing cut off, shows an exact total without the ≥.

Sometimes a run was cut off before anything it did could be priced at all — a single model step stopped part-way, with no finished step behind it. There is no floor to show there, so the run reads cost unknown rather than showing nothing: it did spend credits, and the amount is the one thing that cannot be recovered. Check your usage for the period if you need the exact figure.

Not every step shows a cost figure. Action, Database write, Script, Notify, and Condition steps don't call a model, so none of them show a cost — that's different from a cost of zero, which would mean a model ran and happened to cost nothing.

Runs that finished before this feature shipped read cost unknown for the same reason: nothing was recorded for them at the time, and it can't be filled in after the fact. They did cost what they cost — the platform simply has no record of it per run.

Cost across runs

The workflow list has a Cost section next to Health. It shows what your own runs of the agent's workflows spent over the last 7, 14 or 30 days — runs other people start aren't counted, even when you pay for them (see What the owner sees of other people's runs): the total, the average per run, and a bar per day. The table below breaks the same period down per workflow — runs, average, median, and total. The average and the median are drawn from the same set of runs — those whose cost is actually known — so a handful of expensive ones among them can still pull the average well past what a typical run costs; the median, the middle of that same set, sits alongside it as a steadier read on the ordinary run. Opening a row draws that workflow's spend over time — with an All time switch when you want the whole history rather than the selected window.

Opening a workflow and clicking its cost summary shows the same figures for that workflow alone, plus its most expensive runs, so you can go straight from "this month cost more" to the run that caused it.

Two things the numbers deliberately do not do. Some runs appear in the history but never execute a single step — most often a scheduled run that fires while the balance that pays for it is out of credits, or one whose required settings were left empty or whose connections aren't set up. Those are counted separately as Never started and left out of the total, the average and the median; including them would drag the average toward zero without telling you anything about spend. (When you press Run yourself under the same conditions, the run is refused before it is created at all, so it never appears in the history or in these numbers.) And a run only carries a cost if it was priced while it ran: runs from before this feature shipped, and attempts the platform could not price, are shown as coverage ("Fully priced N of M started runs") rather than silently counted as free — and, like the never-started ones, they're left out of the average and the median too, not guessed at. While any started run is unpriced, the total is marked as a lower bound; the average and the median never are — they're drawn only from runs whose cost is fully known, so each is either an exact figure or, once nothing in the window has been priced yet, no figure at all.

As everywhere else, this is the cost of the workflow's steps, not your account statement — see the note above.

Webhook trigger

The third way a workflow starts: another system calls it. Switch on a webhook trigger and you get your own URL and your own secret for the workflow, so anything that can send an HTTP request — a CRM, a form service, an issue tracker, a script in another department — can start a run. Use it when the work has to happen when something happens elsewhere, rather than on a clock. The webhook is yours: a run it starts acts as you, on your connections, and anyone else who runs the workflow has a webhook of their own (see Personal schedules and webhooks).

Turning it on

The Webhook trigger section sits next to the schedule in the workflow's settings — on an agent shared with you, in the Triggers section of the workflow's card on the Workflows tab.

  • Enable webhook mints the URL and the secret. The secret (it begins with whk_) is shown once, right then — copy it into the calling system before you leave the panel. Afterwards only its first few characters are shown, alongside when the webhook was last used.
  • Rotate secret replaces it with a new one. The old secret stops working immediately, so update the calling system in the same sitting.
  • Disable webhook stops accepting calls, and leaves your schedule untouched. Enabling it again issues a new secret: the one the sender is holding does not come back to life, so plan on updating the sender whenever you switch the webhook back on.

Calling it

Send a POST to the URL from the panel, with the secret in a header. The URL names both the workflow and your webhook — it ends in /hooks/workflows/<workflow-id>/<webhook-id>. Four header forms are accepted, so most systems can be pointed straight at it:

  • Authorization: Bearer <secret> — the usual form. A bare Authorization: <secret> also works.
  • X-Webhook-Token: <secret>
  • X-Gitlab-Token: <secret>
  • X-Telegram-Bot-Api-Secret-Token: <secret> — set as secret_token when calling Telegram's setWebhook.
curl -X POST https://app.donkit.ai/api/hooks/workflows/<workflow-id>/<webhook-id> \
  -H "Authorization: Bearer whk_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: <the sender's own event id>" \
  -d '{"event": "order.paid", "order_id": "A-1042"}'

Idempotency-Key is optional and worth sending: if the same key arrives twice at the same webhook, the second call answers with the first call's run instead of starting another. The same key sent to two people's webhooks is two events, and each starts its own run. GitLab's X-Gitlab-Event-UUID counts as the same thing.

The older address

The address without the webhook part, …/api/hooks/workflows/<workflow-id>, still works for the agent owner's webhook, so a sender the owner set up with it earlier needs no change. Only the owner's secret, or a delivery signed with the owner's webhook keys (see below), gets through there; anyone else's secret or signature is answered with "not found". Everyone else uses the full address from their own panel.

GitLab projects

Paste the URL into the project's webhook settings and put the secret in GitLab's own Secret token field — GitLab cannot send an Authorization header and transmits that field as X-Gitlab-Token. It stamps every delivery with an event id, which covers the de-duplication too.

Senders that sign deliveries

Some services never transmit a secret — they sign each delivery with it, and send only the signature. The signature covers the whole request body, so a delivery that was tampered with in transit is refused the same way a wrong secret is.

  • Services that let you type the secret — GitHub, Bitbucket, Gitea: paste the workflow's whk_ secret into the service's field for it (on GitHub, the webhook's Secret, with Content type set to application/json).
  • Services that create their own secret — Linear (lin_wh_…), Sentry, Shopify: copy that secret into the webhook trigger panel's Sender signing secret field.

The workflow's own whk_ secret always goes into the sender, never into Sender signing secret: it already verifies signed deliveries by itself (a webhook enabled before its secret could sign needs one Rotate secret first — see Older webhooks below), and the panel refuses it there.

A signature is accepted when it matches either secret. Recognized signature headers: X-Hub-Signature-256 (GitHub), X-Hub-Signature with sha256= (Bitbucket), X-Gitea-Signature (Gitea), Linear-Signature (Linear), Sentry-Hook-Signature (Sentry), X-Shopify-Hmac-Sha256 (Shopify).

Older webhooks

A webhook enabled before its secret could sign deliveries still accepts that secret in a header. To sign with it, press Rotate secret once — the panel asks for it while it is needed — and paste the new secret into the sender. Pasted into Sender signing secret, the old secret is refused, and the message names this same step. If the old secret already sits in Sender signing secret, the same rotation clears it from there.

The stored Sender signing secret is shown afterwards only by its first few characters, like the webhook's own. Remove clears it. Rotating the whk_ secret leaves it in place — unless the field holds the old whk_ secret itself, which Rotate secret clears along with it. A delivery that carries the whk_ secret in a header is judged on that secret alone. GitHub and Linear stamp deliveries with their own event id, so de-duplication works without any extra setup. Gitea stamps its deliveries too (as X-GitHub-Delivery), but its Replay sends the event under a new id, so a replayed delivery starts another run. Senders without a recognized delivery-id header (Idempotency-Key, X-Gitlab-Event-UUID, X-GitHub-Delivery, Linear-Delivery) are not de-duplicated, so a redelivery starts another run, billed like any other — Bitbucket, Sentry, Shopify and Telegram among them.

Response What it means
202 queued Accepted; the run is either executing now or waiting for a free slot. The response carries the run_id.
202 duplicate This key was seen before. The original run's run_id comes back and nothing new was started.
409 Max parallel runs is 1, so the person whose webhook it is has a single slot on this workflow and something is already using it — another run of theirs of this workflow, of any kind. Other people's runs never count. Carries Retry-After: 60 — send it again.
409 The workflow has not passed validation, so it cannot run yet.
409 The workflow reads a request body and the call arrived without one. An empty object ({}) counts as a body and starts a run.
429 Too many requests to this webhook (carries Retry-After), or the balance that pays for its runs is out of credits (see Who pays for a run).
429 This webhook already has 20 deliveries waiting for a slot (carries Retry-After).
413 The body is larger than 256 KiB — measured both as it arrives and after it is prepared for the steps.
400 The body is not a JSON object (on GitHub: set the webhook's Content type to application/json), or the Content-Length header is not a number.
400 The body holds a value that cannot be stored: a number too large to be a real number (1e999 and anything else that overflows, plus NaN and Infinity, which JSON does not have), or text containing a NUL or a broken Unicode character. This applies to field names as well as values, at any depth.
503 Deliveries cannot be counted right now (carries Retry-After). Send it again.
404 Wrong secret, a signature that matches neither secret, disabled webhook, no such workflow, or the person whose webhook it is may no longer run the workflow — the agent isn't shared with them any more, shared users may no longer run its workflows, or their account is switched off. On a webhook enabled before signing, a delivery signed with its secret answers 404 until you press Rotate secret once. When a working integration starts answering 404, check for a rotated secret and a disabled webhook first.

Parallelism is opt-in. Once the webhook is enabled, Max parallel runs appears right below it in the workflow's Triggers card and sets how many deliveries may execute at once — it defaults to 1, so a fresh workflow has no parallelism at all: a delivery that arrives while the person whose webhook it is already has a run of the workflow going is refused with 409, exactly like every other trigger. Raise it and deliveries of the same webhook can genuinely run at the same time instead of queuing or refusing one another. The number applies to each person's webhook separately: with 3, your deliveries and another person's each get three at once. It's an upper bound, not a guarantee even once raised: a platform-wide limit on how many webhook runs can execute at once across every workflow can hold any single one of them below its own setting when the platform is busy. Once every slot is busy, further deliveries wait in a queue instead of being refused: up to 20 waiting at a time for each webhook, each for up to 40 minutes. A wait usually ends well before the limit, as soon as one of that person's executing runs finishes and frees its slot.

A queued delivery can still be lost. If nothing frees a slot before the 40-minute limit, or the workflow stops being able to run while a delivery is waiting — the webhook gets disabled or its secret rotated, the workflow fails validation, or the balance that pays for the delivery is out of credits — the delivery is dropped rather than run late. It shows up in Run history as an interrupted run with the reason queue_expired. A queue that is already holding 20 deliveries answers a new one with 429 instead of accepting an event it has nowhere to put. Whatever you point at the URL must be able to retry on a 409, a 429, or a 503; a queued delivery (202) does not need an immediate retry — the platform is already holding it. Only a delivery that later expires (queue_expired) is actually lost, and resending it is on you.

Watching and cancelling parallel runs. Nothing about slots appears on a workflow that runs one thing at a time — the page looks exactly as it always has. The moment two or more of your runs are executing at once, a card appears for each of them, showing what kind of run it is, its status, when it started and how long it has been going, plus its own cancel button: with several runs in flight, cancelling is per run, never one shared button. Cards come and go with the runs themselves — one finishes and its card disappears, a new delivery starts and a new card appears — and once a single run is left, the block disappears again. Waiting deliveries sit in a collapsible Queued panel below; opening one shows everything known about it, including the request body it arrived with, so you can decide whether to discard it.

Parallel runs share the workflow's outside world, not always cleanly. Each run gets its own code-runner workspace, its own MCP connections, and its own slice of conversation history, so one delivery's script files or chat context can't leak into a sibling's. What is not isolated is anything a step writes to the agent's own database: those writes are last-write-wins, so a step that reads a value, changes it, and writes it back can lose an update when another delivery does the same thing at nearly the same time. Design read-modify-write steps with that in mind if you turn parallelism on. Long-term memory is shared on purpose, not isolated per run: every run that acts as the same person reads and writes that person's memory with the agent, and every run reads the agent's own memory — that's how something a webhook-triggered run learns can be used by a later scheduled run or chat.

Resuming an interrupted webhook run competes for a different, single slot. Besides the parallel pool above, every person has one more slot on each workflow, and Resume, Restart, and every manual, scheduled, or agent-triggered run of theirs use it. Press Resume on an interrupted webhook run while a scheduled or manual run of yours of the same workflow is executing, and it's refused with 409 — even when the webhook pool itself has room. Other people's runs never take your slot.

A failing webhook keeps failing. Failed webhook runs reach the workflow-failure email of the person whose webhook it is, the same as failed scheduled runs — but a webhook does not switch itself off the way a schedule does. Deliveries keep arriving and keep failing until you fix the workflow or disable the webhook, so act on the first failure notice.

Using the request body

Whatever the caller sends is available to the steps as {{trigger_payload}} — put it in a step's prompt, or anywhere else a variable goes. The step receives the whole body as JSON text, keys in alphabetical order. The placeholder always stands for the entire body: {{trigger_payload.order_id}} is not a way to reach a single field, and it isn't an error either — it simply arrives in the prompt as those characters, braces and all. To work with one field, have a step pull it out and refer to that step downstream as {{<node_id>.output}}, or {{<node_id>.output.order_id}} for one field of its result. A Transform step is the usual way to do that — it reads the JSON text and gives back the fields it found, each one bindable downstream. A Script step reads it a different way: give the script an input fed by the earlier step and read it in the code as inputs['<name>'], where the value arrives as a ready Python object beside the code. Putting {{trigger_payload}} in a script's code is refused when you save, because a placeholder written in code becomes part of the program rather than data it reads.

The body can end up in the run record, so don't send secrets in it. The run history has no field of its own for the body — it is not listed beside the run the way the trigger type is. But a step that passes the body straight through has the body in its result, in full, and the run detail shows that result like any other; so does an error message that quotes the request back. Anything a step takes out of the body is an ordinary step result too, so an extracted field is just as visible. If the sending system can put a credential in the body, expect to see it in the run detail — send it in a header the workflow doesn't read, or don't send it at all.

Step results carry the body in full because later steps read them: a re-run restores a finished step from its stored result and hands it to the next step, and a blanked-out body would arrive there as unreadable text. The live node log has no such reader — it is only there for you to watch — so the body is masked as *** in the lines that stream while a step runs.

Restarting a webhook run replays the same body, so a re-run reproduces the original event rather than an empty one.

A workflow that reads {{trigger_payload}} runs only on delivery: the Run on a schedule toggle is locked off for it, and the agent's own Workflows tool can't start it either, because neither has an event to hand it. If you want the same process on a clock as well, keep the event-driven steps here and make a second workflow that fetches what it needs itself.

When a change makes an existing workflow start reading the body, its schedules can no longer fire. Your own schedule of it holds the change back: publishing is refused until you switch your schedule off. Other people's schedules of the workflow don't — the change switches them off as it's published, and each person's card says why: Switched off: this workflow now reads a request body, so it can't run on a schedule.

Pressing Run on such a workflow opens Run with a test payload: paste a JSON object and the run proceeds as if that body had arrived over the webhook. It applies to that run only and is not saved. This is the quickest way to try the steps before the real sender is wired up, and to replay an event by hand when an integration breaks.

Live node logs

While a step is running, open it from the run detail view to watch its script output stream in, line by line, in real time — useful for confirming a long-running step is actually making progress instead of waiting for it to finish.

Live logs are streamed on demand and ephemeral: they're only available while a step is running (and briefly after), and are not stored as part of the run's permanent history. If a step produces a very large amount of output, only the most recent lines are kept in the live view.

Steps nested inside a parallel group don't stream live logs yet — opening one shows an empty panel; this is expected, not an error.

When an AI step's answer doesn't fit its shape

An AI step can be given a shape its answer has to follow — which fields it returns, and what kind of value each one holds. Models mostly follow it. Not always: a field asking for text can come back blank, hold a number instead, or be left out altogether.

Rather than throw the whole answer away, Donkit moves what it can onto the declared shape before checking it. A blank piece of text stays blank text, a missing list becomes an empty list, a number written as text becomes a number, a single item where a list was expected becomes a list of one. The step then carries on with the rest of the answer intact — which matters, because a step that searches the web or reads documents may have spent several minutes and a good deal of credit earning it.

Anything that can't be moved without guessing is left exactly as it arrived, and the step fails. There is no sensible stand-in for a missing number, a missing yes/no, or a value that has to come from a fixed list — and where a field could plausibly be read two ways, Donkit does not pick one. The error names the field that didn't fit, so you can see what to change. A step that fails this way is now retried automatically instead of ending the run on the first miss — a second pass often comes back clean.

Seeing what was adjusted

In the run history, a step whose answer had to be adjusted carries a Normalized badge with a count — the same holds for a step inside a parallel group. Hover it to see which fields were touched. A step without the badge needed nothing.

Worth a glance when a result looks thinner than you expected: it tells you the model left something out or returned it in another form, which usually means the step's instructions and the shape it was given disagree about what that field should hold.

Requiring a field to hold real content

Because an empty value now counts as present, mark the fields that must carry something:

  • text that must not be blank → set a minimum length of 1
  • a list that must not be empty → set a minimum of 1 item
  • a value from a fixed set → list the allowed values

These are checked after the filling-in, so a step that comes back blank on a field you marked this way still fails, and still gets retried — instead of quietly completing with nothing in it.

Repair and recovery

When a run fails, the workflow can attempt to self-heal, and the interface offers Fix with AI and Rebuild for workflows that hit validation errors.

You can also stop a repair while it's in progress. The run settles as interrupted, with the failure still shown and Fix with AI right there if you'd rather step in yourself. From there, Continue self-healing hands the run back to the system for another attempt, with its own fresh repair budget — as if the failure had just happened. A run can be continued like this at most twice; after that, the button stays visible but disabled.

When an interrupted run picks up again — after Resume, a rerun from a step, Continue self-healing or an automatic self-healing pass — the steps that already finished aren't run again: the diagram labels them Reused and the run history marks them reused, and they keep the time, tokens and credits of the pass that ran them, while the run's total still counts each step once. Rerunning from a step of a run that has already finished starts a new run instead; the steps it reuses show no time or cost there, because that run spent nothing on them. And if the earlier pass was stopped before its steps were priced, a reused step keeps its time and tokens but not its credits.

Granular live run controls — Stop, Resume, Restart, rerun-from-a-step, and Continue self-healing — are rolling out gradually and may not be enabled on your account yet.

A Transform or Agent step that gets an answer back cut off part-way — or in the wrong shape — asks the model again, showing it what came back and what was wrong with it, up to three times in one run. A step that gets a usable answer on the second try just carries on, and the run history shows it as completed. A step still without one after three tries stops the run and says so, rather than passing half an answer to the next step.

Those extra tries are fitted into the time and allowance the step already has — they are not added on top of it. A step sized for a single call gets a single try and then fails, so if a step keeps stopping this way, give it more room before anything else.

A step waiting for the model can also hit a hiccup on the AI service's side: the service stops responding, the connection to it drops, or it's overloaded. An Agent (legacy) step then asks again on its own after a short wait, at most twice, before it fails; when a later try goes through, the step simply finishes a little later, within the step's own time. An Agent step stops at once instead, and self-healing runs it again after a pause — the step itself is not rewritten for a hiccup that was not its fault.

An Agent (legacy) step is not asked again for a cut-off answer — if its answer comes back cut off, the step just fails. If a workflow still has one of these steps and keeps failing this way, ask the Builder to rebuild the workflow: that moves the step onto the newer types above, which are.

Browser-driven workflows

If the agent can control a browser, a run started with Run or by a schedule drives the browser of the person it acts as — whoever pressed Run or set up the schedule — through the Donkit extension while it's connected. Runs triggered from within a chat or by a webhook never get browser access.