ReAct Agent
Overview
ReAct Agent is a general paradigm that combines reasoning and action capabilities to solve complex tasks. Leveraging this paradigm, the user only needs to specify the goal with prompt and provide available tools, and the LLM will decide how to achieve the goal and take actions autonomously.
For guidance on choosing Java or Python, see Should I choose Java or Python?.
The snippets on this page are fragments that each focus on a single concept. For an end-to-end runnable walkthrough, see the ReAct Agent Quickstart and the full source:
react_agent_example.py(Python) andReActAgentExample.java(Java).
The snippets below assume the following imports:
Python
from pydantic import BaseModel
from pyflink.common.typeinfo import BasicTypeInfo, RowTypeInfo
from flink_agents.api.agents.react_agent import ReActAgent
from flink_agents.api.chat_message import ChatMessage, MessageRole
from flink_agents.api.execution_environment import AgentsExecutionEnvironment
from flink_agents.api.prompts.prompt import Prompt
from flink_agents.api.resource import ResourceDescriptor, ResourceName, ResourceType
from flink_agents.api.tools.tool import ToolJava
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.flink.agents.api.AgentsExecutionEnvironment;
import org.apache.flink.agents.api.agents.ReActAgent;
import org.apache.flink.agents.api.chat.messages.ChatMessage;
import org.apache.flink.agents.api.chat.messages.MessageRole;
import org.apache.flink.agents.api.prompt.Prompt;
import org.apache.flink.agents.api.resource.ResourceDescriptor;
import org.apache.flink.agents.api.resource.ResourceName;
import org.apache.flink.agents.api.resource.ResourceType;
import org.apache.flink.agents.api.tools.Tool;
import org.apache.flink.api.common.typeinfo.BasicTypeInfo;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import java.util.Arrays;
import java.util.List;ReAct Agent Example
Python
my_react_agent = ReActAgent(
chat_model=chat_model_descriptor,
prompt=my_prompt,
output_schema=MyBaseModelDataType, # or output_schema=my_row_type_info
)Java
ReActAgent myReActAgent =
new ReActAgent(
chatModelDescriptor,
myPrompt,
MyBaseModelDataType.class
// or myRowTypeInfo
);Initialize Arguments
Chat Model
User should specify the chat model used in the ReAct Agent.
We use ResourceDescriptor to describe the chat model, includes chat model type and chat model arguments. See Chat Model for more details.
Python
chat_model_descriptor = ResourceDescriptor(
clazz=ResourceName.ChatModel.OLLAMA_SETUP,
connection="my_ollama_connection",
model="qwen3:8b",
tools=["my_tool1", "my_tool2"],
)Java
ResourceDescriptor chatModelDescriptor =
ResourceDescriptor.Builder.newBuilder(ResourceName.ChatModel.OLLAMA_SETUP)
.addInitialArgument("connection", "myOllamaConnection")
.addInitialArgument("model", "qwen3:8b")
.addInitialArgument(
"tools", List.of("myTool1", "myTool2"))
.build();The tools listed in
tools=[...]must be registered on theAgentsExecutionEnvironmentbefore the agent runs, using a name that matches the entry in the list — otherwise the agent fails at runtime with a “resource not found” error.
Register the referenced tools (this can also be done with a YAML file — see Tool Use for the full guide):
Python
agents_env.add_resource(
"my_tool1", ResourceType.TOOL, Tool.from_callable(my_tool1)
)Java
agentsEnv.addResource(
"myTool1",
ResourceType.TOOL,
Tool.fromMethod(MyAgentExample.class.getMethod("myTool1", String.class)));Prompt
User can provide prompt to instruct agent.
A typical prompt contains two messages: a SYSTEM message that tells the agent what to do (and gives input and output examples), and a USER message that describes how to convert the input element into a text string. This is a recommended pattern, not a strict requirement — the agent uses all messages in the prompt, and the SYSTEM message is optional (if it is omitted, the framework still prepends the output-schema instruction automatically).
Python
system_prompt_str = """
Analyze
...
Example input format:
...
Ensure your response can be parsed by Python JSON, using this format as an example:
...
"""
# Prompt for review analysis react agent.
my_prompt = Prompt.from_messages(
messages=[
ChatMessage(
role=MessageRole.SYSTEM,
content=system_prompt_str,
),
# For react agent, if the input element is not primitive types,
# framework will deserialize input element to dict and fill the prompt.
# Note, the input element should be primitive types, BaseModel or Row.
ChatMessage(
role=MessageRole.USER,
content="""
"id": {id},
"review": {review}
""",
),
],
)Java
String systemPromptString =
"Analyze ..."
+ "Example input format:\n"
+ "..."
+ "Ensure your response can be parsed by Java JSON, using this format as an example:\n"
+ "...";
// Prompt for review analysis react agent.
Prompt myPrompt = Prompt.fromMessages(
Arrays.asList(
new ChatMessage(MessageRole.SYSTEM, systemPromptString),
new ChatMessage(
MessageRole.USER,
"{\"id\": \"{id}\",\n" + "\"review\": \"{review}\"}")));The USER-message template uses {placeholder} syntax. The placeholder names are derived from the agent input element, and depend on its type:
- Primitive (
int,str,float,bool, …): a single{input}placeholder. Row: one placeholder per field name (row.as_dict()keys in Python,row.getFieldNames()in Java).dict/Map: the keys are used directly.BaseModel(Python) / Pojo (Java): the object’s field names.
For example, the prompt snippet above uses {id} and {review} because the input element’s fields are named id and review. A placeholder whose name does not match a field is left unchanged in the text.
If the input element is primitive types, like int, str and so on, the second message should be
Python
ChatMessage(
role=MessageRole.USER,
content="{input}"
)Java
new ChatMessage(MessageRole.USER, "{input}")See Prompt for more details.
Output Schema
User can set output schema to configure the ReAct Agent output type. If output schema is set, the ReAct Agent will deserialize the llm response to expected type.
The output schema should be a BaseModel subclass (Python) / a Pojo class (Java), or a RowTypeInfo (both).
Python
class MyBaseModelDataType(BaseModel):
id: str
score: int
reasons: list[str]
# Currently, for RowTypeInfo, only support BasicType fields.
my_row_type_info = RowTypeInfo(
[BasicTypeInfo.STRING_TYPE_INFO(), BasicTypeInfo.INT_TYPE_INFO()],
["id", "score"],
)Java
@JsonSerialize
@JsonDeserialize
public static class MyBaseModelDataType {
private final String id;
private final int score;
private final List<String> reasons;
@JsonCreator
public MyBaseModelDataType(
@JsonProperty("id") String id,
@JsonProperty("score") int score,
@JsonProperty("reasons") List<String> reasons) {
this.id = id;
this.score = score;
this.reasons = reasons;
}
public MyBaseModelDataType() {
id = null;
score = 0;
reasons = List.of();
}
public String getId() {
return id;
}
public int getScore() {
return score;
}
public List<String> getReasons() {
return reasons;
}
@Override
public String toString() {
return String.format(
"MyBaseModelDataType{id='%s', score=%d, reasons=%s}", id, score, reasons);
}
}
// Currently, for RowTypeInfo, only support BasicType fields.
RowTypeInfo myRowTypeInfo =
new RowTypeInfo(
new TypeInformation[] {
BasicTypeInfo.STRING_TYPE_INFO, BasicTypeInfo.INT_TYPE_INFO
},
new String[] {"id", "score"});评论
登录后参与评论
KnowForge