# Your First ReAct Agent

> Applies to: ChengOS v0.1.0+ ｜ Last verified: 2026-08-12 ｜ Source: `crates/cheng-nodes/src/nodes/builtin/agent`, `deploy/workflow-templates/tools-user/`, `crates/cheng-nodes/src/nodes/builtin/tools/tool_hub`

[Your first workflow](/docs/quickstart-first-workflow) built a graph where you decided the
order. This one builds an **agent**: you give it a goal and some tools, and it decides the order
at runtime.

About fifteen minutes. You need a running installation and a configured model provider.

## When an agent is the right answer

An agent costs more, runs slower, and is less predictable than a plain graph. It earns that when
the steps genuinely depend on what earlier steps find — "look through these files and tell me
which ones mention X" has no fixed sequence, because the agent cannot know which file to open
second until it has read the first.

If you already know the sequence, draw the graph.

## The shape

Six nodes. This is the `tools-user` template's structure, and it is the standard agent layout:

```text
chat/input ─────────────────► agent/react_agent ──► chat/output
                                 ▲       ▲
                  ai/llm_config ─┘       └─ tools/tool_hub ──► tools/file_ops_hub
```

- **`chat/input`** receives the user's message.
- **`ai/llm_config`** holds the model choice, wired into the agent rather than typed into it —
  so one config node can serve several nodes.
- **`agent/react_agent`** is the loop.
- **`tools/tool_hub`** presents many tools behind one stable function.
- **`tools/file_ops_hub`** is the actual capability, in this example file operations.
- **`chat/output`** returns the answer.

## Step 1 — Start from the template

Rather than building from scratch, install the `tools-user` template — see
[Workflow Templates](/docs/editor-templates). You get the layout above, already wired, and can
read it before you change it. Open it in the editor.

If you prefer to build it by hand, drag the six nodes on and connect them as drawn: input to the
agent's task input, `llm_config` to the agent's `llm_config`, the tool hub to the agent's
`tools` port, and the agent's answer to `chat/output`.

## Step 2 — Configure the model

Select `ai/llm_config` and pick a provider and model.

One thing to check before going further: **the agent's `use_function_calling` defaults to
`true`, and not every provider declares native tool calling.** In the shipped
`providers.toml`, Anthropic and Ollama do **not** declare `native_tool_calling`, so an agent
with `use_function_calling = true` will not work on those. Pick a provider that declares it —
see [LLM & Model Configuration](/docs/config-llm-models). This is the single most common reason
a first agent does nothing.

## Step 3 — Give it tools

Select `tools/file_ops_hub` and turn on the operations you want it to have. Read operations are
safe to enable; leave writes off for a first run.

Then look at `tools/tool_hub`. Its job is to put many tools behind **one** function the model
calls, instead of growing the model's tool list until the list itself eats the context window.
For a first agent the defaults are fine.

## Step 4 — Set the iteration budget

Select `agent/react_agent`:

| Setting | For a first agent |
|---|---|
| `max_iterations` | `10` (the default) is plenty |
| `use_function_calling` | Leave `true` — see step 2 |
| `use_llm_evaluation` | Leave `false` for now |
| `task_run_mode` | `short` (the default) |

`short` mode means: when the iteration budget runs out, **pause and ask you** rather than
stopping silently. That is what you want while learning — an agent that quietly gives up is much
harder to debug than one that says it ran out of room.

## Step 5 — Run it

Use the chat panel beside the canvas and ask for something that genuinely requires looking
around, for example:

```
List the files in the workspace and tell me which one is the largest.
```

Watch the run. Each iteration renders as its own group: the reasoning, the tool call with its
arguments, the result, then the next iteration. This is the part worth staring at — you are
seeing the agent's actual decisions, not a summary of them.

## Step 6 — Read the trace

The agent returns more than an answer:

| Output | Use it for |
|---|---|
| `final_answer` | The result |
| `trace` | Every reasoning step and tool call |
| `iterations_used` | How much of the budget it needed |
| `total_tokens` | Cost |
| `success` | Whether it completed |

`iterations_used` is the number to watch. Hitting `max_iterations` every time means the task is
too big for the budget or the tools are wrong for it — raising the ceiling usually treats the
symptom.

## When it goes wrong

| Symptom | Cause |
|---|---|
| The agent does nothing, or replies without calling tools | The provider does not support native tool calling — see step 2 |
| It calls a tool with nonsense arguments | The tool description is unclear; a [skill](/docs/agent-skills-system) with usage guidance fixes this better than prompt tweaks |
| It loops on the same call | The tool is returning an error the agent cannot interpret; check the trace for the actual result text |
| It stops too early | Its completion judgment is wrong; try `use_llm_evaluation = true` |
| It runs forever | You are in `long` mode without progress limits, or the task has no terminal state |

## Where to go next

Once the loop works, the useful upgrades are:

1. **Better tools.** An agent is only as good as what it can call. Add
   [MCP servers](/docs/agent-mcp-integration) or [skills](/docs/agent-skills-system).
2. **Approval gates.** Before enabling write operations, put an
   [approval gate](/docs/exec-approvals-reviews) in front of them so you confirm each dangerous
   action.
3. **`long` mode.** For multi-step autonomous work, switch `task_run_mode` to `long`, which
   renews the agent's budget as long as it is making progress.

## Next steps

- [ReAct Agent Guide](/docs/agent-react-guide) — every setting in depth.
- [Tool Discovery & Tool Hub](/docs/agent-tools-and-hub) — scaling past a handful of tools.
- [Approvals & Human Review](/docs/exec-approvals-reviews) — before you enable writes.
