Sign up

Run data

What a workflow run carries from step to step: message, context, identity and answer_as, and how Maps, Gates, Exceptions, tests and the Identity chain use them.

Every workflow run carries the same four objects. Each step reads them with merge codes such as {{context.subject}}, and a Map step writes into them. What came in, untouched, is always there too as {{trigger}}.

Which channels keep a photo's location

A photo can carry GPS, the time it was taken, camera details and rotation. Metadata can be missing or stripped along the way. RCS, SMS/MMS, WhatsApp, web upload and email retention have not yet been measured here, so none is described as keeping or stripping location. Original-quality and normal-quality sending may differ.

The original-file metadata parser is tested internally. Live metadata sources and Nearest place are still being connected. The intended privacy rule is to mask GPS in Test, samples and logs, and keep it out of AI checks, agent input and memory unless a Map explicitly selects it. The image bytes must also have their embedded metadata removed before model use.

The four run objects

ObjectWhat it holdsRead it as
messageWhat was said: an ordered list of parts, each a type (text, image, document, audio or video) and a value.{{message.0.value}} for the first part
contextEverything else the way in brought or a lookup added, as named, typed fields: text, number, yes/no, date, link, email, phone, object or list.{{context.order.total}}
identityWho it is from, filled in as the Ways in and Identity steps go. Its fields are your company's identity fields.{{identity.name}}
answer_asWho answers: the identity the agent speaks as, and why it was chosen (a rule, next in turn, kept from earlier in the conversation, or the workflow's default).{{answer_as.name}}

Example: an email asking to move a booking, with a PDF attached, after the way in and Find person have run.

{
  "message": [
    {
      "type": "text",
      "value": "Can I move my booking to Friday?"
    },
    {
      "type": "document",
      "value": "https://files.example.com/booking-4471.pdf"
    }
  ],
  "context": {
    "subject": "Booking 4471",
    "from": "sam@example.com",
    "sent_at": "2026-10-16T09:12:00Z",
    "order": {
      "id": "4471",
      "total": 120
    }
  },
  "identity": {
    "key": "sam@example.com",
    "name": "Sam Lee",
    "verified": false
  },
  "answer_as": {
    "name": "Ava",
    "chosen_by": "default"
  }
}

A Map step has no result name of its own: it updates these objects. Each Map that changes context makes a new version, and Studio shows which step added or changed each field ("added by Map"). The step's panel shows the run as a small tree, Identity, Message and Context, marking what this step sets.

A lookup (HTTP request, App action or Tool) writes its reply to context under its Context name, shown at the top of the step: later steps read {{context.order.status}}, and a Map after it can reshape it. A Fan out writes each item to context.item the same way; each run reads earlier context as parent.context.<name>. Live runs and Test use these same paths. Only fields a lookup's response mapping keeps reach context; its raw reply stays in the step receipt. A Gate, Switchboard or Throw writes nothing. Codes written the older way, such as {{order.status}}, still read the same reply.

Message parts

A part's value is a merge-code text box: words, merge codes or both, such as Order {{context.order.id}}: {{trigger.text}}. Parts keep their order, and the model receives them as text, image and document input.

Spread parts. When a part's value is a list, it spreads into one part per item. Each item says its own type, or the part's type is used. The format is enforced: a text part must be words, and an image, document, audio or video part must be a link or a file. An item that doesn't fit is left out and reported, for example Item 2: a document needs a link or a file, not words.; it is never guessed.

{
  "trigger.files": [
    {
      "type": "image",
      "url": "https://files.example.com/front.jpg"
    },
    {
      "type": "image",
      "url": "https://files.example.com/back.jpg"
    }
  ],
  "message part": {
    "type": "image",
    "value": "{{trigger.files}}"
  },
  "result": [
    {
      "type": "image",
      "value": "https://files.example.com/front.jpg"
    },
    {
      "type": "image",
      "value": "https://files.example.com/back.jpg"
    }
  ]
}

Context fields

A context field has a name, a type and a value. An object or list field keeps its structure, so {{context.order.total}} reads inside it. Choose Write JSON on an object or list field to type its value by hand; text that isn't valid JSON is reported, never stored in its place.

{
  "name": "order",
  "type": "object",
  "value": {
    "id": "4471",
    "total": 120,
    "items": [
      "Room",
      "Breakfast"
    ]
  }
}

What each way in fills in

Every way in builds the first message and context from what came in, with no Map step needed, so a Gate placed first already has them. A Map only makes later versions.

Way inMessageContext
EmailThe body as text, then one part per attachmentsubject, from, to, sent_at
Web chatThe text, then any uploadssession, page_url, visitor
SMS, MMS and RCSThe text, then any imagesfrom, sent_at
SlackThe text, then any filesuser, channel, thread, sent_at
VoiceThe transcriptcaller, call_id
App eventThe event's summary as textThe event's top-level fields
Called by an AI assistant (MCP)The arguments as textThe arguments
File storageThe file, as one part of its typefile, bucket, key, size, content_type, uploaded_at, metadata
Webhook or Request URL with nothing mappedOne JSON message (the catch-all)Empty

File storage

  • A File storage way in starts one run for each new file. Choose where files arrive: a folder Falcon keeps for you, or a bucket in your own AWS account.
  • The folder is temporary. A file is deleted once its run finishes cleanly. If the run raises an exception, the file is kept for 7 days so it can be handled or run again. Nothing stays longer than 7 days: to keep a file, have the agent save it to one of your stores.
  • Upload with upload keys: they can only add files to the folder, never list, read or delete anything. Each set works for 15 minutes and is shown once. Rotate gives a new folder name, and files uploaded with older keys no longer start runs.
  • Your own bucket is read only. You create a role that can only read new files in the folder, and an EventBridge rule that tells Falcon about them. Falcon never deletes or changes files in your bucket; your own rules decide how long they stay.
  • Choose the kinds of file (images, documents, audio, video) and the largest file. The type is read from the file itself, not its name. Other files, and files over the limit, start nothing. Every file is scanned before an agent sees it.
  • Photo location is off by default: where a photo was taken stays private. Turned on, it reaches the workflow as metadata.location. A photo's time and camera come either way.
{
  "file": {
    "name": "IMG_0042.JPG",
    "type": "image/jpeg",
    "size": 8421377,
    "url": "s3://your-company-bucket/…/site-14/IMG_0042.JPG"
  },
  "content_type": "image/jpeg",
  "uploaded_at": "2026-10-17T15:04:05Z",
  "metadata": {
    "taken_at": "2026-10-17T15:02:41Z",
    "camera": {
      "make": "Example",
      "model": "Survey 3"
    }
  }
}

The catch-all for webhooks and Request URLs

A webhook or Request URL with nothing mapped still hands everything on: one text part holding a JSON object of the request's GET values, its POST (form) values and its body, each kept apart. Context stays empty, and the raw request is still {{trigger}}. A request that is only a body becomes {"body": …}. Add a Map when you want named context fields.

{
  "get": {
    "campaign": "autumn"
  },
  "post": {
    "name": "Sam Lee",
    "email": "sam@example.com"
  },
  "body": {
    "note": "Please call me back"
  }
}

Merge codes

  • Type {{ in any merge-code box to see the fields available at that step: only the steps before it. After a dot, the box lists that object's fields, each with its type and a masked sample. Choosing an object fills context. and keeps the list open; choosing a field closes the code with }}.
  • Merge codes work without drawing wires. In the mapper, each code a message part names is drawn as a wire to that part, and its source shows as mapped.

App actions that find things, such as Gmail's Search emails and List conversations, take a search written in the app's own syntax. Values from the run go in as merge codes. Ask Studio can write the search from plain words.

  • Gmail: is:unread, is:starred, is:important, in:inbox, in:sent, label:<name>, from:<address>, to:<address>, subject:<words>, newer_than:7d (also 1d, 30d), older_than:<n>d, has:attachment. Combine them with spaces; OR between two means either.
  • Example: unread emails in the inbox from the person writing in, this week: is:unread in:inbox from:{{context.email}} newer_than:7d.
  • Other apps have their own syntax. Use only what the action's description gives, and test the step before relying on it.

Gate rules: Simple match and AI match

A Gate lets an item through only when its rules hold. All rules or any rule, as you choose.

  • Simple match compares a field: equals, contains, starts with, greater than and so on. Free and instant.
  • AI match asks a question about the item: yes or no, pick one of several answers, or a score. It costs one AI check, and runs only while the Gate is still undecided, after the simple matches.
  • Score: the AI picks one level (numbered from 0, up to 10, with your own labels) and says how sure it is. Sure enough at is checked first; then Let it through at lets the item through at that level or higher.
  • Scorecard asks several score questions and adds them up: each answer's level times the question's weight (0 to 10, in steps of 0.5). It lets the item through at a total you choose, such as 8 of 12. Its questions go in the same AI check as the AI matches. When one answer is unsure: let it through, raise it, or leave that question out (it counts as 0 and the total is judged on the rest). Scorecards are saved with the way in and run on live runs too.
  • When this stops it, inside each rule, names the exception and its message. A blank name uses the Gate's. A sure answer that doesn't let the item through always raises; an unsure answer raises only when the rule's unsure choice is Raise to Exceptions.
  • It reads says exactly what an AI match is sent: what arrived so far (the default), chosen fields, or everything the Maps before it made. Naming a field in the question as {{field}} also sends it.
  • Test runs every rule on one message and shows each answer, how sure it was, and whether the Gate lets it through.
  • A stop always raises. There is no quiet stop: a stopped item starts no run and goes to Exceptions with a kind (gate_stopped unless you name another) and a message, by default the stopping rule's own ({{stop.reason}}). Exceptions decides what happens next, and Do nothing is a choice.
  • A Switchboard at the end of a way in can route by a question: one pick-one or score question, each answer a route, with an Unsure or otherwise route last.
{
  "rule": "AI match · Is this an automatic reply? · lets it through when No",
  "message": "Looks like an automatic reply",
  "test": "Automatic reply: Yes · 97%",
  "gate": "Stops it → auto_reply",
  "exception": {
    "kind": "auto_reply",
    "reason": "Looks like an automatic reply"
  }
}

Exceptions: kinds and routing

  • Every step before the agent has If this fails: Carry on, or Raise to Exceptions. A raised run skips the rest of the normal path.
  • A Throw step's first choice is what it throws. Exception ends the normal path with error.kind and error.reason. Event publishes a named company event that other workflows' Event ways in can start from; then it carries on or stops here. Inside Exceptions only Event is allowed, so an exception never loops.
  • The Exceptions tab keeps the workflow's kinds list: the built-in kinds (step_failed, agent_flow_failed, delivery_failed, not_verified), every kind a Gate or Throw raises, and kinds you define with a name and a description.
  • Exceptions starts with a By kind router. It uses simple matches only (no AI check, free and instant): each route matches error.kind, the first route that holds takes the exception, and Otherwise is last. A new kind gets its own route once, when it appears.
  • Defaults: a kind a Gate raises starts at Do nothing; an error kind starts at Tell the workflow owners. Handlers use the same steps as Deliveries.
  • Kinds on the step bar opens the Kinds of exceptions side panel: each kind, where it is raised and its route. See Kinds of exceptions.
{
  "By kind": [
    {
      "when": "error.kind is auto_reply",
      "then": "Do nothing"
    },
    {
      "when": "error.kind is not_verified",
      "then": "Reply on the channel"
    },
    {
      "when": "Otherwise",
      "then": "Tell the workflow owners"
    }
  ]
}

Test a step

Every step has one Test dialog. A test from a step runs the workflow from the way in's sample through every step on the path to it, and stops after it: nothing after that step runs. It is instant and free, and nothing is sent. Run it on the server instead to call the real lookups once, read-only; an AI match is then charged as a check.

The result shows the trail of steps that ran, this step's own result, the run's objects as a tree, and the raw JSON behind ›. If the sample never reaches the step, the dialog says where it stopped and why.

Way in → Map ✓ → Gate ✓ → Find person
Stopped at Gate before reaching this step: Didn't match: subject contains invoice

A way in's own Test runs its whole chain, Ways in then Identity, once and read-only: no agent and no deliveries.

The Identity chain

  • This workflow is for Contacts (the default), Team, or Both, by way in. It decides where Find person looks and which identity fields exist. Contacts are the people outside the company who write in; Team are the company's Studio users. A Slack or Teams user is a Team field only.
  • Find person searches your own Contacts or Team list and fills identity.person directly. If several match: Most recently updated (the default), Most recent conversation, Ask the person which, or Treat as unknown.
  • An outside lookup (App action, HTTP request or Tool) goes lookup → Smart filter (Keep one) → Map into identity → Who this is.
  • Who this is reads the identity object alone and applies the person rules. A matched key or a lookup is a claim, not proof: only a Gate set to mark the person verified sets identity.verified.
  • Team directory (Settings › Team directory) keeps the Team list in step with Microsoft Entra ID, Google Workspace or a SCIM provider. Nobody is deleted: someone removed becomes former, and suspending someone pauses what acts for them.
  • A Team workflow starts with an Active employees only Gate after Who this is, so a suspended or former person is never treated as Team.
  • Verify with your work account asks the person, on web chat, to sign in with their Microsoft or Google work account, checked against your connected directory. It is offered only in Team workflows. A disabled or suspended account fails; the signed-in email is the key Find person uses.
Web chat → Verify with your work account → Find person (Team) → Who this is → Active employees only → Agent flow

Agent steps

  • An agent step's Output format (on its Behavior tab) lists the fields it returns with its reply: name, type, description and whether it is required. Later steps read them as {{steps.<agent>.output.<field>}}.
  • What this agent reads (on its Data tab) chooses its input: the whole thread (the default), only the previous step's output, or chosen fields; and, rarely, an earlier agent's tool calls.

Called by an AI assistant (MCP)

  • MCP is a way in of its own, one per workflow. Turning it on turns the workflow's own MCP address on; pausing or removing it turns the address off.
  • The company MCP address lists only published workflows whose MCP way in is on.
  • The tool's name, description and inputs come from the workflow's name, description and start fields.
  • A call runs the MCP way in's chain before the run starts: its arguments are what came in. A Gate stop refuses the call with a plain message.
  • Access tags (MCP › Access tags) decide which callers may list and call which agents and workflows. A caller a grant names reaches only targets that share one of its tags; a caller no grant names keeps the plain access setting for untagged targets and is refused on tagged ones.

Where this is today

Parts of this page describe the Studio before live runs catch up. In short:

  • Works in Studio now: the Map editor with message parts and context fields, merge codes, the run tree and the Test dialog. Live runs save lookup and Fan out context references directly, with older bare names kept as read aliases. They save a Map's parts and context fields with the way in; field types, versions, and parts sent to the model as text, image and document input follow.
  • Gates on live runs save and use each rule's exception name and message. A rule without its own name uses the Gate's, then gate_stopped; the Gate's message can include the stopping rule's message with {{stop.reason}}. Scorecards sum weighted answers in the Gate's single AI check and fill their total, maximum and needed score in the exception message. An AI match reads what arrived; It reads set to chosen fields or everything mapped remains test-only.
  • Saved, running once the engine is connected: the Identity and Exceptions tabs. Until then every exception is logged in Runs and the workflow owners are alerted. Deliveries keeps Call a URL deliveries, which send when the workflow finishes. See What runs today.
  • Not yet saved with the workflow: a Throw in Ways in or after the agent, and What this agent reads. Raised chain results include the exception kind, reason and stopping step.
  • File storage shows its settings on Hosted by Falcon but saves nothing and makes no keys until the server supports it.
  • Designed, not built: a fixed reply shape for every agent (a status, the reply and its data). An agent's Output format is saved today.
  • During an MCP call lookups do not run yet: a lookup step fails by its own If this fails setting.
  • Stored keys in an HTTP request's Headers (a header set to Stored key, shown masked) work in tests only for now; live runs send no stored key until Connections stores them.