# Concepts

The vocabulary you'll see across the editor, API, and run logs.

## Workflow

A workflow is a directed graph of nodes that runs from a trigger to one or more end states. Each workflow belongs to one tenant and is versioned — every save creates a new revision that runs can pin to.

```text
Workflow: customer-support
  Webhook ─▶ Classify ─▶ Agent ─▶ Respond
```

## Node

A node is one step. Types fall into categories: **Core** (Agent, Classify, End, Note), **Triggers & HTTP** (Webhook, HTTP Request, Schedule, Event listener, Respond), **Logic** (If/else, While, User approval), **Data** (Transform, Set state, Generate file, RAG), and **Tools** (Guardrails, MCP). Each node has its own config schema in the right panel.

## Edge

An edge connects one node's output to another node's input. Some nodes (Classify, If/else) have **multiple labeled outputs** — the edge's source handle picks which branch to follow.

```text
Classify ──(intent=refund)──▶ RefundAgent
         ──(intent=other)───▶ FallbackAgent
```

## Trigger

A trigger is the node that starts a workflow run. Four kinds:

| Trigger | Starts on |
|---------|-----------|
| Manual / Start | Editor "Run" button or chat preview |
| Webhook | Inbound HTTP request |
| Schedule | Cron expression or interval |
| Event listener | Poller finds a new event in an external source |

## Validation rules

Every save runs structural checks. A failed **block** returns `400` and the workflow isn't saved; a **warning** is informational and still saves.

| Rule | Severity | Why |
|------|----------|-----|
| Exactly **one trigger node** (Webhook / Schedule / Event listener) | Block | A run has a single entry point |
| Don't mix a trigger node with a **Start** node | Block | Pick one entry point — a published trigger *or* a manual/API Start |
| A **Webhook** must be authenticated (`authType` ≠ `none`) and have a path | Block | Unauthenticated public endpoints are rejected |
| At most **one Respond node**, and only with a Webhook trigger or Start entry | Block | A Respond node needs an HTTP caller to answer — see [Respond to webhook](#/node-respond-webhook) |
| **Orphan node** — a node with no incoming connection that isn't the entry | Warning | Likely a dangling step; it never runs |

New workflows are created as **Draft**. Switching one to **Live** runs an extra activation check — see [Troubleshooting → Can't activate](#/troubleshooting).

## Run (execution)

A run is one execution of a workflow. The runtime records each node's input, output, duration, and error (if any). Runs are visible in the **Runs** panel and queryable via API. Failed runs can be replayed from the failing node.

```json
{
  "run_id": "run_01HX...",
  "status": "succeeded",
  "duration_ms": 1842,
  "nodes": [
    { "id": "agent_1", "status": "ok", "tokens_in": 312, "tokens_out": 87 }
  ]
}
```

## Credential

A credential is a named, encrypted secret stored encrypted at rest in your workspace's credential store. Nodes reference credentials **by name** — the secret value is decrypted at execution time and never sent to the LLM. See [Credentials](#/credentials).

## Agent

An agent is a Core node that calls an LLM with a system prompt, optional tools, and an output mode. It receives input from upstream nodes (or chat), reasons, optionally invokes tools, and emits a result.

```yaml
agent:
  name: Triage
  model: gpt-4.1-mini
  system_prompt: "Classify the user message and call route_ticket."
  tools: [function:route_ticket, web_search]
  output_mode: structured
```

## Tool

A tool is something an agent can call mid-reasoning. Built-in tools: `function` (custom code or HTTP), `web_search`, `code_interpreter`, `file_search`, `image_generation`, `shell`, `mcp`. Tools have schemas the LLM uses to know when and how to call them.

## Output mode

Each agent emits its result in one of three shapes, selected per-node:

| Mode | Output type | Use when |
|------|-------------|----------|
| `text` | Plain string | Free-form replies, summaries |
| `json` | Parsed JSON object | LLM should return loose structured data |
| `structured` | Typed schema you define | Downstream node needs strict fields |

Downstream nodes can reference fields with `{outputs.<node-id>.parsed.<field>}` interpolation when `json` or `structured` is used.

## Templates & placeholders

Anywhere a node accepts a string (prompts, URLs, HTTP bodies, set-state values, respond-webhook bodies, file templates…) you can interpolate values from the run context with `{key.path}`.

| Placeholder | What it points to |
|---|---|
| `{event.body}`, `{event.body.X}` | Payload of the trigger that fired the run (works for **webhook**, **schedule**, **event listener**) |
| `{event.headers.X}`, `{event.query.X}` | Webhook-specific: incoming headers / query string |
| `{webhook.body.X}` | Legacy alias of `{event.body.X}` — same value, more explicit |
| `{input}` | Initial workflow input (the trigger body, or what you passed to `/execute`) |
| `{last_output}` | Output of the **previous node only** — overwritten after each step |
| `{last_output.field}` | A field inside a JSON `last_output` |
| `{state.<key>}` | Value written by a **Set state** node, with explicit namespace (recommended) |
| `{<key>}` | Shortcut for `{state.<key>}` |
| `{outputs.<node-id>.raw}` | The raw (text) output of any past node |
| `{outputs.<node-id>.parsed.<field>}` | A field of any past node's structured output |

> Placeholders resolve once, at the moment the node runs. If a path doesn't exist, the literal `{path}` is left untouched — useful for debugging mistyped keys.

### `{`-autocomplete and the data panel

You don't have to remember these paths. In any templated field, **type `{`** and an autocomplete dropdown lists every variable actually available at that point of the graph — trigger fields, upstream node outputs (with their schema fields when the upstream agent uses JSON output), and state keys. Arrow keys + Enter insert the `{path}`.

The config panel also has a **`{}` icon** that opens the **available input data** reference: the same variables, grouped by source, with a copy button on each path.

### Structured outputs per node

Every node records both `outputs.<id>.raw` (text) and, when it has structure, `outputs.<id>.parsed`:

| Node | `.parsed` contains |
|---|---|
| Agent (json / structured) | The fields of your output schema |
| HTTP Request | The parsed JSON response body — `{outputs.<id>.parsed.<field>}` |
| Classify | `.classification` — the chosen category name |
| If/else | `.branch` (handle taken), `.condition_met` (bool) |
| Guardrails | `.safe` (bool), `.reason` |
| RAG | `.answer`, `.sources` |
| File search | `.matches`, `.count` |
| Code execution | `.output`, `.exit_code`, provider details |
| Generate file | `.url`, `.filename`, `.format`, `.size_bytes` |
| Transform / MCP | Parsed JSON when the output is JSON text |

---

*Source: https://agentbuilder.systalink.sn/docs/concepts — human documentation.*
*Other language: [/docs-md/fr/concepts.md](/docs-md/fr/concepts.md).*
*Machine-readable index: [/llms.txt](/llms.txt).*
