# 0030 · A call's answer runs the next step: the same automation, given the answer and what it asked to be given back

**Status:** Accepted · 2026-11-02. It extends the calls of
[0028](https://codna.me/docs/adr/0028-scripts-call-the-apis-they-read.md), whose answers reach no script today. The sandbox
([0007](https://codna.me/docs/adr/0007-quickjs-sandbox.md)) does not change: a script is still synchronous and runs in 100 ms,
and the next step is a run of its own.

## Context

With [0027](https://codna.me/docs/adr/0027-other-apps-start-automations.md), [0028](https://codna.me/docs/adr/0028-scripts-call-the-apis-they-read.md)
and [0029](https://codna.me/docs/adr/0029-an-automation-keeps-what-it-needs-between-runs.md), an automation can be started by
another app, read what it needs, write back to an API and remember what it did. One kind of flow
still can't be written: one whose next step needs what the API answered.

- **A form is filled in.** Make the contact in the CRM, then add it to the list for its plan. The
  second call needs the id the first one answered.
- **A deal is won.** Make the invoice in the billing system, then post its link to Slack.
- **An issue is opened in Linear.** If it was made, attach the customer's page to it; if the API said
  the team doesn't exist, tell the owner.
- **A page is created in Notion.** Then add its blocks, which need the new page's id.

What exists can't do it:

- **The answer is recorded and reaches no script** (0028).
- **A read happens before the run** (0025), so a script can't read something made by a call in the
  same run.
- **Two automations,** one making the call and one reading the record, would have to find each
  other's calls. Nothing fires on a call's answer.

n8n's answer is the next node on the canvas. Here, the script stays where the flow is written.

## Decision

### A call can ask for its answer

`actions.call` takes a third argument. With `then`, the call's answer comes back to the same
automation, in a new run, with whatever `then` holds:

```js
export default function ({ event, actions }) {
  if (event.type === 'call.answered') {
    const { answer, then } = event
    if (then.step === 'add-to-list' && answer.status === 201) {
      actions.call('crm', { method: 'POST', path: '/lists/' + then.list + '/members', body: { id: answer.data.id } })
    } else if (answer.error) {
      actions.notify('me', 'The contact for ' + then.email + ' was not made: ' + answer.error)
    }
    return
  }
  const form = event.request.body
  actions.call('crm', { method: 'POST', path: '/contacts', body: { email: form.email } },
    { then: { step: 'add-to-list', list: form.plan, email: form.email } })
}
```

- **`then`** is any JSON, at most 16 KB, handed back as it was given. It carries what the next step
  needs from this one, so the script needn't keep it in its state (0029).
- **The next run** is told `event.type` `'call.answered'`, and `event.answer`:
  - `status`, and `data` (an answer in JSON) or `text` (anything else), at most 1 MB;
  - `error` when there is no answer: the call failed for good, or was never made because a call
    before it failed. The call is in `method`, `path` and `connection`.
- **The run's `inputs` export is given the answer too,** so a step can read a source about what was
  just made.
- **It is the same automation, as the same owner,** with its current script and state. It is a run
  like any other: vetted, recorded, counted towards being switched off for failing, and able to
  call again with `then`.

### When the next step runs

- **As soon as the call is finished,** through the outbox. A run's calls to one connection still go
  in order (0028); each call's next step runs when that call is done, without waiting for the rest.
- **Every call that asked for its answer gets a next step,** whether it was answered, failed, or
  never made. A flow that needs to clean up, or to tell someone, always has its chance.
- **A switched-off automation's next steps don't run.** The call's record says its answer was not
  handed back, and why.
- **At most 10 steps in a chain.** Each next step is one step further on, and `event.step` says how
  far. A call made at the tenth is refused, saying so. That bounds a script that asks for answers in
  a loop, as the cascade depth bounds one that writes the pages it fires on.

### Trying it

- **A dry run of the first step** shows each call with its `then`, and says its answer would run the
  next step.
- **The next step is tried with an answer given:** `run_automation` with `answer` (such as
  `{ "status": 201, "data": { "id": 812 } }`) and `then`. A dry run or a preview of it calls nothing,
  as any does. On the automation's page, **Try it on an answer…** takes them.
- **A real run by hand makes its calls,** and their next steps run, as they would on any run.

### What is kept

- **The next step's run record keeps the answer it was given,** as `event.answer`, cut at 64 KB, for
  30 days, as it keeps a request (0027). It also says which run's call it answers. A chain can be
  followed run to run on the automation's page.
- **The call's record says it ran a next step,** and links to that run.

## Consequences

- **The flows that need one call's answer for the next are one automation,** and their steps read
  as one script. n8n remains for flows that branch across many systems, wait on people, or need a
  canvas to be understood.
- **A script now has several entry points.** It branches on `event.type` and `then.step`, and a step
  it forgot to handle does nothing, saying nothing. The skill tells agents to write each step, and to
  try each with an answer before switching the automation on.
- **An API's answer drives what a script does next.** The answer is data from a system its owner
  connected, and code acts on it, as code acts on a request (0027). A field such as a contact's name
  can hold anything the system holds, and a script that puts it in a message passes it on.
- **More runs:** one per step. The 10-step limit, the 20 calls a run, and switching an automation off
  after repeated failures bound how many.

## Alternatives rejected

- **`await` on a call inside the run:** a run is 100 ms and synchronous, so a dry run can be safe
  and secrets stay out of the sandbox. What 0023 and 0025 rejected `fetch` for holds here too.
- **A second automation fired by answers,** such as a trigger `call.answered` on a connection: the
  flow would be split over two scripts, which have to agree on what each answer is for. `then`
  keeps the flow in one script, and says what each answer is for.
- **Answers kept in the state** (0029) for the next scheduled run: the flow would wait for a tick, and
  the state isn't meant to hold answers of up to 1 MB.
- **Next steps only for answers that succeeded:** a flow could not tell anyone that its first step
  failed.
- **A graph of steps,** as n8n draws: a workflow engine, which 2026-10-25's direction keeps CoDNA
  from becoming.

## Settled when it was accepted

Tornike accepted it as proposed on 2026-11-02, settling:

1. `then` is `actions.call`'s third argument, and the same automation runs again with `event.type`
   `'call.answered'`.
2. The limits: `then` 16 KB, an answer handed back up to 1 MB, 10 steps in a chain.
3. Every call that asked gets its next step, answered, failed or never made.
4. A switched-off automation's next steps are dropped.

## Still open

- **Waiting:** "if the invoice isn't paid in 3 days, remind them", as a next step that runs later. It
  could be a `then` with a time.
- **Answers from reads** in the same shape, for a read that should be made only after a call.

## Building it

1. **The next step:**
   - `then` on a call, kept with it;
   - the event when the call is finished, carrying its answer;
   - the run with `event.answer`, `event.then` and `event.step`, in `inputs` too, and the step limit;
   - the records linking a call and its next step;
   - trying a step with an answer, over MCP and on the automation's page;
   - the contract.
2. **Docs:** [automations.md](https://codna.me/docs/automations.md), and the `set-up-an-automation` skill, with the
   form-to-CRM flow as its example.
