> For the complete documentation index, see [llms.txt](https://docs.interactive.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.interactive.ai/agents/concepts/routines.md).

# Routines

> **Context** — Routines are the structured-flow building block of an agent (the cross-cutting one is [policies](/agents/concepts/policies.md)). This page is the definitive model; [Authoring routines](/agents/guides/authoring-routines.md) is the hands-on companion. If you read only one warning on this page, read [the node types](#node-types-read-this-first).
>
> YAML examples follow **manifest schema 6.1.1**. Manifest and content shapes are schema-versioned and differ across runtime versions — see [Versioning & compatibility](/agents/operations/versioning.md).

## What a routine is

A routine is a versioned YAML document describing a **graph** the agent walks through across one or many turns: nodes carry actions, and each node lists its outbound transitions. Execution starts at the node named by `entry`.

```yaml
id: car-search
title: Car Search
conditions:
  - >
    The user wants to browse the fleet, find a car, or asks for car
    suggestions — phrases like "what cars do you have", "show me an SUV",
    "I need a 7-seater". Do NOT activate when the user is referring to a
    specific booking they already have.
description: >
  Help the user narrow down the fleet to one or two candidate cars by
  collecting their criteria, searching the catalog, and presenting results
  with prices.

entry: gather-criteria
nodes:
  - id: gather-criteria
    chat_state: >
      Ask the user for their preferences in one short message: category
      (economy / compact / SUV / van / luxury), minimum number of seats,
      transmission preference, and any daily-budget cap in EUR. Tell them
      any field is optional.
    transitions:
      - to: run-search
        condition: >
          The user has provided at least one preference, or has said
          "anything" / "no preference".

  - id: run-search
    tools: cars:search_cars
    tool_instruction: >
      Call search_cars with the filters the user provided. Pass null /
      omit fields the user did not mention. Do not invent constraints.
    transitions:
      - to: present-results

  - id: present-results
    chat_state: >
      Summarise the matching cars in a compact list — one line per car
      with make, model, category, transmission, and daily price in EUR.
      End by asking if the user wants to book one.
```

## Top-level fields

| Field         | Type                      | Required            | Meaning                                                                                                                                                                       |
| ------------- | ------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`       | string                    | yes                 | Display name in the platform UI, traces, and logs.                                                                                                                            |
| `conditions`  | string or list of strings | yes (≥ 1 non-empty) | When the routine activates. Evaluated like policy conditions; the routine activates when **any** condition matches.                                                           |
| `entry`       | string                    | yes                 | Id of the node where execution starts. Must match a declared node id.                                                                                                         |
| `nodes`       | list of node objects      | yes (≥ 1)           | The graph (below). Each node is declared exactly once; node ids must be unique.                                                                                               |
| `id`          | string                    | no                  | Optional in-document id. Identity actually comes from the catalog name the document is published under — that name is what the manifest's `context.routines[].id` references. |
| `description` | string                    | no                  | Long-form purpose. Not used for matching.                                                                                                                                     |
| `policies`    | list of policy objects    | no                  | Routine-scoped policies (each requires an explicit `id`) — see [Policies](/agents/concepts/policies.md#scoping-agent-wide-vs-routine-scoped).                                 |
| `autonomous`  | object                    | no                  | Makes the routine triggerable as a typed automation — see [Autonomous routines](/agents/concepts/autonomous-routines.md).                                                     |

## Node fields

| Field                     | Type                       | Meaning                                                                                                                                                                              |
| ------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`                      | string                     | Unique within the routine. Required. Referenced by `entry` and by `transitions[].to`.                                                                                                |
| `description`             | string                     | Author note; surfaced in traces, never shown to the customer.                                                                                                                        |
| `tools`                   | string or list             | TOOL node: tool id(s) to call, `service:tool` form (a bare string is normalised to a one-element list).                                                                              |
| `tool_instruction`        | string                     | TOOL node: how to call the tool(s) — parameter mapping, derivation rules. Never shown to the customer. Requires `tools`.                                                             |
| `chat_state`              | string                     | CHAT node: instruction for what the agent should say. Supports `${macro-id}` interpolation — see [Glossaries & macros](/agents/concepts/glossaries-and-macros.md#macros).            |
| `transitions`             | list of `{to, condition?}` | Outbound edges. **Omitted/empty = terminal node.** With 2+ entries, every transition requires a `condition`.                                                                         |
| `think` / `output_schema` | string / object            | **Autonomous routines only** — the typed-inference (THINK) node. Not used in conversational routines; see [Autonomous routines](/agents/concepts/autonomous-routines.md#node-types). |

Machine-validated rules (enforced by the published JSON Schema): unique node ids; `entry` and every `transitions[].to` must name declared nodes; `tools` is mutually exclusive with `chat_state`; `tool_instruction` requires `tools`; a node must carry an action (`tools` or `chat_state`) **or** at least one transition; 2+ transitions ⇒ all conditioned; malformed `${…}` macro tokens in `chat_state` are rejected. (The schema also defines the `think`/`output_schema` node used by [autonomous routines](/agents/concepts/autonomous-routines.md).)

## Node types: read this first

A conversational routine is built from **three node types**. Each node is exactly one of them, determined by its action field:

| Node type                     | Set by                                      | What it is                                                                                                                                                 |
| ----------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **CHAT**                      | `chat_state`                                | Speaks to the customer. Completes when the agent sends a message fulfilling the instruction. May interpolate `${macro-id}`.                                |
| **TOOL**                      | `tools` (+ `tool_instruction`)              | Calls one or more tools. Completes when the tool executes — it produces no message of its own.                                                             |
| **Routing-only** (the *fork*) | no action field, 2+ conditional transitions | A pure branch point — no tool call, no message. The engine evaluates the outgoing conditions and takes the matching path. This is how a routine **forks**. |

> A fourth node type — **THINK** (typed inference) — exists only for [autonomous routines](/agents/concepts/autonomous-routines.md#node-types). It has no customer-facing output, so it is **not used in conversational routines**; if you need a routine to reason over typed data, that's an autonomous routine.

> ⚠️ **The classic bug.** `tools` and `chat_state` on the same node is rejected by the schema — and for good reason: "call the handoff tool *and* tell the customer they're being transferred" must be **two nodes**. A tool node's customer-facing output always belongs in a follow-up chat node.

## Runtime semantics by node kind

### CHAT node: completes when the agent speaks

The engine generates a message fulfilling the `chat_state` instruction; that message **ends the turn**. If the outbound transition's condition depends on the customer's answer, the routine waits on the customer before advancing. Two CHAT nodes can never run in the same turn.

### TOOL node: completes when the tool executes

The engine calls the tool(s) per `tool_instruction`, appends the results to history, and immediately re-evaluates — walking the node's transitions **within the same turn**. Chains of TOOL nodes execute back-to-back without customer interaction.

(Need a node that reasons over typed data instead of speaking or calling a tool? That's a **THINK** node, which lives in [autonomous routines](/agents/concepts/autonomous-routines.md#node-types) — not in conversational routines.)

### Routing-only node (fork): completes immediately

No action — just conditional transitions. The engine evaluates the outgoing conditions and takes the matching branch. This is the routine's **fork**: use one wherever the flow splits on a decision rather than on a tool call or a message.

```yaml
  - id: status-route
    transitions:
      - to: active-path
        condition: "account status is ACTIVE"
      - to: suspended-path
        condition: "account status is SUSPENDED"
```

## Transitions, terminals, and movement

* A transition's `condition` decides when that edge is followed. A node with exactly **one** transition may omit the condition (unconditional); a node with **2+** transitions must condition every one.
* **No `transitions` = terminal node.** When a terminal node completes, the routine is done. (In autonomous routines, terminal nodes must call `built-in:emit_output`.)
* **Fan-in and cycles are allowed** — any node id can be the target of multiple transitions, including loops back to earlier nodes ("ask again until the data validates").
* The engine can **backtrack**: if the customer revisits an earlier topic ("actually, change the dates"), evaluation can re-enter a previous node rather than forcing forward-only movement.
* Activation and advancement decisions are evaluation-model calls — see [Conversation lifecycle](/agents/concepts/conversation-lifecycle.md).

## Referencing from the manifest

```yaml
agent_config:
  context:
    routines:
      - id: car-search
        version: 1
      - id: book-a-car
        version: 1
```

Pins are exact versions from the platform catalog. At boot, the server also pre-computes behavioural metadata for every routine (node reachability, customer-dependence); on a cold cache this is the slow part of startup — see [Startup evaluation](/agents/concepts/startup-evaluation.md).

## See also

* [Authoring routines](/agents/guides/authoring-routines.md) — patterns, anti-patterns, checklist
* [Autonomous routines](/agents/concepts/autonomous-routines.md) — typed input/output automations
* [Glossaries & macros](/agents/concepts/glossaries-and-macros.md) — `${macro-id}` interpolation
* [Priorities](/agents/concepts/priorities.md) — when routines compete with each other or with policies


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.interactive.ai/agents/concepts/routines.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
