---
name: spring-ai-alibaba-react-agent
description: Build or update Java and Spring Boot agents with Spring AI Alibaba ReactAgent using the official Agents tutorial patterns, including ChatModel setup, ToolCallback tools, systemPrompt or instruction design, call or invoke usage, RunnableConfig threadId and metadata, outputType or outputSchema, MemorySaver, hooks, interceptors, and streaming-oriented agent integration. Use when requests mention Spring AI Alibaba, ReactAgent, RunnableConfig, ToolContext, MemorySaver, outputType, outputSchema, hooks, interceptors, or implementing agent workflows on the Spring stack.
---

# Spring AI Alibaba ReactAgent

Use this skill to implement or refactor Spring AI Alibaba agent code around `ReactAgent`. Keep the implementation aligned with the official Agents tutorial, and read [references/agents.md](./references/agents.md) when exact API shape, invocation mode, or advanced capability details matter.

## Workflow

1. Build the smallest agent that solves the request.
Start from `ChatModel + ReactAgent + call(...)`. Add tools, memory, state access, hooks, or streaming only when the request needs them.

2. Configure the model first.
Create the provider `ChatModel` explicitly. If the project already has a model bean, reuse it instead of introducing a second configuration style.

3. Add tools only when the agent must act.
Use `FunctionToolCallback` with explicit tool names and short descriptions. If the tool needs request-scoped metadata, read it through `ToolContext` from `RunnableConfig`.

4. Choose prompt style deliberately.
Use `systemPrompt(...)` for a compact role definition. Use `instruction(...)` for a longer task-specific directive.

5. Pick the invocation mode based on the caller contract.
Use `call(...)` for the final answer. Use `invoke(...)` when the caller needs `OverAllState`, message history, or custom state.

6. Add conversation memory deliberately.
Use `MemorySaver` and reuse the same `threadId` in `RunnableConfig` for multi-turn chat. For production, prefer a persistent saver.

7. Shape outputs only when the consumer requires it.
Prefer `outputType(...)` for stable Java contracts. Use `outputSchema(...)` when a schema-like response contract is more practical.

8. Add hooks, interceptors, or streaming only after the basic path works.
Use `ModelCallLimitHook` to cap loops, interceptors for tool or prompt customization, and wrap streaming output in your own application contract.

## Implementation Defaults

- Keep API keys out of source code. Prefer environment variables and Spring properties.
- Keep tools narrow and explicit. Tool names and descriptions directly affect model behavior.
- Prefer the shortest prompt that enforces the needed behavior.
- Pass request metadata through `RunnableConfig.addMetadata(...)` instead of globals.
- Reuse `threadId` for multi-turn continuity. Change it for a fresh session.
- Keep the controller thin and push agent assembly or orchestration into the service layer.
- Do not expose raw low-level graph streaming objects directly to external callers unless the project already standardizes on them.

## Minimal Assembly Pattern

```java
DashScopeApi dashScopeApi = DashScopeApi.builder()
    .apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
    .build();

ChatModel chatModel = DashScopeChatModel.builder()
    .dashScopeApi(dashScopeApi)
    .build();

ReactAgent agent = ReactAgent.builder()
    .name("my_agent")
    .model(chatModel)
    .build();

AssistantMessage response = agent.call("杭州的天气怎么样？");
System.out.println(response.getText());
```

## Decision Rules

- If the caller only needs the final assistant text, use `call(...)`.
- If the caller needs state, messages, or custom graph values, use `invoke(...)`.
- If follow-up requests must retain context, add `.saver(...)` and reuse `threadId`.
- If the agent must use runtime business context, pass it via `RunnableConfig` and read it through `ToolContext`.
- If the output must map to a stable Java contract, prefer `outputType(...)`.
- If the agent may over-iterate, add `ModelCallLimitHook`.
- If the request is for HTTP streaming, keep the agent logic in the service layer and convert framework output to a stable SSE or chunked response shape.

## References

- Read [references/agents.md](./references/agents.md) for the extracted official tutorial guidance on agent assembly, invocation, memory, hooks, interceptors, and streaming-related decisions.
