Build a Basic ReAct Agent
ReAct means Reason → Act → Observe. The agent first decides what to do, calls a tool, turns the tool result into an observation, and then answers from that observation.
This tutorial keeps the tool simple: it reads one environment variable with
env://process, so you can run the example without MCP or network setup.
Full source: ../../../tutorials/react.as
1. The Complete Program
Create react.as or open the repository copy at tutorials/react.as:
import llm Qwen from "ollama://localhost:11434/qwen3.6"
import tool Env from "env://process"
main agent BasicReAct {
model Qwen
role "Diagnostic assistant"
description "Answer one question with a minimal Reason-Act-Observe flow."
main func(input {
question: string
}) {
env_name = "USER"
thought = reason(input.question, env_name)
action = Env.get({
name: env_name
})
observation = observe(input.question, env_name, action)
answer(input.question, thought, observation)
}
func reason(question, env_name) {
use question as "question"
use env_name as "planned tool input"
generate({ input: "Explain why this environment variable may help answer the question", max_output: 300 }) -> {
why
}
}
func observe(question, env_name, action) {
use question as "question"
use env_name as "environment variable"
use action.value as "environment value"
generate({ input: "Turn the tool result into a useful observation", max_output: 400 }) -> {
facts: list[string]
value_found: boolean
}
}
func answer(question, thought, observation) {
use question as "question"
use thought.why as "reasoning note"
use observation.facts max 1k as "observed facts"
use observation.value_found as "value found"
generate({ input: "Answer using only the observation", max_output: 500 }) -> {
answer
confidence
}
}
}
2. Reason
reason is the planning step. It does not call a tool. It looks at the
question and the planned tool input, then explains why that input may help.
The important part is that use question is explicit. The function may receive
other values later, but only selected values enter this model call.
3. Act
The action is the tool call:
action = Env.get({
name: env_name
})
The model does not call the tool directly. Your AgentScript program calls it
with structured arguments. That keeps the boundary between model output and host
capabilities visible. In this minimal tutorial, the tool input is fixed to
"USER" so the example stays runnable with --mock.
4. Observe
observe converts the raw tool result into a model-friendly observation. This
keeps the final answer from depending on an unprocessed host result.
5. Answer
The final step uses the original question, the reasoning note, and the observed
facts. It does not see every local variable by default; it sees only the values
selected with use.
6. Run It
Run with mock model output:
agentscript tutorials/react.as --mock --input '{"question":"Which environment variable identifies my shell user?"}'
Print the trace to see the Reason → Act → Observe shape:
agentscript tutorials/react.as --mock --trace --input '{"question":"Which environment variable identifies my shell user?"}'
To use a real model, keep the same file and run without --mock after your
chosen model provider is configured.